]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/iD/iD.js
Merge remote-tracking branch 'upstream/pull/3446'
[rails.git] / vendor / assets / iD / iD.js
1 (function () {
2
3         var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
4
5         var check = function (it) {
6           return it && it.Math == Math && it;
7         };
8
9         // https://github.com/zloirock/core-js/issues/86#issuecomment-115759028
10         var global$1o =
11           // eslint-disable-next-line es/no-global-this -- safe
12           check(typeof globalThis == 'object' && globalThis) ||
13           check(typeof window == 'object' && window) ||
14           // eslint-disable-next-line no-restricted-globals -- safe
15           check(typeof self == 'object' && self) ||
16           check(typeof commonjsGlobal == 'object' && commonjsGlobal) ||
17           // eslint-disable-next-line no-new-func -- fallback
18           (function () { return this; })() || Function('return this')();
19
20         var objectGetOwnPropertyDescriptor = {};
21
22         var fails$V = function (exec) {
23           try {
24             return !!exec();
25           } catch (error) {
26             return true;
27           }
28         };
29
30         var fails$U = fails$V;
31
32         // Detect IE8's incomplete defineProperty implementation
33         var descriptors = !fails$U(function () {
34           // eslint-disable-next-line es/no-object-defineproperty -- required for testing
35           return Object.defineProperty({}, 1, { get: function () { return 7; } })[1] != 7;
36         });
37
38         var fails$T = fails$V;
39
40         var functionBindNative = !fails$T(function () {
41           var test = (function () { /* empty */ }).bind();
42           // eslint-disable-next-line no-prototype-builtins -- safe
43           return typeof test != 'function' || test.hasOwnProperty('prototype');
44         });
45
46         var NATIVE_BIND$4 = functionBindNative;
47
48         var call$q = Function.prototype.call;
49
50         var functionCall = NATIVE_BIND$4 ? call$q.bind(call$q) : function () {
51           return call$q.apply(call$q, arguments);
52         };
53
54         var objectPropertyIsEnumerable = {};
55
56         var $propertyIsEnumerable$2 = {}.propertyIsEnumerable;
57         // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
58         var getOwnPropertyDescriptor$5 = Object.getOwnPropertyDescriptor;
59
60         // Nashorn ~ JDK8 bug
61         var NASHORN_BUG = getOwnPropertyDescriptor$5 && !$propertyIsEnumerable$2.call({ 1: 2 }, 1);
62
63         // `Object.prototype.propertyIsEnumerable` method implementation
64         // https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
65         objectPropertyIsEnumerable.f = NASHORN_BUG ? function propertyIsEnumerable(V) {
66           var descriptor = getOwnPropertyDescriptor$5(this, V);
67           return !!descriptor && descriptor.enumerable;
68         } : $propertyIsEnumerable$2;
69
70         var createPropertyDescriptor$7 = function (bitmap, value) {
71           return {
72             enumerable: !(bitmap & 1),
73             configurable: !(bitmap & 2),
74             writable: !(bitmap & 4),
75             value: value
76           };
77         };
78
79         var NATIVE_BIND$3 = functionBindNative;
80
81         var FunctionPrototype$3 = Function.prototype;
82         var bind$g = FunctionPrototype$3.bind;
83         var call$p = FunctionPrototype$3.call;
84         var uncurryThis$Y = NATIVE_BIND$3 && bind$g.bind(call$p, call$p);
85
86         var functionUncurryThis = NATIVE_BIND$3 ? function (fn) {
87           return fn && uncurryThis$Y(fn);
88         } : function (fn) {
89           return fn && function () {
90             return call$p.apply(fn, arguments);
91           };
92         };
93
94         var uncurryThis$X = functionUncurryThis;
95
96         var toString$n = uncurryThis$X({}.toString);
97         var stringSlice$c = uncurryThis$X(''.slice);
98
99         var classofRaw$1 = function (it) {
100           return stringSlice$c(toString$n(it), 8, -1);
101         };
102
103         var global$1n = global$1o;
104         var uncurryThis$W = functionUncurryThis;
105         var fails$S = fails$V;
106         var classof$e = classofRaw$1;
107
108         var Object$5 = global$1n.Object;
109         var split$4 = uncurryThis$W(''.split);
110
111         // fallback for non-array-like ES3 and non-enumerable old V8 strings
112         var indexedObject = fails$S(function () {
113           // throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
114           // eslint-disable-next-line no-prototype-builtins -- safe
115           return !Object$5('z').propertyIsEnumerable(0);
116         }) ? function (it) {
117           return classof$e(it) == 'String' ? split$4(it, '') : Object$5(it);
118         } : Object$5;
119
120         var global$1m = global$1o;
121
122         var TypeError$p = global$1m.TypeError;
123
124         // `RequireObjectCoercible` abstract operation
125         // https://tc39.es/ecma262/#sec-requireobjectcoercible
126         var requireObjectCoercible$e = function (it) {
127           if (it == undefined) throw TypeError$p("Can't call method on " + it);
128           return it;
129         };
130
131         // toObject with fallback for non-array-like ES3 strings
132         var IndexedObject$4 = indexedObject;
133         var requireObjectCoercible$d = requireObjectCoercible$e;
134
135         var toIndexedObject$d = function (it) {
136           return IndexedObject$4(requireObjectCoercible$d(it));
137         };
138
139         // `IsCallable` abstract operation
140         // https://tc39.es/ecma262/#sec-iscallable
141         var isCallable$r = function (argument) {
142           return typeof argument == 'function';
143         };
144
145         var isCallable$q = isCallable$r;
146
147         var isObject$s = function (it) {
148           return typeof it == 'object' ? it !== null : isCallable$q(it);
149         };
150
151         var global$1l = global$1o;
152         var isCallable$p = isCallable$r;
153
154         var aFunction = function (argument) {
155           return isCallable$p(argument) ? argument : undefined;
156         };
157
158         var getBuiltIn$b = function (namespace, method) {
159           return arguments.length < 2 ? aFunction(global$1l[namespace]) : global$1l[namespace] && global$1l[namespace][method];
160         };
161
162         var uncurryThis$V = functionUncurryThis;
163
164         var objectIsPrototypeOf = uncurryThis$V({}.isPrototypeOf);
165
166         var getBuiltIn$a = getBuiltIn$b;
167
168         var engineUserAgent = getBuiltIn$a('navigator', 'userAgent') || '';
169
170         var global$1k = global$1o;
171         var userAgent$7 = engineUserAgent;
172
173         var process$4 = global$1k.process;
174         var Deno = global$1k.Deno;
175         var versions = process$4 && process$4.versions || Deno && Deno.version;
176         var v8 = versions && versions.v8;
177         var match, version$1;
178
179         if (v8) {
180           match = v8.split('.');
181           // in old Chrome, versions of V8 isn't V8 = Chrome / 10
182           // but their correct versions are not interesting for us
183           version$1 = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]);
184         }
185
186         // BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
187         // so check `userAgent` even if `.v8` exists, but 0
188         if (!version$1 && userAgent$7) {
189           match = userAgent$7.match(/Edge\/(\d+)/);
190           if (!match || match[1] >= 74) {
191             match = userAgent$7.match(/Chrome\/(\d+)/);
192             if (match) version$1 = +match[1];
193           }
194         }
195
196         var engineV8Version = version$1;
197
198         /* eslint-disable es/no-symbol -- required for testing */
199
200         var V8_VERSION$3 = engineV8Version;
201         var fails$R = fails$V;
202
203         // eslint-disable-next-line es/no-object-getownpropertysymbols -- required for testing
204         var nativeSymbol = !!Object.getOwnPropertySymbols && !fails$R(function () {
205           var symbol = Symbol();
206           // Chrome 38 Symbol has incorrect toString conversion
207           // `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
208           return !String(symbol) || !(Object(symbol) instanceof Symbol) ||
209             // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
210             !Symbol.sham && V8_VERSION$3 && V8_VERSION$3 < 41;
211         });
212
213         /* eslint-disable es/no-symbol -- required for testing */
214
215         var NATIVE_SYMBOL$3 = nativeSymbol;
216
217         var useSymbolAsUid = NATIVE_SYMBOL$3
218           && !Symbol.sham
219           && typeof Symbol.iterator == 'symbol';
220
221         var global$1j = global$1o;
222         var getBuiltIn$9 = getBuiltIn$b;
223         var isCallable$o = isCallable$r;
224         var isPrototypeOf$9 = objectIsPrototypeOf;
225         var USE_SYMBOL_AS_UID$1 = useSymbolAsUid;
226
227         var Object$4 = global$1j.Object;
228
229         var isSymbol$6 = USE_SYMBOL_AS_UID$1 ? function (it) {
230           return typeof it == 'symbol';
231         } : function (it) {
232           var $Symbol = getBuiltIn$9('Symbol');
233           return isCallable$o($Symbol) && isPrototypeOf$9($Symbol.prototype, Object$4(it));
234         };
235
236         var global$1i = global$1o;
237
238         var String$6 = global$1i.String;
239
240         var tryToString$5 = function (argument) {
241           try {
242             return String$6(argument);
243           } catch (error) {
244             return 'Object';
245           }
246         };
247
248         var global$1h = global$1o;
249         var isCallable$n = isCallable$r;
250         var tryToString$4 = tryToString$5;
251
252         var TypeError$o = global$1h.TypeError;
253
254         // `Assert: IsCallable(argument) is true`
255         var aCallable$a = function (argument) {
256           if (isCallable$n(argument)) return argument;
257           throw TypeError$o(tryToString$4(argument) + ' is not a function');
258         };
259
260         var aCallable$9 = aCallable$a;
261
262         // `GetMethod` abstract operation
263         // https://tc39.es/ecma262/#sec-getmethod
264         var getMethod$7 = function (V, P) {
265           var func = V[P];
266           return func == null ? undefined : aCallable$9(func);
267         };
268
269         var global$1g = global$1o;
270         var call$o = functionCall;
271         var isCallable$m = isCallable$r;
272         var isObject$r = isObject$s;
273
274         var TypeError$n = global$1g.TypeError;
275
276         // `OrdinaryToPrimitive` abstract operation
277         // https://tc39.es/ecma262/#sec-ordinarytoprimitive
278         var ordinaryToPrimitive$1 = function (input, pref) {
279           var fn, val;
280           if (pref === 'string' && isCallable$m(fn = input.toString) && !isObject$r(val = call$o(fn, input))) return val;
281           if (isCallable$m(fn = input.valueOf) && !isObject$r(val = call$o(fn, input))) return val;
282           if (pref !== 'string' && isCallable$m(fn = input.toString) && !isObject$r(val = call$o(fn, input))) return val;
283           throw TypeError$n("Can't convert object to primitive value");
284         };
285
286         var shared$5 = {exports: {}};
287
288         var isPure = false;
289
290         var global$1f = global$1o;
291
292         // eslint-disable-next-line es/no-object-defineproperty -- safe
293         var defineProperty$d = Object.defineProperty;
294
295         var setGlobal$3 = function (key, value) {
296           try {
297             defineProperty$d(global$1f, key, { value: value, configurable: true, writable: true });
298           } catch (error) {
299             global$1f[key] = value;
300           } return value;
301         };
302
303         var global$1e = global$1o;
304         var setGlobal$2 = setGlobal$3;
305
306         var SHARED = '__core-js_shared__';
307         var store$4 = global$1e[SHARED] || setGlobal$2(SHARED, {});
308
309         var sharedStore = store$4;
310
311         var store$3 = sharedStore;
312
313         (shared$5.exports = function (key, value) {
314           return store$3[key] || (store$3[key] = value !== undefined ? value : {});
315         })('versions', []).push({
316           version: '3.21.0',
317           mode: 'global',
318           copyright: '© 2014-2022 Denis Pushkarev (zloirock.ru)',
319           license: 'https://github.com/zloirock/core-js/blob/v3.21.0/LICENSE',
320           source: 'https://github.com/zloirock/core-js'
321         });
322
323         var global$1d = global$1o;
324         var requireObjectCoercible$c = requireObjectCoercible$e;
325
326         var Object$3 = global$1d.Object;
327
328         // `ToObject` abstract operation
329         // https://tc39.es/ecma262/#sec-toobject
330         var toObject$i = function (argument) {
331           return Object$3(requireObjectCoercible$c(argument));
332         };
333
334         var uncurryThis$U = functionUncurryThis;
335         var toObject$h = toObject$i;
336
337         var hasOwnProperty$3 = uncurryThis$U({}.hasOwnProperty);
338
339         // `HasOwnProperty` abstract operation
340         // https://tc39.es/ecma262/#sec-hasownproperty
341         var hasOwnProperty_1 = Object.hasOwn || function hasOwn(it, key) {
342           return hasOwnProperty$3(toObject$h(it), key);
343         };
344
345         var uncurryThis$T = functionUncurryThis;
346
347         var id$2 = 0;
348         var postfix = Math.random();
349         var toString$m = uncurryThis$T(1.0.toString);
350
351         var uid$5 = function (key) {
352           return 'Symbol(' + (key === undefined ? '' : key) + ')_' + toString$m(++id$2 + postfix, 36);
353         };
354
355         var global$1c = global$1o;
356         var shared$4 = shared$5.exports;
357         var hasOwn$l = hasOwnProperty_1;
358         var uid$4 = uid$5;
359         var NATIVE_SYMBOL$2 = nativeSymbol;
360         var USE_SYMBOL_AS_UID = useSymbolAsUid;
361
362         var WellKnownSymbolsStore$1 = shared$4('wks');
363         var Symbol$3 = global$1c.Symbol;
364         var symbolFor = Symbol$3 && Symbol$3['for'];
365         var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$3 : Symbol$3 && Symbol$3.withoutSetter || uid$4;
366
367         var wellKnownSymbol$t = function (name) {
368           if (!hasOwn$l(WellKnownSymbolsStore$1, name) || !(NATIVE_SYMBOL$2 || typeof WellKnownSymbolsStore$1[name] == 'string')) {
369             var description = 'Symbol.' + name;
370             if (NATIVE_SYMBOL$2 && hasOwn$l(Symbol$3, name)) {
371               WellKnownSymbolsStore$1[name] = Symbol$3[name];
372             } else if (USE_SYMBOL_AS_UID && symbolFor) {
373               WellKnownSymbolsStore$1[name] = symbolFor(description);
374             } else {
375               WellKnownSymbolsStore$1[name] = createWellKnownSymbol(description);
376             }
377           } return WellKnownSymbolsStore$1[name];
378         };
379
380         var global$1b = global$1o;
381         var call$n = functionCall;
382         var isObject$q = isObject$s;
383         var isSymbol$5 = isSymbol$6;
384         var getMethod$6 = getMethod$7;
385         var ordinaryToPrimitive = ordinaryToPrimitive$1;
386         var wellKnownSymbol$s = wellKnownSymbol$t;
387
388         var TypeError$m = global$1b.TypeError;
389         var TO_PRIMITIVE$1 = wellKnownSymbol$s('toPrimitive');
390
391         // `ToPrimitive` abstract operation
392         // https://tc39.es/ecma262/#sec-toprimitive
393         var toPrimitive$3 = function (input, pref) {
394           if (!isObject$q(input) || isSymbol$5(input)) return input;
395           var exoticToPrim = getMethod$6(input, TO_PRIMITIVE$1);
396           var result;
397           if (exoticToPrim) {
398             if (pref === undefined) pref = 'default';
399             result = call$n(exoticToPrim, input, pref);
400             if (!isObject$q(result) || isSymbol$5(result)) return result;
401             throw TypeError$m("Can't convert object to primitive value");
402           }
403           if (pref === undefined) pref = 'number';
404           return ordinaryToPrimitive(input, pref);
405         };
406
407         var toPrimitive$2 = toPrimitive$3;
408         var isSymbol$4 = isSymbol$6;
409
410         // `ToPropertyKey` abstract operation
411         // https://tc39.es/ecma262/#sec-topropertykey
412         var toPropertyKey$5 = function (argument) {
413           var key = toPrimitive$2(argument, 'string');
414           return isSymbol$4(key) ? key : key + '';
415         };
416
417         var global$1a = global$1o;
418         var isObject$p = isObject$s;
419
420         var document$3 = global$1a.document;
421         // typeof document.createElement is 'object' in old IE
422         var EXISTS$1 = isObject$p(document$3) && isObject$p(document$3.createElement);
423
424         var documentCreateElement$2 = function (it) {
425           return EXISTS$1 ? document$3.createElement(it) : {};
426         };
427
428         var DESCRIPTORS$p = descriptors;
429         var fails$Q = fails$V;
430         var createElement$1 = documentCreateElement$2;
431
432         // Thanks to IE8 for its funny defineProperty
433         var ie8DomDefine = !DESCRIPTORS$p && !fails$Q(function () {
434           // eslint-disable-next-line es/no-object-defineproperty -- required for testing
435           return Object.defineProperty(createElement$1('div'), 'a', {
436             get: function () { return 7; }
437           }).a != 7;
438         });
439
440         var DESCRIPTORS$o = descriptors;
441         var call$m = functionCall;
442         var propertyIsEnumerableModule$2 = objectPropertyIsEnumerable;
443         var createPropertyDescriptor$6 = createPropertyDescriptor$7;
444         var toIndexedObject$c = toIndexedObject$d;
445         var toPropertyKey$4 = toPropertyKey$5;
446         var hasOwn$k = hasOwnProperty_1;
447         var IE8_DOM_DEFINE$1 = ie8DomDefine;
448
449         // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
450         var $getOwnPropertyDescriptor$2 = Object.getOwnPropertyDescriptor;
451
452         // `Object.getOwnPropertyDescriptor` method
453         // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
454         objectGetOwnPropertyDescriptor.f = DESCRIPTORS$o ? $getOwnPropertyDescriptor$2 : function getOwnPropertyDescriptor(O, P) {
455           O = toIndexedObject$c(O);
456           P = toPropertyKey$4(P);
457           if (IE8_DOM_DEFINE$1) try {
458             return $getOwnPropertyDescriptor$2(O, P);
459           } catch (error) { /* empty */ }
460           if (hasOwn$k(O, P)) return createPropertyDescriptor$6(!call$m(propertyIsEnumerableModule$2.f, O, P), O[P]);
461         };
462
463         var objectDefineProperty = {};
464
465         var DESCRIPTORS$n = descriptors;
466         var fails$P = fails$V;
467
468         // V8 ~ Chrome 36-
469         // https://bugs.chromium.org/p/v8/issues/detail?id=3334
470         var v8PrototypeDefineBug = DESCRIPTORS$n && fails$P(function () {
471           // eslint-disable-next-line es/no-object-defineproperty -- required for testing
472           return Object.defineProperty(function () { /* empty */ }, 'prototype', {
473             value: 42,
474             writable: false
475           }).prototype != 42;
476         });
477
478         var global$19 = global$1o;
479         var isObject$o = isObject$s;
480
481         var String$5 = global$19.String;
482         var TypeError$l = global$19.TypeError;
483
484         // `Assert: Type(argument) is Object`
485         var anObject$n = function (argument) {
486           if (isObject$o(argument)) return argument;
487           throw TypeError$l(String$5(argument) + ' is not an object');
488         };
489
490         var global$18 = global$1o;
491         var DESCRIPTORS$m = descriptors;
492         var IE8_DOM_DEFINE = ie8DomDefine;
493         var V8_PROTOTYPE_DEFINE_BUG$1 = v8PrototypeDefineBug;
494         var anObject$m = anObject$n;
495         var toPropertyKey$3 = toPropertyKey$5;
496
497         var TypeError$k = global$18.TypeError;
498         // eslint-disable-next-line es/no-object-defineproperty -- safe
499         var $defineProperty$1 = Object.defineProperty;
500         // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
501         var $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
502         var ENUMERABLE = 'enumerable';
503         var CONFIGURABLE$1 = 'configurable';
504         var WRITABLE = 'writable';
505
506         // `Object.defineProperty` method
507         // https://tc39.es/ecma262/#sec-object.defineproperty
508         objectDefineProperty.f = DESCRIPTORS$m ? V8_PROTOTYPE_DEFINE_BUG$1 ? function defineProperty(O, P, Attributes) {
509           anObject$m(O);
510           P = toPropertyKey$3(P);
511           anObject$m(Attributes);
512           if (typeof O === 'function' && P === 'prototype' && 'value' in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) {
513             var current = $getOwnPropertyDescriptor$1(O, P);
514             if (current && current[WRITABLE]) {
515               O[P] = Attributes.value;
516               Attributes = {
517                 configurable: CONFIGURABLE$1 in Attributes ? Attributes[CONFIGURABLE$1] : current[CONFIGURABLE$1],
518                 enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE],
519                 writable: false
520               };
521             }
522           } return $defineProperty$1(O, P, Attributes);
523         } : $defineProperty$1 : function defineProperty(O, P, Attributes) {
524           anObject$m(O);
525           P = toPropertyKey$3(P);
526           anObject$m(Attributes);
527           if (IE8_DOM_DEFINE) try {
528             return $defineProperty$1(O, P, Attributes);
529           } catch (error) { /* empty */ }
530           if ('get' in Attributes || 'set' in Attributes) throw TypeError$k('Accessors not supported');
531           if ('value' in Attributes) O[P] = Attributes.value;
532           return O;
533         };
534
535         var DESCRIPTORS$l = descriptors;
536         var definePropertyModule$7 = objectDefineProperty;
537         var createPropertyDescriptor$5 = createPropertyDescriptor$7;
538
539         var createNonEnumerableProperty$b = DESCRIPTORS$l ? function (object, key, value) {
540           return definePropertyModule$7.f(object, key, createPropertyDescriptor$5(1, value));
541         } : function (object, key, value) {
542           object[key] = value;
543           return object;
544         };
545
546         var redefine$h = {exports: {}};
547
548         var uncurryThis$S = functionUncurryThis;
549         var isCallable$l = isCallable$r;
550         var store$2 = sharedStore;
551
552         var functionToString$1 = uncurryThis$S(Function.toString);
553
554         // this helper broken in `core-js@3.4.1-3.4.4`, so we can't use `shared` helper
555         if (!isCallable$l(store$2.inspectSource)) {
556           store$2.inspectSource = function (it) {
557             return functionToString$1(it);
558           };
559         }
560
561         var inspectSource$4 = store$2.inspectSource;
562
563         var global$17 = global$1o;
564         var isCallable$k = isCallable$r;
565         var inspectSource$3 = inspectSource$4;
566
567         var WeakMap$1 = global$17.WeakMap;
568
569         var nativeWeakMap = isCallable$k(WeakMap$1) && /native code/.test(inspectSource$3(WeakMap$1));
570
571         var shared$3 = shared$5.exports;
572         var uid$3 = uid$5;
573
574         var keys$3 = shared$3('keys');
575
576         var sharedKey$4 = function (key) {
577           return keys$3[key] || (keys$3[key] = uid$3(key));
578         };
579
580         var hiddenKeys$6 = {};
581
582         var NATIVE_WEAK_MAP = nativeWeakMap;
583         var global$16 = global$1o;
584         var uncurryThis$R = functionUncurryThis;
585         var isObject$n = isObject$s;
586         var createNonEnumerableProperty$a = createNonEnumerableProperty$b;
587         var hasOwn$j = hasOwnProperty_1;
588         var shared$2 = sharedStore;
589         var sharedKey$3 = sharedKey$4;
590         var hiddenKeys$5 = hiddenKeys$6;
591
592         var OBJECT_ALREADY_INITIALIZED = 'Object already initialized';
593         var TypeError$j = global$16.TypeError;
594         var WeakMap = global$16.WeakMap;
595         var set$4, get$5, has;
596
597         var enforce = function (it) {
598           return has(it) ? get$5(it) : set$4(it, {});
599         };
600
601         var getterFor = function (TYPE) {
602           return function (it) {
603             var state;
604             if (!isObject$n(it) || (state = get$5(it)).type !== TYPE) {
605               throw TypeError$j('Incompatible receiver, ' + TYPE + ' required');
606             } return state;
607           };
608         };
609
610         if (NATIVE_WEAK_MAP || shared$2.state) {
611           var store$1 = shared$2.state || (shared$2.state = new WeakMap());
612           var wmget = uncurryThis$R(store$1.get);
613           var wmhas = uncurryThis$R(store$1.has);
614           var wmset = uncurryThis$R(store$1.set);
615           set$4 = function (it, metadata) {
616             if (wmhas(store$1, it)) throw new TypeError$j(OBJECT_ALREADY_INITIALIZED);
617             metadata.facade = it;
618             wmset(store$1, it, metadata);
619             return metadata;
620           };
621           get$5 = function (it) {
622             return wmget(store$1, it) || {};
623           };
624           has = function (it) {
625             return wmhas(store$1, it);
626           };
627         } else {
628           var STATE = sharedKey$3('state');
629           hiddenKeys$5[STATE] = true;
630           set$4 = function (it, metadata) {
631             if (hasOwn$j(it, STATE)) throw new TypeError$j(OBJECT_ALREADY_INITIALIZED);
632             metadata.facade = it;
633             createNonEnumerableProperty$a(it, STATE, metadata);
634             return metadata;
635           };
636           get$5 = function (it) {
637             return hasOwn$j(it, STATE) ? it[STATE] : {};
638           };
639           has = function (it) {
640             return hasOwn$j(it, STATE);
641           };
642         }
643
644         var internalState = {
645           set: set$4,
646           get: get$5,
647           has: has,
648           enforce: enforce,
649           getterFor: getterFor
650         };
651
652         var DESCRIPTORS$k = descriptors;
653         var hasOwn$i = hasOwnProperty_1;
654
655         var FunctionPrototype$2 = Function.prototype;
656         // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
657         var getDescriptor = DESCRIPTORS$k && Object.getOwnPropertyDescriptor;
658
659         var EXISTS = hasOwn$i(FunctionPrototype$2, 'name');
660         // additional protection from minified / mangled / dropped function names
661         var PROPER = EXISTS && (function something() { /* empty */ }).name === 'something';
662         var CONFIGURABLE = EXISTS && (!DESCRIPTORS$k || (DESCRIPTORS$k && getDescriptor(FunctionPrototype$2, 'name').configurable));
663
664         var functionName = {
665           EXISTS: EXISTS,
666           PROPER: PROPER,
667           CONFIGURABLE: CONFIGURABLE
668         };
669
670         var global$15 = global$1o;
671         var isCallable$j = isCallable$r;
672         var hasOwn$h = hasOwnProperty_1;
673         var createNonEnumerableProperty$9 = createNonEnumerableProperty$b;
674         var setGlobal$1 = setGlobal$3;
675         var inspectSource$2 = inspectSource$4;
676         var InternalStateModule$9 = internalState;
677         var CONFIGURABLE_FUNCTION_NAME$2 = functionName.CONFIGURABLE;
678
679         var getInternalState$7 = InternalStateModule$9.get;
680         var enforceInternalState$1 = InternalStateModule$9.enforce;
681         var TEMPLATE = String(String).split('String');
682
683         (redefine$h.exports = function (O, key, value, options) {
684           var unsafe = options ? !!options.unsafe : false;
685           var simple = options ? !!options.enumerable : false;
686           var noTargetGet = options ? !!options.noTargetGet : false;
687           var name = options && options.name !== undefined ? options.name : key;
688           var state;
689           if (isCallable$j(value)) {
690             if (String(name).slice(0, 7) === 'Symbol(') {
691               name = '[' + String(name).replace(/^Symbol\(([^)]*)\)/, '$1') + ']';
692             }
693             if (!hasOwn$h(value, 'name') || (CONFIGURABLE_FUNCTION_NAME$2 && value.name !== name)) {
694               createNonEnumerableProperty$9(value, 'name', name);
695             }
696             state = enforceInternalState$1(value);
697             if (!state.source) {
698               state.source = TEMPLATE.join(typeof name == 'string' ? name : '');
699             }
700           }
701           if (O === global$15) {
702             if (simple) O[key] = value;
703             else setGlobal$1(key, value);
704             return;
705           } else if (!unsafe) {
706             delete O[key];
707           } else if (!noTargetGet && O[key]) {
708             simple = true;
709           }
710           if (simple) O[key] = value;
711           else createNonEnumerableProperty$9(O, key, value);
712         // add fake Function#toString for correct work wrapped methods / constructors with methods like LoDash isNative
713         })(Function.prototype, 'toString', function toString() {
714           return isCallable$j(this) && getInternalState$7(this).source || inspectSource$2(this);
715         });
716
717         var objectGetOwnPropertyNames = {};
718
719         var ceil$1 = Math.ceil;
720         var floor$8 = Math.floor;
721
722         // `ToIntegerOrInfinity` abstract operation
723         // https://tc39.es/ecma262/#sec-tointegerorinfinity
724         var toIntegerOrInfinity$b = function (argument) {
725           var number = +argument;
726           // eslint-disable-next-line no-self-compare -- safe
727           return number !== number || number === 0 ? 0 : (number > 0 ? floor$8 : ceil$1)(number);
728         };
729
730         var toIntegerOrInfinity$a = toIntegerOrInfinity$b;
731
732         var max$5 = Math.max;
733         var min$9 = Math.min;
734
735         // Helper for a popular repeating case of the spec:
736         // Let integer be ? ToInteger(index).
737         // If integer < 0, let result be max((length + integer), 0); else let result be min(integer, length).
738         var toAbsoluteIndex$9 = function (index, length) {
739           var integer = toIntegerOrInfinity$a(index);
740           return integer < 0 ? max$5(integer + length, 0) : min$9(integer, length);
741         };
742
743         var toIntegerOrInfinity$9 = toIntegerOrInfinity$b;
744
745         var min$8 = Math.min;
746
747         // `ToLength` abstract operation
748         // https://tc39.es/ecma262/#sec-tolength
749         var toLength$c = function (argument) {
750           return argument > 0 ? min$8(toIntegerOrInfinity$9(argument), 0x1FFFFFFFFFFFFF) : 0; // 2 ** 53 - 1 == 9007199254740991
751         };
752
753         var toLength$b = toLength$c;
754
755         // `LengthOfArrayLike` abstract operation
756         // https://tc39.es/ecma262/#sec-lengthofarraylike
757         var lengthOfArrayLike$i = function (obj) {
758           return toLength$b(obj.length);
759         };
760
761         var toIndexedObject$b = toIndexedObject$d;
762         var toAbsoluteIndex$8 = toAbsoluteIndex$9;
763         var lengthOfArrayLike$h = lengthOfArrayLike$i;
764
765         // `Array.prototype.{ indexOf, includes }` methods implementation
766         var createMethod$6 = function (IS_INCLUDES) {
767           return function ($this, el, fromIndex) {
768             var O = toIndexedObject$b($this);
769             var length = lengthOfArrayLike$h(O);
770             var index = toAbsoluteIndex$8(fromIndex, length);
771             var value;
772             // Array#includes uses SameValueZero equality algorithm
773             // eslint-disable-next-line no-self-compare -- NaN check
774             if (IS_INCLUDES && el != el) while (length > index) {
775               value = O[index++];
776               // eslint-disable-next-line no-self-compare -- NaN check
777               if (value != value) return true;
778             // Array#indexOf ignores holes, Array#includes - not
779             } else for (;length > index; index++) {
780               if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
781             } return !IS_INCLUDES && -1;
782           };
783         };
784
785         var arrayIncludes = {
786           // `Array.prototype.includes` method
787           // https://tc39.es/ecma262/#sec-array.prototype.includes
788           includes: createMethod$6(true),
789           // `Array.prototype.indexOf` method
790           // https://tc39.es/ecma262/#sec-array.prototype.indexof
791           indexOf: createMethod$6(false)
792         };
793
794         var uncurryThis$Q = functionUncurryThis;
795         var hasOwn$g = hasOwnProperty_1;
796         var toIndexedObject$a = toIndexedObject$d;
797         var indexOf$1 = arrayIncludes.indexOf;
798         var hiddenKeys$4 = hiddenKeys$6;
799
800         var push$a = uncurryThis$Q([].push);
801
802         var objectKeysInternal = function (object, names) {
803           var O = toIndexedObject$a(object);
804           var i = 0;
805           var result = [];
806           var key;
807           for (key in O) !hasOwn$g(hiddenKeys$4, key) && hasOwn$g(O, key) && push$a(result, key);
808           // Don't enum bug & hidden keys
809           while (names.length > i) if (hasOwn$g(O, key = names[i++])) {
810             ~indexOf$1(result, key) || push$a(result, key);
811           }
812           return result;
813         };
814
815         // IE8- don't enum bug keys
816         var enumBugKeys$3 = [
817           'constructor',
818           'hasOwnProperty',
819           'isPrototypeOf',
820           'propertyIsEnumerable',
821           'toLocaleString',
822           'toString',
823           'valueOf'
824         ];
825
826         var internalObjectKeys$1 = objectKeysInternal;
827         var enumBugKeys$2 = enumBugKeys$3;
828
829         var hiddenKeys$3 = enumBugKeys$2.concat('length', 'prototype');
830
831         // `Object.getOwnPropertyNames` method
832         // https://tc39.es/ecma262/#sec-object.getownpropertynames
833         // eslint-disable-next-line es/no-object-getownpropertynames -- safe
834         objectGetOwnPropertyNames.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
835           return internalObjectKeys$1(O, hiddenKeys$3);
836         };
837
838         var objectGetOwnPropertySymbols = {};
839
840         // eslint-disable-next-line es/no-object-getownpropertysymbols -- safe
841         objectGetOwnPropertySymbols.f = Object.getOwnPropertySymbols;
842
843         var getBuiltIn$8 = getBuiltIn$b;
844         var uncurryThis$P = functionUncurryThis;
845         var getOwnPropertyNamesModule$2 = objectGetOwnPropertyNames;
846         var getOwnPropertySymbolsModule$2 = objectGetOwnPropertySymbols;
847         var anObject$l = anObject$n;
848
849         var concat$3 = uncurryThis$P([].concat);
850
851         // all object keys, includes non-enumerable and symbols
852         var ownKeys$1 = getBuiltIn$8('Reflect', 'ownKeys') || function ownKeys(it) {
853           var keys = getOwnPropertyNamesModule$2.f(anObject$l(it));
854           var getOwnPropertySymbols = getOwnPropertySymbolsModule$2.f;
855           return getOwnPropertySymbols ? concat$3(keys, getOwnPropertySymbols(it)) : keys;
856         };
857
858         var hasOwn$f = hasOwnProperty_1;
859         var ownKeys = ownKeys$1;
860         var getOwnPropertyDescriptorModule$3 = objectGetOwnPropertyDescriptor;
861         var definePropertyModule$6 = objectDefineProperty;
862
863         var copyConstructorProperties$2 = function (target, source, exceptions) {
864           var keys = ownKeys(source);
865           var defineProperty = definePropertyModule$6.f;
866           var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule$3.f;
867           for (var i = 0; i < keys.length; i++) {
868             var key = keys[i];
869             if (!hasOwn$f(target, key) && !(exceptions && hasOwn$f(exceptions, key))) {
870               defineProperty(target, key, getOwnPropertyDescriptor(source, key));
871             }
872           }
873         };
874
875         var fails$O = fails$V;
876         var isCallable$i = isCallable$r;
877
878         var replacement = /#|\.prototype\./;
879
880         var isForced$5 = function (feature, detection) {
881           var value = data[normalize$1(feature)];
882           return value == POLYFILL ? true
883             : value == NATIVE ? false
884             : isCallable$i(detection) ? fails$O(detection)
885             : !!detection;
886         };
887
888         var normalize$1 = isForced$5.normalize = function (string) {
889           return String(string).replace(replacement, '.').toLowerCase();
890         };
891
892         var data = isForced$5.data = {};
893         var NATIVE = isForced$5.NATIVE = 'N';
894         var POLYFILL = isForced$5.POLYFILL = 'P';
895
896         var isForced_1 = isForced$5;
897
898         var global$14 = global$1o;
899         var getOwnPropertyDescriptor$4 = objectGetOwnPropertyDescriptor.f;
900         var createNonEnumerableProperty$8 = createNonEnumerableProperty$b;
901         var redefine$g = redefine$h.exports;
902         var setGlobal = setGlobal$3;
903         var copyConstructorProperties$1 = copyConstructorProperties$2;
904         var isForced$4 = isForced_1;
905
906         /*
907           options.target      - name of the target object
908           options.global      - target is the global object
909           options.stat        - export as static methods of target
910           options.proto       - export as prototype methods of target
911           options.real        - real prototype method for the `pure` version
912           options.forced      - export even if the native feature is available
913           options.bind        - bind methods to the target, required for the `pure` version
914           options.wrap        - wrap constructors to preventing global pollution, required for the `pure` version
915           options.unsafe      - use the simple assignment of property instead of delete + defineProperty
916           options.sham        - add a flag to not completely full polyfills
917           options.enumerable  - export as enumerable property
918           options.noTargetGet - prevent calling a getter on target
919           options.name        - the .name of the function if it does not match the key
920         */
921         var _export = function (options, source) {
922           var TARGET = options.target;
923           var GLOBAL = options.global;
924           var STATIC = options.stat;
925           var FORCED, target, key, targetProperty, sourceProperty, descriptor;
926           if (GLOBAL) {
927             target = global$14;
928           } else if (STATIC) {
929             target = global$14[TARGET] || setGlobal(TARGET, {});
930           } else {
931             target = (global$14[TARGET] || {}).prototype;
932           }
933           if (target) for (key in source) {
934             sourceProperty = source[key];
935             if (options.noTargetGet) {
936               descriptor = getOwnPropertyDescriptor$4(target, key);
937               targetProperty = descriptor && descriptor.value;
938             } else targetProperty = target[key];
939             FORCED = isForced$4(GLOBAL ? key : TARGET + (STATIC ? '.' : '#') + key, options.forced);
940             // contained in target
941             if (!FORCED && targetProperty !== undefined) {
942               if (typeof sourceProperty == typeof targetProperty) continue;
943               copyConstructorProperties$1(sourceProperty, targetProperty);
944             }
945             // add a flag to not completely full polyfills
946             if (options.sham || (targetProperty && targetProperty.sham)) {
947               createNonEnumerableProperty$8(sourceProperty, 'sham', true);
948             }
949             // extend global
950             redefine$g(target, key, sourceProperty, options);
951           }
952         };
953
954         var $$1e = _export;
955         var global$13 = global$1o;
956         var uncurryThis$O = functionUncurryThis;
957
958         var Date$1 = global$13.Date;
959         var getTime$2 = uncurryThis$O(Date$1.prototype.getTime);
960
961         // `Date.now` method
962         // https://tc39.es/ecma262/#sec-date.now
963         $$1e({ target: 'Date', stat: true }, {
964           now: function now() {
965             return getTime$2(new Date$1());
966           }
967         });
968
969         var uncurryThis$N = functionUncurryThis;
970         var redefine$f = redefine$h.exports;
971
972         var DatePrototype$1 = Date.prototype;
973         var INVALID_DATE = 'Invalid Date';
974         var TO_STRING$1 = 'toString';
975         var un$DateToString = uncurryThis$N(DatePrototype$1[TO_STRING$1]);
976         var getTime$1 = uncurryThis$N(DatePrototype$1.getTime);
977
978         // `Date.prototype.toString` method
979         // https://tc39.es/ecma262/#sec-date.prototype.tostring
980         if (String(new Date(NaN)) != INVALID_DATE) {
981           redefine$f(DatePrototype$1, TO_STRING$1, function toString() {
982             var value = getTime$1(this);
983             // eslint-disable-next-line no-self-compare -- NaN check
984             return value === value ? un$DateToString(this) : INVALID_DATE;
985           });
986         }
987
988         function _typeof(obj) {
989           "@babel/helpers - typeof";
990
991           return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
992             return typeof obj;
993           } : function (obj) {
994             return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
995           }, _typeof(obj);
996         }
997
998         function _classCallCheck$1(instance, Constructor) {
999           if (!(instance instanceof Constructor)) {
1000             throw new TypeError("Cannot call a class as a function");
1001           }
1002         }
1003
1004         function _defineProperties$1(target, props) {
1005           for (var i = 0; i < props.length; i++) {
1006             var descriptor = props[i];
1007             descriptor.enumerable = descriptor.enumerable || false;
1008             descriptor.configurable = true;
1009             if ("value" in descriptor) descriptor.writable = true;
1010             Object.defineProperty(target, descriptor.key, descriptor);
1011           }
1012         }
1013
1014         function _createClass$1(Constructor, protoProps, staticProps) {
1015           if (protoProps) _defineProperties$1(Constructor.prototype, protoProps);
1016           if (staticProps) _defineProperties$1(Constructor, staticProps);
1017           Object.defineProperty(Constructor, "prototype", {
1018             writable: false
1019           });
1020           return Constructor;
1021         }
1022
1023         function _defineProperty(obj, key, value) {
1024           if (key in obj) {
1025             Object.defineProperty(obj, key, {
1026               value: value,
1027               enumerable: true,
1028               configurable: true,
1029               writable: true
1030             });
1031           } else {
1032             obj[key] = value;
1033           }
1034
1035           return obj;
1036         }
1037
1038         function _slicedToArray(arr, i) {
1039           return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
1040         }
1041
1042         function _toConsumableArray(arr) {
1043           return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
1044         }
1045
1046         function _arrayWithoutHoles(arr) {
1047           if (Array.isArray(arr)) return _arrayLikeToArray(arr);
1048         }
1049
1050         function _arrayWithHoles(arr) {
1051           if (Array.isArray(arr)) return arr;
1052         }
1053
1054         function _iterableToArray(iter) {
1055           if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
1056         }
1057
1058         function _iterableToArrayLimit(arr, i) {
1059           var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
1060
1061           if (_i == null) return;
1062           var _arr = [];
1063           var _n = true;
1064           var _d = false;
1065
1066           var _s, _e;
1067
1068           try {
1069             for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) {
1070               _arr.push(_s.value);
1071
1072               if (i && _arr.length === i) break;
1073             }
1074           } catch (err) {
1075             _d = true;
1076             _e = err;
1077           } finally {
1078             try {
1079               if (!_n && _i["return"] != null) _i["return"]();
1080             } finally {
1081               if (_d) throw _e;
1082             }
1083           }
1084
1085           return _arr;
1086         }
1087
1088         function _unsupportedIterableToArray(o, minLen) {
1089           if (!o) return;
1090           if (typeof o === "string") return _arrayLikeToArray(o, minLen);
1091           var n = Object.prototype.toString.call(o).slice(8, -1);
1092           if (n === "Object" && o.constructor) n = o.constructor.name;
1093           if (n === "Map" || n === "Set") return Array.from(o);
1094           if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
1095         }
1096
1097         function _arrayLikeToArray(arr, len) {
1098           if (len == null || len > arr.length) len = arr.length;
1099
1100           for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
1101
1102           return arr2;
1103         }
1104
1105         function _nonIterableSpread() {
1106           throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1107         }
1108
1109         function _nonIterableRest() {
1110           throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1111         }
1112
1113         function _createForOfIteratorHelper(o, allowArrayLike) {
1114           var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
1115
1116           if (!it) {
1117             if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
1118               if (it) o = it;
1119               var i = 0;
1120
1121               var F = function () {};
1122
1123               return {
1124                 s: F,
1125                 n: function () {
1126                   if (i >= o.length) return {
1127                     done: true
1128                   };
1129                   return {
1130                     done: false,
1131                     value: o[i++]
1132                   };
1133                 },
1134                 e: function (e) {
1135                   throw e;
1136                 },
1137                 f: F
1138               };
1139             }
1140
1141             throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
1142           }
1143
1144           var normalCompletion = true,
1145               didErr = false,
1146               err;
1147           return {
1148             s: function () {
1149               it = it.call(o);
1150             },
1151             n: function () {
1152               var step = it.next();
1153               normalCompletion = step.done;
1154               return step;
1155             },
1156             e: function (e) {
1157               didErr = true;
1158               err = e;
1159             },
1160             f: function () {
1161               try {
1162                 if (!normalCompletion && it.return != null) it.return();
1163               } finally {
1164                 if (didErr) throw err;
1165               }
1166             }
1167           };
1168         }
1169
1170         var $$1d = _export;
1171         var global$12 = global$1o;
1172
1173         // `globalThis` object
1174         // https://tc39.es/ecma262/#sec-globalthis
1175         $$1d({ global: true }, {
1176           globalThis: global$12
1177         });
1178
1179         var global$11 = global$1o;
1180
1181         var path$1 = global$11;
1182
1183         var wellKnownSymbolWrapped = {};
1184
1185         var wellKnownSymbol$r = wellKnownSymbol$t;
1186
1187         wellKnownSymbolWrapped.f = wellKnownSymbol$r;
1188
1189         var path = path$1;
1190         var hasOwn$e = hasOwnProperty_1;
1191         var wrappedWellKnownSymbolModule$1 = wellKnownSymbolWrapped;
1192         var defineProperty$c = objectDefineProperty.f;
1193
1194         var defineWellKnownSymbol$4 = function (NAME) {
1195           var Symbol = path.Symbol || (path.Symbol = {});
1196           if (!hasOwn$e(Symbol, NAME)) defineProperty$c(Symbol, NAME, {
1197             value: wrappedWellKnownSymbolModule$1.f(NAME)
1198           });
1199         };
1200
1201         var defineWellKnownSymbol$3 = defineWellKnownSymbol$4;
1202
1203         // `Symbol.iterator` well-known symbol
1204         // https://tc39.es/ecma262/#sec-symbol.iterator
1205         defineWellKnownSymbol$3('iterator');
1206
1207         var objectDefineProperties = {};
1208
1209         var internalObjectKeys = objectKeysInternal;
1210         var enumBugKeys$1 = enumBugKeys$3;
1211
1212         // `Object.keys` method
1213         // https://tc39.es/ecma262/#sec-object.keys
1214         // eslint-disable-next-line es/no-object-keys -- safe
1215         var objectKeys$4 = Object.keys || function keys(O) {
1216           return internalObjectKeys(O, enumBugKeys$1);
1217         };
1218
1219         var DESCRIPTORS$j = descriptors;
1220         var V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug;
1221         var definePropertyModule$5 = objectDefineProperty;
1222         var anObject$k = anObject$n;
1223         var toIndexedObject$9 = toIndexedObject$d;
1224         var objectKeys$3 = objectKeys$4;
1225
1226         // `Object.defineProperties` method
1227         // https://tc39.es/ecma262/#sec-object.defineproperties
1228         // eslint-disable-next-line es/no-object-defineproperties -- safe
1229         objectDefineProperties.f = DESCRIPTORS$j && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) {
1230           anObject$k(O);
1231           var props = toIndexedObject$9(Properties);
1232           var keys = objectKeys$3(Properties);
1233           var length = keys.length;
1234           var index = 0;
1235           var key;
1236           while (length > index) definePropertyModule$5.f(O, key = keys[index++], props[key]);
1237           return O;
1238         };
1239
1240         var getBuiltIn$7 = getBuiltIn$b;
1241
1242         var html$2 = getBuiltIn$7('document', 'documentElement');
1243
1244         /* global ActiveXObject -- old IE, WSH */
1245
1246         var anObject$j = anObject$n;
1247         var definePropertiesModule$1 = objectDefineProperties;
1248         var enumBugKeys = enumBugKeys$3;
1249         var hiddenKeys$2 = hiddenKeys$6;
1250         var html$1 = html$2;
1251         var documentCreateElement$1 = documentCreateElement$2;
1252         var sharedKey$2 = sharedKey$4;
1253
1254         var GT = '>';
1255         var LT = '<';
1256         var PROTOTYPE$2 = 'prototype';
1257         var SCRIPT = 'script';
1258         var IE_PROTO$1 = sharedKey$2('IE_PROTO');
1259
1260         var EmptyConstructor = function () { /* empty */ };
1261
1262         var scriptTag = function (content) {
1263           return LT + SCRIPT + GT + content + LT + '/' + SCRIPT + GT;
1264         };
1265
1266         // Create object with fake `null` prototype: use ActiveX Object with cleared prototype
1267         var NullProtoObjectViaActiveX = function (activeXDocument) {
1268           activeXDocument.write(scriptTag(''));
1269           activeXDocument.close();
1270           var temp = activeXDocument.parentWindow.Object;
1271           activeXDocument = null; // avoid memory leak
1272           return temp;
1273         };
1274
1275         // Create object with fake `null` prototype: use iframe Object with cleared prototype
1276         var NullProtoObjectViaIFrame = function () {
1277           // Thrash, waste and sodomy: IE GC bug
1278           var iframe = documentCreateElement$1('iframe');
1279           var JS = 'java' + SCRIPT + ':';
1280           var iframeDocument;
1281           iframe.style.display = 'none';
1282           html$1.appendChild(iframe);
1283           // https://github.com/zloirock/core-js/issues/475
1284           iframe.src = String(JS);
1285           iframeDocument = iframe.contentWindow.document;
1286           iframeDocument.open();
1287           iframeDocument.write(scriptTag('document.F=Object'));
1288           iframeDocument.close();
1289           return iframeDocument.F;
1290         };
1291
1292         // Check for document.domain and active x support
1293         // No need to use active x approach when document.domain is not set
1294         // see https://github.com/es-shims/es5-shim/issues/150
1295         // variation of https://github.com/kitcambridge/es5-shim/commit/4f738ac066346
1296         // avoid IE GC bug
1297         var activeXDocument;
1298         var NullProtoObject = function () {
1299           try {
1300             activeXDocument = new ActiveXObject('htmlfile');
1301           } catch (error) { /* ignore */ }
1302           NullProtoObject = typeof document != 'undefined'
1303             ? document.domain && activeXDocument
1304               ? NullProtoObjectViaActiveX(activeXDocument) // old IE
1305               : NullProtoObjectViaIFrame()
1306             : NullProtoObjectViaActiveX(activeXDocument); // WSH
1307           var length = enumBugKeys.length;
1308           while (length--) delete NullProtoObject[PROTOTYPE$2][enumBugKeys[length]];
1309           return NullProtoObject();
1310         };
1311
1312         hiddenKeys$2[IE_PROTO$1] = true;
1313
1314         // `Object.create` method
1315         // https://tc39.es/ecma262/#sec-object.create
1316         var objectCreate = Object.create || function create(O, Properties) {
1317           var result;
1318           if (O !== null) {
1319             EmptyConstructor[PROTOTYPE$2] = anObject$j(O);
1320             result = new EmptyConstructor();
1321             EmptyConstructor[PROTOTYPE$2] = null;
1322             // add "__proto__" for Object.getPrototypeOf polyfill
1323             result[IE_PROTO$1] = O;
1324           } else result = NullProtoObject();
1325           return Properties === undefined ? result : definePropertiesModule$1.f(result, Properties);
1326         };
1327
1328         var wellKnownSymbol$q = wellKnownSymbol$t;
1329         var create$a = objectCreate;
1330         var definePropertyModule$4 = objectDefineProperty;
1331
1332         var UNSCOPABLES = wellKnownSymbol$q('unscopables');
1333         var ArrayPrototype$1 = Array.prototype;
1334
1335         // Array.prototype[@@unscopables]
1336         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
1337         if (ArrayPrototype$1[UNSCOPABLES] == undefined) {
1338           definePropertyModule$4.f(ArrayPrototype$1, UNSCOPABLES, {
1339             configurable: true,
1340             value: create$a(null)
1341           });
1342         }
1343
1344         // add a key to Array.prototype[@@unscopables]
1345         var addToUnscopables$6 = function (key) {
1346           ArrayPrototype$1[UNSCOPABLES][key] = true;
1347         };
1348
1349         var iterators = {};
1350
1351         var fails$N = fails$V;
1352
1353         var correctPrototypeGetter = !fails$N(function () {
1354           function F() { /* empty */ }
1355           F.prototype.constructor = null;
1356           // eslint-disable-next-line es/no-object-getprototypeof -- required for testing
1357           return Object.getPrototypeOf(new F()) !== F.prototype;
1358         });
1359
1360         var global$10 = global$1o;
1361         var hasOwn$d = hasOwnProperty_1;
1362         var isCallable$h = isCallable$r;
1363         var toObject$g = toObject$i;
1364         var sharedKey$1 = sharedKey$4;
1365         var CORRECT_PROTOTYPE_GETTER$1 = correctPrototypeGetter;
1366
1367         var IE_PROTO = sharedKey$1('IE_PROTO');
1368         var Object$2 = global$10.Object;
1369         var ObjectPrototype$4 = Object$2.prototype;
1370
1371         // `Object.getPrototypeOf` method
1372         // https://tc39.es/ecma262/#sec-object.getprototypeof
1373         var objectGetPrototypeOf = CORRECT_PROTOTYPE_GETTER$1 ? Object$2.getPrototypeOf : function (O) {
1374           var object = toObject$g(O);
1375           if (hasOwn$d(object, IE_PROTO)) return object[IE_PROTO];
1376           var constructor = object.constructor;
1377           if (isCallable$h(constructor) && object instanceof constructor) {
1378             return constructor.prototype;
1379           } return object instanceof Object$2 ? ObjectPrototype$4 : null;
1380         };
1381
1382         var fails$M = fails$V;
1383         var isCallable$g = isCallable$r;
1384         var getPrototypeOf$4 = objectGetPrototypeOf;
1385         var redefine$e = redefine$h.exports;
1386         var wellKnownSymbol$p = wellKnownSymbol$t;
1387
1388         var ITERATOR$a = wellKnownSymbol$p('iterator');
1389         var BUGGY_SAFARI_ITERATORS$1 = false;
1390
1391         // `%IteratorPrototype%` object
1392         // https://tc39.es/ecma262/#sec-%iteratorprototype%-object
1393         var IteratorPrototype$2, PrototypeOfArrayIteratorPrototype, arrayIterator;
1394
1395         /* eslint-disable es/no-array-prototype-keys -- safe */
1396         if ([].keys) {
1397           arrayIterator = [].keys();
1398           // Safari 8 has buggy iterators w/o `next`
1399           if (!('next' in arrayIterator)) BUGGY_SAFARI_ITERATORS$1 = true;
1400           else {
1401             PrototypeOfArrayIteratorPrototype = getPrototypeOf$4(getPrototypeOf$4(arrayIterator));
1402             if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype$2 = PrototypeOfArrayIteratorPrototype;
1403           }
1404         }
1405
1406         var NEW_ITERATOR_PROTOTYPE = IteratorPrototype$2 == undefined || fails$M(function () {
1407           var test = {};
1408           // FF44- legacy iterators case
1409           return IteratorPrototype$2[ITERATOR$a].call(test) !== test;
1410         });
1411
1412         if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype$2 = {};
1413
1414         // `%IteratorPrototype%[@@iterator]()` method
1415         // https://tc39.es/ecma262/#sec-%iteratorprototype%-@@iterator
1416         if (!isCallable$g(IteratorPrototype$2[ITERATOR$a])) {
1417           redefine$e(IteratorPrototype$2, ITERATOR$a, function () {
1418             return this;
1419           });
1420         }
1421
1422         var iteratorsCore = {
1423           IteratorPrototype: IteratorPrototype$2,
1424           BUGGY_SAFARI_ITERATORS: BUGGY_SAFARI_ITERATORS$1
1425         };
1426
1427         var defineProperty$b = objectDefineProperty.f;
1428         var hasOwn$c = hasOwnProperty_1;
1429         var wellKnownSymbol$o = wellKnownSymbol$t;
1430
1431         var TO_STRING_TAG$4 = wellKnownSymbol$o('toStringTag');
1432
1433         var setToStringTag$a = function (target, TAG, STATIC) {
1434           if (target && !STATIC) target = target.prototype;
1435           if (target && !hasOwn$c(target, TO_STRING_TAG$4)) {
1436             defineProperty$b(target, TO_STRING_TAG$4, { configurable: true, value: TAG });
1437           }
1438         };
1439
1440         var IteratorPrototype$1 = iteratorsCore.IteratorPrototype;
1441         var create$9 = objectCreate;
1442         var createPropertyDescriptor$4 = createPropertyDescriptor$7;
1443         var setToStringTag$9 = setToStringTag$a;
1444         var Iterators$4 = iterators;
1445
1446         var returnThis$1 = function () { return this; };
1447
1448         var createIteratorConstructor$2 = function (IteratorConstructor, NAME, next, ENUMERABLE_NEXT) {
1449           var TO_STRING_TAG = NAME + ' Iterator';
1450           IteratorConstructor.prototype = create$9(IteratorPrototype$1, { next: createPropertyDescriptor$4(+!ENUMERABLE_NEXT, next) });
1451           setToStringTag$9(IteratorConstructor, TO_STRING_TAG, false);
1452           Iterators$4[TO_STRING_TAG] = returnThis$1;
1453           return IteratorConstructor;
1454         };
1455
1456         var global$$ = global$1o;
1457         var isCallable$f = isCallable$r;
1458
1459         var String$4 = global$$.String;
1460         var TypeError$i = global$$.TypeError;
1461
1462         var aPossiblePrototype$1 = function (argument) {
1463           if (typeof argument == 'object' || isCallable$f(argument)) return argument;
1464           throw TypeError$i("Can't set " + String$4(argument) + ' as a prototype');
1465         };
1466
1467         /* eslint-disable no-proto -- safe */
1468
1469         var uncurryThis$M = functionUncurryThis;
1470         var anObject$i = anObject$n;
1471         var aPossiblePrototype = aPossiblePrototype$1;
1472
1473         // `Object.setPrototypeOf` method
1474         // https://tc39.es/ecma262/#sec-object.setprototypeof
1475         // Works with __proto__ only. Old v8 can't work with null proto objects.
1476         // eslint-disable-next-line es/no-object-setprototypeof -- safe
1477         var objectSetPrototypeOf = Object.setPrototypeOf || ('__proto__' in {} ? function () {
1478           var CORRECT_SETTER = false;
1479           var test = {};
1480           var setter;
1481           try {
1482             // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
1483             setter = uncurryThis$M(Object.getOwnPropertyDescriptor(Object.prototype, '__proto__').set);
1484             setter(test, []);
1485             CORRECT_SETTER = test instanceof Array;
1486           } catch (error) { /* empty */ }
1487           return function setPrototypeOf(O, proto) {
1488             anObject$i(O);
1489             aPossiblePrototype(proto);
1490             if (CORRECT_SETTER) setter(O, proto);
1491             else O.__proto__ = proto;
1492             return O;
1493           };
1494         }() : undefined);
1495
1496         var $$1c = _export;
1497         var call$l = functionCall;
1498         var FunctionName$1 = functionName;
1499         var isCallable$e = isCallable$r;
1500         var createIteratorConstructor$1 = createIteratorConstructor$2;
1501         var getPrototypeOf$3 = objectGetPrototypeOf;
1502         var setPrototypeOf$6 = objectSetPrototypeOf;
1503         var setToStringTag$8 = setToStringTag$a;
1504         var createNonEnumerableProperty$7 = createNonEnumerableProperty$b;
1505         var redefine$d = redefine$h.exports;
1506         var wellKnownSymbol$n = wellKnownSymbol$t;
1507         var Iterators$3 = iterators;
1508         var IteratorsCore = iteratorsCore;
1509
1510         var PROPER_FUNCTION_NAME$3 = FunctionName$1.PROPER;
1511         var CONFIGURABLE_FUNCTION_NAME$1 = FunctionName$1.CONFIGURABLE;
1512         var IteratorPrototype = IteratorsCore.IteratorPrototype;
1513         var BUGGY_SAFARI_ITERATORS = IteratorsCore.BUGGY_SAFARI_ITERATORS;
1514         var ITERATOR$9 = wellKnownSymbol$n('iterator');
1515         var KEYS = 'keys';
1516         var VALUES = 'values';
1517         var ENTRIES = 'entries';
1518
1519         var returnThis = function () { return this; };
1520
1521         var defineIterator$3 = function (Iterable, NAME, IteratorConstructor, next, DEFAULT, IS_SET, FORCED) {
1522           createIteratorConstructor$1(IteratorConstructor, NAME, next);
1523
1524           var getIterationMethod = function (KIND) {
1525             if (KIND === DEFAULT && defaultIterator) return defaultIterator;
1526             if (!BUGGY_SAFARI_ITERATORS && KIND in IterablePrototype) return IterablePrototype[KIND];
1527             switch (KIND) {
1528               case KEYS: return function keys() { return new IteratorConstructor(this, KIND); };
1529               case VALUES: return function values() { return new IteratorConstructor(this, KIND); };
1530               case ENTRIES: return function entries() { return new IteratorConstructor(this, KIND); };
1531             } return function () { return new IteratorConstructor(this); };
1532           };
1533
1534           var TO_STRING_TAG = NAME + ' Iterator';
1535           var INCORRECT_VALUES_NAME = false;
1536           var IterablePrototype = Iterable.prototype;
1537           var nativeIterator = IterablePrototype[ITERATOR$9]
1538             || IterablePrototype['@@iterator']
1539             || DEFAULT && IterablePrototype[DEFAULT];
1540           var defaultIterator = !BUGGY_SAFARI_ITERATORS && nativeIterator || getIterationMethod(DEFAULT);
1541           var anyNativeIterator = NAME == 'Array' ? IterablePrototype.entries || nativeIterator : nativeIterator;
1542           var CurrentIteratorPrototype, methods, KEY;
1543
1544           // fix native
1545           if (anyNativeIterator) {
1546             CurrentIteratorPrototype = getPrototypeOf$3(anyNativeIterator.call(new Iterable()));
1547             if (CurrentIteratorPrototype !== Object.prototype && CurrentIteratorPrototype.next) {
1548               if (getPrototypeOf$3(CurrentIteratorPrototype) !== IteratorPrototype) {
1549                 if (setPrototypeOf$6) {
1550                   setPrototypeOf$6(CurrentIteratorPrototype, IteratorPrototype);
1551                 } else if (!isCallable$e(CurrentIteratorPrototype[ITERATOR$9])) {
1552                   redefine$d(CurrentIteratorPrototype, ITERATOR$9, returnThis);
1553                 }
1554               }
1555               // Set @@toStringTag to native iterators
1556               setToStringTag$8(CurrentIteratorPrototype, TO_STRING_TAG, true);
1557             }
1558           }
1559
1560           // fix Array.prototype.{ values, @@iterator }.name in V8 / FF
1561           if (PROPER_FUNCTION_NAME$3 && DEFAULT == VALUES && nativeIterator && nativeIterator.name !== VALUES) {
1562             if (CONFIGURABLE_FUNCTION_NAME$1) {
1563               createNonEnumerableProperty$7(IterablePrototype, 'name', VALUES);
1564             } else {
1565               INCORRECT_VALUES_NAME = true;
1566               defaultIterator = function values() { return call$l(nativeIterator, this); };
1567             }
1568           }
1569
1570           // export additional methods
1571           if (DEFAULT) {
1572             methods = {
1573               values: getIterationMethod(VALUES),
1574               keys: IS_SET ? defaultIterator : getIterationMethod(KEYS),
1575               entries: getIterationMethod(ENTRIES)
1576             };
1577             if (FORCED) for (KEY in methods) {
1578               if (BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME || !(KEY in IterablePrototype)) {
1579                 redefine$d(IterablePrototype, KEY, methods[KEY]);
1580               }
1581             } else $$1c({ target: NAME, proto: true, forced: BUGGY_SAFARI_ITERATORS || INCORRECT_VALUES_NAME }, methods);
1582           }
1583
1584           // define iterator
1585           if (IterablePrototype[ITERATOR$9] !== defaultIterator) {
1586             redefine$d(IterablePrototype, ITERATOR$9, defaultIterator, { name: DEFAULT });
1587           }
1588           Iterators$3[NAME] = defaultIterator;
1589
1590           return methods;
1591         };
1592
1593         var toIndexedObject$8 = toIndexedObject$d;
1594         var addToUnscopables$5 = addToUnscopables$6;
1595         var Iterators$2 = iterators;
1596         var InternalStateModule$8 = internalState;
1597         var defineProperty$a = objectDefineProperty.f;
1598         var defineIterator$2 = defineIterator$3;
1599         var DESCRIPTORS$i = descriptors;
1600
1601         var ARRAY_ITERATOR = 'Array Iterator';
1602         var setInternalState$8 = InternalStateModule$8.set;
1603         var getInternalState$6 = InternalStateModule$8.getterFor(ARRAY_ITERATOR);
1604
1605         // `Array.prototype.entries` method
1606         // https://tc39.es/ecma262/#sec-array.prototype.entries
1607         // `Array.prototype.keys` method
1608         // https://tc39.es/ecma262/#sec-array.prototype.keys
1609         // `Array.prototype.values` method
1610         // https://tc39.es/ecma262/#sec-array.prototype.values
1611         // `Array.prototype[@@iterator]` method
1612         // https://tc39.es/ecma262/#sec-array.prototype-@@iterator
1613         // `CreateArrayIterator` internal method
1614         // https://tc39.es/ecma262/#sec-createarrayiterator
1615         var es_array_iterator = defineIterator$2(Array, 'Array', function (iterated, kind) {
1616           setInternalState$8(this, {
1617             type: ARRAY_ITERATOR,
1618             target: toIndexedObject$8(iterated), // target
1619             index: 0,                          // next index
1620             kind: kind                         // kind
1621           });
1622         // `%ArrayIteratorPrototype%.next` method
1623         // https://tc39.es/ecma262/#sec-%arrayiteratorprototype%.next
1624         }, function () {
1625           var state = getInternalState$6(this);
1626           var target = state.target;
1627           var kind = state.kind;
1628           var index = state.index++;
1629           if (!target || index >= target.length) {
1630             state.target = undefined;
1631             return { value: undefined, done: true };
1632           }
1633           if (kind == 'keys') return { value: index, done: false };
1634           if (kind == 'values') return { value: target[index], done: false };
1635           return { value: [index, target[index]], done: false };
1636         }, 'values');
1637
1638         // argumentsList[@@iterator] is %ArrayProto_values%
1639         // https://tc39.es/ecma262/#sec-createunmappedargumentsobject
1640         // https://tc39.es/ecma262/#sec-createmappedargumentsobject
1641         var values = Iterators$2.Arguments = Iterators$2.Array;
1642
1643         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
1644         addToUnscopables$5('keys');
1645         addToUnscopables$5('values');
1646         addToUnscopables$5('entries');
1647
1648         // V8 ~ Chrome 45- bug
1649         if (DESCRIPTORS$i && values.name !== 'values') try {
1650           defineProperty$a(values, 'name', { value: 'values' });
1651         } catch (error) { /* empty */ }
1652
1653         var wellKnownSymbol$m = wellKnownSymbol$t;
1654
1655         var TO_STRING_TAG$3 = wellKnownSymbol$m('toStringTag');
1656         var test$2 = {};
1657
1658         test$2[TO_STRING_TAG$3] = 'z';
1659
1660         var toStringTagSupport = String(test$2) === '[object z]';
1661
1662         var global$_ = global$1o;
1663         var TO_STRING_TAG_SUPPORT$2 = toStringTagSupport;
1664         var isCallable$d = isCallable$r;
1665         var classofRaw = classofRaw$1;
1666         var wellKnownSymbol$l = wellKnownSymbol$t;
1667
1668         var TO_STRING_TAG$2 = wellKnownSymbol$l('toStringTag');
1669         var Object$1 = global$_.Object;
1670
1671         // ES3 wrong here
1672         var CORRECT_ARGUMENTS = classofRaw(function () { return arguments; }()) == 'Arguments';
1673
1674         // fallback for IE11 Script Access Denied error
1675         var tryGet = function (it, key) {
1676           try {
1677             return it[key];
1678           } catch (error) { /* empty */ }
1679         };
1680
1681         // getting tag from ES6+ `Object.prototype.toString`
1682         var classof$d = TO_STRING_TAG_SUPPORT$2 ? classofRaw : function (it) {
1683           var O, tag, result;
1684           return it === undefined ? 'Undefined' : it === null ? 'Null'
1685             // @@toStringTag case
1686             : typeof (tag = tryGet(O = Object$1(it), TO_STRING_TAG$2)) == 'string' ? tag
1687             // builtinTag case
1688             : CORRECT_ARGUMENTS ? classofRaw(O)
1689             // ES3 arguments fallback
1690             : (result = classofRaw(O)) == 'Object' && isCallable$d(O.callee) ? 'Arguments' : result;
1691         };
1692
1693         var TO_STRING_TAG_SUPPORT$1 = toStringTagSupport;
1694         var classof$c = classof$d;
1695
1696         // `Object.prototype.toString` method implementation
1697         // https://tc39.es/ecma262/#sec-object.prototype.tostring
1698         var objectToString$1 = TO_STRING_TAG_SUPPORT$1 ? {}.toString : function toString() {
1699           return '[object ' + classof$c(this) + ']';
1700         };
1701
1702         var TO_STRING_TAG_SUPPORT = toStringTagSupport;
1703         var redefine$c = redefine$h.exports;
1704         var toString$l = objectToString$1;
1705
1706         // `Object.prototype.toString` method
1707         // https://tc39.es/ecma262/#sec-object.prototype.tostring
1708         if (!TO_STRING_TAG_SUPPORT) {
1709           redefine$c(Object.prototype, 'toString', toString$l, { unsafe: true });
1710         }
1711
1712         var global$Z = global$1o;
1713         var classof$b = classof$d;
1714
1715         var String$3 = global$Z.String;
1716
1717         var toString$k = function (argument) {
1718           if (classof$b(argument) === 'Symbol') throw TypeError('Cannot convert a Symbol value to a string');
1719           return String$3(argument);
1720         };
1721
1722         var uncurryThis$L = functionUncurryThis;
1723         var toIntegerOrInfinity$8 = toIntegerOrInfinity$b;
1724         var toString$j = toString$k;
1725         var requireObjectCoercible$b = requireObjectCoercible$e;
1726
1727         var charAt$8 = uncurryThis$L(''.charAt);
1728         var charCodeAt$2 = uncurryThis$L(''.charCodeAt);
1729         var stringSlice$b = uncurryThis$L(''.slice);
1730
1731         var createMethod$5 = function (CONVERT_TO_STRING) {
1732           return function ($this, pos) {
1733             var S = toString$j(requireObjectCoercible$b($this));
1734             var position = toIntegerOrInfinity$8(pos);
1735             var size = S.length;
1736             var first, second;
1737             if (position < 0 || position >= size) return CONVERT_TO_STRING ? '' : undefined;
1738             first = charCodeAt$2(S, position);
1739             return first < 0xD800 || first > 0xDBFF || position + 1 === size
1740               || (second = charCodeAt$2(S, position + 1)) < 0xDC00 || second > 0xDFFF
1741                 ? CONVERT_TO_STRING
1742                   ? charAt$8(S, position)
1743                   : first
1744                 : CONVERT_TO_STRING
1745                   ? stringSlice$b(S, position, position + 2)
1746                   : (first - 0xD800 << 10) + (second - 0xDC00) + 0x10000;
1747           };
1748         };
1749
1750         var stringMultibyte = {
1751           // `String.prototype.codePointAt` method
1752           // https://tc39.es/ecma262/#sec-string.prototype.codepointat
1753           codeAt: createMethod$5(false),
1754           // `String.prototype.at` method
1755           // https://github.com/mathiasbynens/String.prototype.at
1756           charAt: createMethod$5(true)
1757         };
1758
1759         var charAt$7 = stringMultibyte.charAt;
1760         var toString$i = toString$k;
1761         var InternalStateModule$7 = internalState;
1762         var defineIterator$1 = defineIterator$3;
1763
1764         var STRING_ITERATOR = 'String Iterator';
1765         var setInternalState$7 = InternalStateModule$7.set;
1766         var getInternalState$5 = InternalStateModule$7.getterFor(STRING_ITERATOR);
1767
1768         // `String.prototype[@@iterator]` method
1769         // https://tc39.es/ecma262/#sec-string.prototype-@@iterator
1770         defineIterator$1(String, 'String', function (iterated) {
1771           setInternalState$7(this, {
1772             type: STRING_ITERATOR,
1773             string: toString$i(iterated),
1774             index: 0
1775           });
1776         // `%StringIteratorPrototype%.next` method
1777         // https://tc39.es/ecma262/#sec-%stringiteratorprototype%.next
1778         }, function next() {
1779           var state = getInternalState$5(this);
1780           var string = state.string;
1781           var index = state.index;
1782           var point;
1783           if (index >= string.length) return { value: undefined, done: true };
1784           point = charAt$7(string, index);
1785           state.index += point.length;
1786           return { value: point, done: false };
1787         });
1788
1789         // iterable DOM collections
1790         // flag - `iterable` interface - 'entries', 'keys', 'values', 'forEach' methods
1791         var domIterables = {
1792           CSSRuleList: 0,
1793           CSSStyleDeclaration: 0,
1794           CSSValueList: 0,
1795           ClientRectList: 0,
1796           DOMRectList: 0,
1797           DOMStringList: 0,
1798           DOMTokenList: 1,
1799           DataTransferItemList: 0,
1800           FileList: 0,
1801           HTMLAllCollection: 0,
1802           HTMLCollection: 0,
1803           HTMLFormElement: 0,
1804           HTMLSelectElement: 0,
1805           MediaList: 0,
1806           MimeTypeArray: 0,
1807           NamedNodeMap: 0,
1808           NodeList: 1,
1809           PaintRequestList: 0,
1810           Plugin: 0,
1811           PluginArray: 0,
1812           SVGLengthList: 0,
1813           SVGNumberList: 0,
1814           SVGPathSegList: 0,
1815           SVGPointList: 0,
1816           SVGStringList: 0,
1817           SVGTransformList: 0,
1818           SourceBufferList: 0,
1819           StyleSheetList: 0,
1820           TextTrackCueList: 0,
1821           TextTrackList: 0,
1822           TouchList: 0
1823         };
1824
1825         // in old WebKit versions, `element.classList` is not an instance of global `DOMTokenList`
1826         var documentCreateElement = documentCreateElement$2;
1827
1828         var classList$1 = documentCreateElement('span').classList;
1829         var DOMTokenListPrototype$2 = classList$1 && classList$1.constructor && classList$1.constructor.prototype;
1830
1831         var domTokenListPrototype = DOMTokenListPrototype$2 === Object.prototype ? undefined : DOMTokenListPrototype$2;
1832
1833         var global$Y = global$1o;
1834         var DOMIterables$1 = domIterables;
1835         var DOMTokenListPrototype$1 = domTokenListPrototype;
1836         var ArrayIteratorMethods = es_array_iterator;
1837         var createNonEnumerableProperty$6 = createNonEnumerableProperty$b;
1838         var wellKnownSymbol$k = wellKnownSymbol$t;
1839
1840         var ITERATOR$8 = wellKnownSymbol$k('iterator');
1841         var TO_STRING_TAG$1 = wellKnownSymbol$k('toStringTag');
1842         var ArrayValues = ArrayIteratorMethods.values;
1843
1844         var handlePrototype$1 = function (CollectionPrototype, COLLECTION_NAME) {
1845           if (CollectionPrototype) {
1846             // some Chrome versions have non-configurable methods on DOMTokenList
1847             if (CollectionPrototype[ITERATOR$8] !== ArrayValues) try {
1848               createNonEnumerableProperty$6(CollectionPrototype, ITERATOR$8, ArrayValues);
1849             } catch (error) {
1850               CollectionPrototype[ITERATOR$8] = ArrayValues;
1851             }
1852             if (!CollectionPrototype[TO_STRING_TAG$1]) {
1853               createNonEnumerableProperty$6(CollectionPrototype, TO_STRING_TAG$1, COLLECTION_NAME);
1854             }
1855             if (DOMIterables$1[COLLECTION_NAME]) for (var METHOD_NAME in ArrayIteratorMethods) {
1856               // some Chrome versions have non-configurable methods on DOMTokenList
1857               if (CollectionPrototype[METHOD_NAME] !== ArrayIteratorMethods[METHOD_NAME]) try {
1858                 createNonEnumerableProperty$6(CollectionPrototype, METHOD_NAME, ArrayIteratorMethods[METHOD_NAME]);
1859               } catch (error) {
1860                 CollectionPrototype[METHOD_NAME] = ArrayIteratorMethods[METHOD_NAME];
1861               }
1862             }
1863           }
1864         };
1865
1866         for (var COLLECTION_NAME$1 in DOMIterables$1) {
1867           handlePrototype$1(global$Y[COLLECTION_NAME$1] && global$Y[COLLECTION_NAME$1].prototype, COLLECTION_NAME$1);
1868         }
1869
1870         handlePrototype$1(DOMTokenListPrototype$1, 'DOMTokenList');
1871
1872         var NATIVE_BIND$2 = functionBindNative;
1873
1874         var FunctionPrototype$1 = Function.prototype;
1875         var apply$9 = FunctionPrototype$1.apply;
1876         var call$k = FunctionPrototype$1.call;
1877
1878         // eslint-disable-next-line es/no-reflect -- safe
1879         var functionApply = typeof Reflect == 'object' && Reflect.apply || (NATIVE_BIND$2 ? call$k.bind(apply$9) : function () {
1880           return call$k.apply(apply$9, arguments);
1881         });
1882
1883         var classof$a = classofRaw$1;
1884
1885         // `IsArray` abstract operation
1886         // https://tc39.es/ecma262/#sec-isarray
1887         // eslint-disable-next-line es/no-array-isarray -- safe
1888         var isArray$8 = Array.isArray || function isArray(argument) {
1889           return classof$a(argument) == 'Array';
1890         };
1891
1892         var objectGetOwnPropertyNamesExternal = {};
1893
1894         var toPropertyKey$2 = toPropertyKey$5;
1895         var definePropertyModule$3 = objectDefineProperty;
1896         var createPropertyDescriptor$3 = createPropertyDescriptor$7;
1897
1898         var createProperty$5 = function (object, key, value) {
1899           var propertyKey = toPropertyKey$2(key);
1900           if (propertyKey in object) definePropertyModule$3.f(object, propertyKey, createPropertyDescriptor$3(0, value));
1901           else object[propertyKey] = value;
1902         };
1903
1904         var global$X = global$1o;
1905         var toAbsoluteIndex$7 = toAbsoluteIndex$9;
1906         var lengthOfArrayLike$g = lengthOfArrayLike$i;
1907         var createProperty$4 = createProperty$5;
1908
1909         var Array$7 = global$X.Array;
1910         var max$4 = Math.max;
1911
1912         var arraySliceSimple = function (O, start, end) {
1913           var length = lengthOfArrayLike$g(O);
1914           var k = toAbsoluteIndex$7(start, length);
1915           var fin = toAbsoluteIndex$7(end === undefined ? length : end, length);
1916           var result = Array$7(max$4(fin - k, 0));
1917           for (var n = 0; k < fin; k++, n++) createProperty$4(result, n, O[k]);
1918           result.length = n;
1919           return result;
1920         };
1921
1922         /* eslint-disable es/no-object-getownpropertynames -- safe */
1923
1924         var classof$9 = classofRaw$1;
1925         var toIndexedObject$7 = toIndexedObject$d;
1926         var $getOwnPropertyNames$1 = objectGetOwnPropertyNames.f;
1927         var arraySlice$c = arraySliceSimple;
1928
1929         var windowNames = typeof window == 'object' && window && Object.getOwnPropertyNames
1930           ? Object.getOwnPropertyNames(window) : [];
1931
1932         var getWindowNames = function (it) {
1933           try {
1934             return $getOwnPropertyNames$1(it);
1935           } catch (error) {
1936             return arraySlice$c(windowNames);
1937           }
1938         };
1939
1940         // fallback for IE11 buggy Object.getOwnPropertyNames with iframe and window
1941         objectGetOwnPropertyNamesExternal.f = function getOwnPropertyNames(it) {
1942           return windowNames && classof$9(it) == 'Window'
1943             ? getWindowNames(it)
1944             : $getOwnPropertyNames$1(toIndexedObject$7(it));
1945         };
1946
1947         var uncurryThis$K = functionUncurryThis;
1948
1949         var arraySlice$b = uncurryThis$K([].slice);
1950
1951         var uncurryThis$J = functionUncurryThis;
1952         var aCallable$8 = aCallable$a;
1953         var NATIVE_BIND$1 = functionBindNative;
1954
1955         var bind$f = uncurryThis$J(uncurryThis$J.bind);
1956
1957         // optional / simple context binding
1958         var functionBindContext = function (fn, that) {
1959           aCallable$8(fn);
1960           return that === undefined ? fn : NATIVE_BIND$1 ? bind$f(fn, that) : function (/* ...args */) {
1961             return fn.apply(that, arguments);
1962           };
1963         };
1964
1965         var uncurryThis$I = functionUncurryThis;
1966         var fails$L = fails$V;
1967         var isCallable$c = isCallable$r;
1968         var classof$8 = classof$d;
1969         var getBuiltIn$6 = getBuiltIn$b;
1970         var inspectSource$1 = inspectSource$4;
1971
1972         var noop$2 = function () { /* empty */ };
1973         var empty$1 = [];
1974         var construct$1 = getBuiltIn$6('Reflect', 'construct');
1975         var constructorRegExp = /^\s*(?:class|function)\b/;
1976         var exec$6 = uncurryThis$I(constructorRegExp.exec);
1977         var INCORRECT_TO_STRING = !constructorRegExp.exec(noop$2);
1978
1979         var isConstructorModern = function isConstructor(argument) {
1980           if (!isCallable$c(argument)) return false;
1981           try {
1982             construct$1(noop$2, empty$1, argument);
1983             return true;
1984           } catch (error) {
1985             return false;
1986           }
1987         };
1988
1989         var isConstructorLegacy = function isConstructor(argument) {
1990           if (!isCallable$c(argument)) return false;
1991           switch (classof$8(argument)) {
1992             case 'AsyncFunction':
1993             case 'GeneratorFunction':
1994             case 'AsyncGeneratorFunction': return false;
1995           }
1996           try {
1997             // we can't check .prototype since constructors produced by .bind haven't it
1998             // `Function#toString` throws on some built-it function in some legacy engines
1999             // (for example, `DOMQuad` and similar in FF41-)
2000             return INCORRECT_TO_STRING || !!exec$6(constructorRegExp, inspectSource$1(argument));
2001           } catch (error) {
2002             return true;
2003           }
2004         };
2005
2006         isConstructorLegacy.sham = true;
2007
2008         // `IsConstructor` abstract operation
2009         // https://tc39.es/ecma262/#sec-isconstructor
2010         var isConstructor$4 = !construct$1 || fails$L(function () {
2011           var called;
2012           return isConstructorModern(isConstructorModern.call)
2013             || !isConstructorModern(Object)
2014             || !isConstructorModern(function () { called = true; })
2015             || called;
2016         }) ? isConstructorLegacy : isConstructorModern;
2017
2018         var global$W = global$1o;
2019         var isArray$7 = isArray$8;
2020         var isConstructor$3 = isConstructor$4;
2021         var isObject$m = isObject$s;
2022         var wellKnownSymbol$j = wellKnownSymbol$t;
2023
2024         var SPECIES$6 = wellKnownSymbol$j('species');
2025         var Array$6 = global$W.Array;
2026
2027         // a part of `ArraySpeciesCreate` abstract operation
2028         // https://tc39.es/ecma262/#sec-arrayspeciescreate
2029         var arraySpeciesConstructor$1 = function (originalArray) {
2030           var C;
2031           if (isArray$7(originalArray)) {
2032             C = originalArray.constructor;
2033             // cross-realm fallback
2034             if (isConstructor$3(C) && (C === Array$6 || isArray$7(C.prototype))) C = undefined;
2035             else if (isObject$m(C)) {
2036               C = C[SPECIES$6];
2037               if (C === null) C = undefined;
2038             }
2039           } return C === undefined ? Array$6 : C;
2040         };
2041
2042         var arraySpeciesConstructor = arraySpeciesConstructor$1;
2043
2044         // `ArraySpeciesCreate` abstract operation
2045         // https://tc39.es/ecma262/#sec-arrayspeciescreate
2046         var arraySpeciesCreate$4 = function (originalArray, length) {
2047           return new (arraySpeciesConstructor(originalArray))(length === 0 ? 0 : length);
2048         };
2049
2050         var bind$e = functionBindContext;
2051         var uncurryThis$H = functionUncurryThis;
2052         var IndexedObject$3 = indexedObject;
2053         var toObject$f = toObject$i;
2054         var lengthOfArrayLike$f = lengthOfArrayLike$i;
2055         var arraySpeciesCreate$3 = arraySpeciesCreate$4;
2056
2057         var push$9 = uncurryThis$H([].push);
2058
2059         // `Array.prototype.{ forEach, map, filter, some, every, find, findIndex, filterReject }` methods implementation
2060         var createMethod$4 = function (TYPE) {
2061           var IS_MAP = TYPE == 1;
2062           var IS_FILTER = TYPE == 2;
2063           var IS_SOME = TYPE == 3;
2064           var IS_EVERY = TYPE == 4;
2065           var IS_FIND_INDEX = TYPE == 6;
2066           var IS_FILTER_REJECT = TYPE == 7;
2067           var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
2068           return function ($this, callbackfn, that, specificCreate) {
2069             var O = toObject$f($this);
2070             var self = IndexedObject$3(O);
2071             var boundFunction = bind$e(callbackfn, that);
2072             var length = lengthOfArrayLike$f(self);
2073             var index = 0;
2074             var create = specificCreate || arraySpeciesCreate$3;
2075             var target = IS_MAP ? create($this, length) : IS_FILTER || IS_FILTER_REJECT ? create($this, 0) : undefined;
2076             var value, result;
2077             for (;length > index; index++) if (NO_HOLES || index in self) {
2078               value = self[index];
2079               result = boundFunction(value, index, O);
2080               if (TYPE) {
2081                 if (IS_MAP) target[index] = result; // map
2082                 else if (result) switch (TYPE) {
2083                   case 3: return true;              // some
2084                   case 5: return value;             // find
2085                   case 6: return index;             // findIndex
2086                   case 2: push$9(target, value);      // filter
2087                 } else switch (TYPE) {
2088                   case 4: return false;             // every
2089                   case 7: push$9(target, value);      // filterReject
2090                 }
2091               }
2092             }
2093             return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : target;
2094           };
2095         };
2096
2097         var arrayIteration = {
2098           // `Array.prototype.forEach` method
2099           // https://tc39.es/ecma262/#sec-array.prototype.foreach
2100           forEach: createMethod$4(0),
2101           // `Array.prototype.map` method
2102           // https://tc39.es/ecma262/#sec-array.prototype.map
2103           map: createMethod$4(1),
2104           // `Array.prototype.filter` method
2105           // https://tc39.es/ecma262/#sec-array.prototype.filter
2106           filter: createMethod$4(2),
2107           // `Array.prototype.some` method
2108           // https://tc39.es/ecma262/#sec-array.prototype.some
2109           some: createMethod$4(3),
2110           // `Array.prototype.every` method
2111           // https://tc39.es/ecma262/#sec-array.prototype.every
2112           every: createMethod$4(4),
2113           // `Array.prototype.find` method
2114           // https://tc39.es/ecma262/#sec-array.prototype.find
2115           find: createMethod$4(5),
2116           // `Array.prototype.findIndex` method
2117           // https://tc39.es/ecma262/#sec-array.prototype.findIndex
2118           findIndex: createMethod$4(6),
2119           // `Array.prototype.filterReject` method
2120           // https://github.com/tc39/proposal-array-filtering
2121           filterReject: createMethod$4(7)
2122         };
2123
2124         var $$1b = _export;
2125         var global$V = global$1o;
2126         var getBuiltIn$5 = getBuiltIn$b;
2127         var apply$8 = functionApply;
2128         var call$j = functionCall;
2129         var uncurryThis$G = functionUncurryThis;
2130         var DESCRIPTORS$h = descriptors;
2131         var NATIVE_SYMBOL$1 = nativeSymbol;
2132         var fails$K = fails$V;
2133         var hasOwn$b = hasOwnProperty_1;
2134         var isArray$6 = isArray$8;
2135         var isCallable$b = isCallable$r;
2136         var isObject$l = isObject$s;
2137         var isPrototypeOf$8 = objectIsPrototypeOf;
2138         var isSymbol$3 = isSymbol$6;
2139         var anObject$h = anObject$n;
2140         var toObject$e = toObject$i;
2141         var toIndexedObject$6 = toIndexedObject$d;
2142         var toPropertyKey$1 = toPropertyKey$5;
2143         var $toString$3 = toString$k;
2144         var createPropertyDescriptor$2 = createPropertyDescriptor$7;
2145         var nativeObjectCreate = objectCreate;
2146         var objectKeys$2 = objectKeys$4;
2147         var getOwnPropertyNamesModule$1 = objectGetOwnPropertyNames;
2148         var getOwnPropertyNamesExternal = objectGetOwnPropertyNamesExternal;
2149         var getOwnPropertySymbolsModule$1 = objectGetOwnPropertySymbols;
2150         var getOwnPropertyDescriptorModule$2 = objectGetOwnPropertyDescriptor;
2151         var definePropertyModule$2 = objectDefineProperty;
2152         var definePropertiesModule = objectDefineProperties;
2153         var propertyIsEnumerableModule$1 = objectPropertyIsEnumerable;
2154         var arraySlice$a = arraySlice$b;
2155         var redefine$b = redefine$h.exports;
2156         var shared$1 = shared$5.exports;
2157         var sharedKey = sharedKey$4;
2158         var hiddenKeys$1 = hiddenKeys$6;
2159         var uid$2 = uid$5;
2160         var wellKnownSymbol$i = wellKnownSymbol$t;
2161         var wrappedWellKnownSymbolModule = wellKnownSymbolWrapped;
2162         var defineWellKnownSymbol$2 = defineWellKnownSymbol$4;
2163         var setToStringTag$7 = setToStringTag$a;
2164         var InternalStateModule$6 = internalState;
2165         var $forEach$2 = arrayIteration.forEach;
2166
2167         var HIDDEN = sharedKey('hidden');
2168         var SYMBOL = 'Symbol';
2169         var PROTOTYPE$1 = 'prototype';
2170         var TO_PRIMITIVE = wellKnownSymbol$i('toPrimitive');
2171
2172         var setInternalState$6 = InternalStateModule$6.set;
2173         var getInternalState$4 = InternalStateModule$6.getterFor(SYMBOL);
2174
2175         var ObjectPrototype$3 = Object[PROTOTYPE$1];
2176         var $Symbol = global$V.Symbol;
2177         var SymbolPrototype$1 = $Symbol && $Symbol[PROTOTYPE$1];
2178         var TypeError$h = global$V.TypeError;
2179         var QObject = global$V.QObject;
2180         var $stringify = getBuiltIn$5('JSON', 'stringify');
2181         var nativeGetOwnPropertyDescriptor$2 = getOwnPropertyDescriptorModule$2.f;
2182         var nativeDefineProperty$1 = definePropertyModule$2.f;
2183         var nativeGetOwnPropertyNames = getOwnPropertyNamesExternal.f;
2184         var nativePropertyIsEnumerable = propertyIsEnumerableModule$1.f;
2185         var push$8 = uncurryThis$G([].push);
2186
2187         var AllSymbols = shared$1('symbols');
2188         var ObjectPrototypeSymbols = shared$1('op-symbols');
2189         var StringToSymbolRegistry = shared$1('string-to-symbol-registry');
2190         var SymbolToStringRegistry = shared$1('symbol-to-string-registry');
2191         var WellKnownSymbolsStore = shared$1('wks');
2192
2193         // Don't use setters in Qt Script, https://github.com/zloirock/core-js/issues/173
2194         var USE_SETTER = !QObject || !QObject[PROTOTYPE$1] || !QObject[PROTOTYPE$1].findChild;
2195
2196         // fallback for old Android, https://code.google.com/p/v8/issues/detail?id=687
2197         var setSymbolDescriptor = DESCRIPTORS$h && fails$K(function () {
2198           return nativeObjectCreate(nativeDefineProperty$1({}, 'a', {
2199             get: function () { return nativeDefineProperty$1(this, 'a', { value: 7 }).a; }
2200           })).a != 7;
2201         }) ? function (O, P, Attributes) {
2202           var ObjectPrototypeDescriptor = nativeGetOwnPropertyDescriptor$2(ObjectPrototype$3, P);
2203           if (ObjectPrototypeDescriptor) delete ObjectPrototype$3[P];
2204           nativeDefineProperty$1(O, P, Attributes);
2205           if (ObjectPrototypeDescriptor && O !== ObjectPrototype$3) {
2206             nativeDefineProperty$1(ObjectPrototype$3, P, ObjectPrototypeDescriptor);
2207           }
2208         } : nativeDefineProperty$1;
2209
2210         var wrap$2 = function (tag, description) {
2211           var symbol = AllSymbols[tag] = nativeObjectCreate(SymbolPrototype$1);
2212           setInternalState$6(symbol, {
2213             type: SYMBOL,
2214             tag: tag,
2215             description: description
2216           });
2217           if (!DESCRIPTORS$h) symbol.description = description;
2218           return symbol;
2219         };
2220
2221         var $defineProperty = function defineProperty(O, P, Attributes) {
2222           if (O === ObjectPrototype$3) $defineProperty(ObjectPrototypeSymbols, P, Attributes);
2223           anObject$h(O);
2224           var key = toPropertyKey$1(P);
2225           anObject$h(Attributes);
2226           if (hasOwn$b(AllSymbols, key)) {
2227             if (!Attributes.enumerable) {
2228               if (!hasOwn$b(O, HIDDEN)) nativeDefineProperty$1(O, HIDDEN, createPropertyDescriptor$2(1, {}));
2229               O[HIDDEN][key] = true;
2230             } else {
2231               if (hasOwn$b(O, HIDDEN) && O[HIDDEN][key]) O[HIDDEN][key] = false;
2232               Attributes = nativeObjectCreate(Attributes, { enumerable: createPropertyDescriptor$2(0, false) });
2233             } return setSymbolDescriptor(O, key, Attributes);
2234           } return nativeDefineProperty$1(O, key, Attributes);
2235         };
2236
2237         var $defineProperties = function defineProperties(O, Properties) {
2238           anObject$h(O);
2239           var properties = toIndexedObject$6(Properties);
2240           var keys = objectKeys$2(properties).concat($getOwnPropertySymbols(properties));
2241           $forEach$2(keys, function (key) {
2242             if (!DESCRIPTORS$h || call$j($propertyIsEnumerable$1, properties, key)) $defineProperty(O, key, properties[key]);
2243           });
2244           return O;
2245         };
2246
2247         var $create = function create(O, Properties) {
2248           return Properties === undefined ? nativeObjectCreate(O) : $defineProperties(nativeObjectCreate(O), Properties);
2249         };
2250
2251         var $propertyIsEnumerable$1 = function propertyIsEnumerable(V) {
2252           var P = toPropertyKey$1(V);
2253           var enumerable = call$j(nativePropertyIsEnumerable, this, P);
2254           if (this === ObjectPrototype$3 && hasOwn$b(AllSymbols, P) && !hasOwn$b(ObjectPrototypeSymbols, P)) return false;
2255           return enumerable || !hasOwn$b(this, P) || !hasOwn$b(AllSymbols, P) || hasOwn$b(this, HIDDEN) && this[HIDDEN][P]
2256             ? enumerable : true;
2257         };
2258
2259         var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(O, P) {
2260           var it = toIndexedObject$6(O);
2261           var key = toPropertyKey$1(P);
2262           if (it === ObjectPrototype$3 && hasOwn$b(AllSymbols, key) && !hasOwn$b(ObjectPrototypeSymbols, key)) return;
2263           var descriptor = nativeGetOwnPropertyDescriptor$2(it, key);
2264           if (descriptor && hasOwn$b(AllSymbols, key) && !(hasOwn$b(it, HIDDEN) && it[HIDDEN][key])) {
2265             descriptor.enumerable = true;
2266           }
2267           return descriptor;
2268         };
2269
2270         var $getOwnPropertyNames = function getOwnPropertyNames(O) {
2271           var names = nativeGetOwnPropertyNames(toIndexedObject$6(O));
2272           var result = [];
2273           $forEach$2(names, function (key) {
2274             if (!hasOwn$b(AllSymbols, key) && !hasOwn$b(hiddenKeys$1, key)) push$8(result, key);
2275           });
2276           return result;
2277         };
2278
2279         var $getOwnPropertySymbols = function getOwnPropertySymbols(O) {
2280           var IS_OBJECT_PROTOTYPE = O === ObjectPrototype$3;
2281           var names = nativeGetOwnPropertyNames(IS_OBJECT_PROTOTYPE ? ObjectPrototypeSymbols : toIndexedObject$6(O));
2282           var result = [];
2283           $forEach$2(names, function (key) {
2284             if (hasOwn$b(AllSymbols, key) && (!IS_OBJECT_PROTOTYPE || hasOwn$b(ObjectPrototype$3, key))) {
2285               push$8(result, AllSymbols[key]);
2286             }
2287           });
2288           return result;
2289         };
2290
2291         // `Symbol` constructor
2292         // https://tc39.es/ecma262/#sec-symbol-constructor
2293         if (!NATIVE_SYMBOL$1) {
2294           $Symbol = function Symbol() {
2295             if (isPrototypeOf$8(SymbolPrototype$1, this)) throw TypeError$h('Symbol is not a constructor');
2296             var description = !arguments.length || arguments[0] === undefined ? undefined : $toString$3(arguments[0]);
2297             var tag = uid$2(description);
2298             var setter = function (value) {
2299               if (this === ObjectPrototype$3) call$j(setter, ObjectPrototypeSymbols, value);
2300               if (hasOwn$b(this, HIDDEN) && hasOwn$b(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
2301               setSymbolDescriptor(this, tag, createPropertyDescriptor$2(1, value));
2302             };
2303             if (DESCRIPTORS$h && USE_SETTER) setSymbolDescriptor(ObjectPrototype$3, tag, { configurable: true, set: setter });
2304             return wrap$2(tag, description);
2305           };
2306
2307           SymbolPrototype$1 = $Symbol[PROTOTYPE$1];
2308
2309           redefine$b(SymbolPrototype$1, 'toString', function toString() {
2310             return getInternalState$4(this).tag;
2311           });
2312
2313           redefine$b($Symbol, 'withoutSetter', function (description) {
2314             return wrap$2(uid$2(description), description);
2315           });
2316
2317           propertyIsEnumerableModule$1.f = $propertyIsEnumerable$1;
2318           definePropertyModule$2.f = $defineProperty;
2319           definePropertiesModule.f = $defineProperties;
2320           getOwnPropertyDescriptorModule$2.f = $getOwnPropertyDescriptor;
2321           getOwnPropertyNamesModule$1.f = getOwnPropertyNamesExternal.f = $getOwnPropertyNames;
2322           getOwnPropertySymbolsModule$1.f = $getOwnPropertySymbols;
2323
2324           wrappedWellKnownSymbolModule.f = function (name) {
2325             return wrap$2(wellKnownSymbol$i(name), name);
2326           };
2327
2328           if (DESCRIPTORS$h) {
2329             // https://github.com/tc39/proposal-Symbol-description
2330             nativeDefineProperty$1(SymbolPrototype$1, 'description', {
2331               configurable: true,
2332               get: function description() {
2333                 return getInternalState$4(this).description;
2334               }
2335             });
2336             {
2337               redefine$b(ObjectPrototype$3, 'propertyIsEnumerable', $propertyIsEnumerable$1, { unsafe: true });
2338             }
2339           }
2340         }
2341
2342         $$1b({ global: true, wrap: true, forced: !NATIVE_SYMBOL$1, sham: !NATIVE_SYMBOL$1 }, {
2343           Symbol: $Symbol
2344         });
2345
2346         $forEach$2(objectKeys$2(WellKnownSymbolsStore), function (name) {
2347           defineWellKnownSymbol$2(name);
2348         });
2349
2350         $$1b({ target: SYMBOL, stat: true, forced: !NATIVE_SYMBOL$1 }, {
2351           // `Symbol.for` method
2352           // https://tc39.es/ecma262/#sec-symbol.for
2353           'for': function (key) {
2354             var string = $toString$3(key);
2355             if (hasOwn$b(StringToSymbolRegistry, string)) return StringToSymbolRegistry[string];
2356             var symbol = $Symbol(string);
2357             StringToSymbolRegistry[string] = symbol;
2358             SymbolToStringRegistry[symbol] = string;
2359             return symbol;
2360           },
2361           // `Symbol.keyFor` method
2362           // https://tc39.es/ecma262/#sec-symbol.keyfor
2363           keyFor: function keyFor(sym) {
2364             if (!isSymbol$3(sym)) throw TypeError$h(sym + ' is not a symbol');
2365             if (hasOwn$b(SymbolToStringRegistry, sym)) return SymbolToStringRegistry[sym];
2366           },
2367           useSetter: function () { USE_SETTER = true; },
2368           useSimple: function () { USE_SETTER = false; }
2369         });
2370
2371         $$1b({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$1, sham: !DESCRIPTORS$h }, {
2372           // `Object.create` method
2373           // https://tc39.es/ecma262/#sec-object.create
2374           create: $create,
2375           // `Object.defineProperty` method
2376           // https://tc39.es/ecma262/#sec-object.defineproperty
2377           defineProperty: $defineProperty,
2378           // `Object.defineProperties` method
2379           // https://tc39.es/ecma262/#sec-object.defineproperties
2380           defineProperties: $defineProperties,
2381           // `Object.getOwnPropertyDescriptor` method
2382           // https://tc39.es/ecma262/#sec-object.getownpropertydescriptors
2383           getOwnPropertyDescriptor: $getOwnPropertyDescriptor
2384         });
2385
2386         $$1b({ target: 'Object', stat: true, forced: !NATIVE_SYMBOL$1 }, {
2387           // `Object.getOwnPropertyNames` method
2388           // https://tc39.es/ecma262/#sec-object.getownpropertynames
2389           getOwnPropertyNames: $getOwnPropertyNames,
2390           // `Object.getOwnPropertySymbols` method
2391           // https://tc39.es/ecma262/#sec-object.getownpropertysymbols
2392           getOwnPropertySymbols: $getOwnPropertySymbols
2393         });
2394
2395         // Chrome 38 and 39 `Object.getOwnPropertySymbols` fails on primitives
2396         // https://bugs.chromium.org/p/v8/issues/detail?id=3443
2397         $$1b({ target: 'Object', stat: true, forced: fails$K(function () { getOwnPropertySymbolsModule$1.f(1); }) }, {
2398           getOwnPropertySymbols: function getOwnPropertySymbols(it) {
2399             return getOwnPropertySymbolsModule$1.f(toObject$e(it));
2400           }
2401         });
2402
2403         // `JSON.stringify` method behavior with symbols
2404         // https://tc39.es/ecma262/#sec-json.stringify
2405         if ($stringify) {
2406           var FORCED_JSON_STRINGIFY = !NATIVE_SYMBOL$1 || fails$K(function () {
2407             var symbol = $Symbol();
2408             // MS Edge converts symbol values to JSON as {}
2409             return $stringify([symbol]) != '[null]'
2410               // WebKit converts symbol values to JSON as null
2411               || $stringify({ a: symbol }) != '{}'
2412               // V8 throws on boxed symbols
2413               || $stringify(Object(symbol)) != '{}';
2414           });
2415
2416           $$1b({ target: 'JSON', stat: true, forced: FORCED_JSON_STRINGIFY }, {
2417             // eslint-disable-next-line no-unused-vars -- required for `.length`
2418             stringify: function stringify(it, replacer, space) {
2419               var args = arraySlice$a(arguments);
2420               var $replacer = replacer;
2421               if (!isObject$l(replacer) && it === undefined || isSymbol$3(it)) return; // IE8 returns string on undefined
2422               if (!isArray$6(replacer)) replacer = function (key, value) {
2423                 if (isCallable$b($replacer)) value = call$j($replacer, this, key, value);
2424                 if (!isSymbol$3(value)) return value;
2425               };
2426               args[1] = replacer;
2427               return apply$8($stringify, null, args);
2428             }
2429           });
2430         }
2431
2432         // `Symbol.prototype[@@toPrimitive]` method
2433         // https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
2434         if (!SymbolPrototype$1[TO_PRIMITIVE]) {
2435           var valueOf = SymbolPrototype$1.valueOf;
2436           // eslint-disable-next-line no-unused-vars -- required for .length
2437           redefine$b(SymbolPrototype$1, TO_PRIMITIVE, function (hint) {
2438             // TODO: improve hint logic
2439             return call$j(valueOf, this);
2440           });
2441         }
2442         // `Symbol.prototype[@@toStringTag]` property
2443         // https://tc39.es/ecma262/#sec-symbol.prototype-@@tostringtag
2444         setToStringTag$7($Symbol, SYMBOL);
2445
2446         hiddenKeys$1[HIDDEN] = true;
2447
2448         var $$1a = _export;
2449         var DESCRIPTORS$g = descriptors;
2450         var global$U = global$1o;
2451         var uncurryThis$F = functionUncurryThis;
2452         var hasOwn$a = hasOwnProperty_1;
2453         var isCallable$a = isCallable$r;
2454         var isPrototypeOf$7 = objectIsPrototypeOf;
2455         var toString$h = toString$k;
2456         var defineProperty$9 = objectDefineProperty.f;
2457         var copyConstructorProperties = copyConstructorProperties$2;
2458
2459         var NativeSymbol = global$U.Symbol;
2460         var SymbolPrototype = NativeSymbol && NativeSymbol.prototype;
2461
2462         if (DESCRIPTORS$g && isCallable$a(NativeSymbol) && (!('description' in SymbolPrototype) ||
2463           // Safari 12 bug
2464           NativeSymbol().description !== undefined
2465         )) {
2466           var EmptyStringDescriptionStore = {};
2467           // wrap Symbol constructor for correct work with undefined description
2468           var SymbolWrapper = function Symbol() {
2469             var description = arguments.length < 1 || arguments[0] === undefined ? undefined : toString$h(arguments[0]);
2470             var result = isPrototypeOf$7(SymbolPrototype, this)
2471               ? new NativeSymbol(description)
2472               // in Edge 13, String(Symbol(undefined)) === 'Symbol(undefined)'
2473               : description === undefined ? NativeSymbol() : NativeSymbol(description);
2474             if (description === '') EmptyStringDescriptionStore[result] = true;
2475             return result;
2476           };
2477
2478           copyConstructorProperties(SymbolWrapper, NativeSymbol);
2479           SymbolWrapper.prototype = SymbolPrototype;
2480           SymbolPrototype.constructor = SymbolWrapper;
2481
2482           var NATIVE_SYMBOL = String(NativeSymbol('test')) == 'Symbol(test)';
2483           var symbolToString$1 = uncurryThis$F(SymbolPrototype.toString);
2484           var symbolValueOf = uncurryThis$F(SymbolPrototype.valueOf);
2485           var regexp = /^Symbol\((.*)\)[^)]+$/;
2486           var replace$8 = uncurryThis$F(''.replace);
2487           var stringSlice$a = uncurryThis$F(''.slice);
2488
2489           defineProperty$9(SymbolPrototype, 'description', {
2490             configurable: true,
2491             get: function description() {
2492               var symbol = symbolValueOf(this);
2493               var string = symbolToString$1(symbol);
2494               if (hasOwn$a(EmptyStringDescriptionStore, symbol)) return '';
2495               var desc = NATIVE_SYMBOL ? stringSlice$a(string, 7, -1) : replace$8(string, regexp, '$1');
2496               return desc === '' ? undefined : desc;
2497             }
2498           });
2499
2500           $$1a({ global: true, forced: true }, {
2501             Symbol: SymbolWrapper
2502           });
2503         }
2504
2505         // eslint-disable-next-line es/no-typed-arrays -- safe
2506         var arrayBufferNative = typeof ArrayBuffer != 'undefined' && typeof DataView != 'undefined';
2507
2508         var redefine$a = redefine$h.exports;
2509
2510         var redefineAll$4 = function (target, src, options) {
2511           for (var key in src) redefine$a(target, key, src[key], options);
2512           return target;
2513         };
2514
2515         var global$T = global$1o;
2516         var isPrototypeOf$6 = objectIsPrototypeOf;
2517
2518         var TypeError$g = global$T.TypeError;
2519
2520         var anInstance$7 = function (it, Prototype) {
2521           if (isPrototypeOf$6(Prototype, it)) return it;
2522           throw TypeError$g('Incorrect invocation');
2523         };
2524
2525         var global$S = global$1o;
2526         var toIntegerOrInfinity$7 = toIntegerOrInfinity$b;
2527         var toLength$a = toLength$c;
2528
2529         var RangeError$b = global$S.RangeError;
2530
2531         // `ToIndex` abstract operation
2532         // https://tc39.es/ecma262/#sec-toindex
2533         var toIndex$2 = function (it) {
2534           if (it === undefined) return 0;
2535           var number = toIntegerOrInfinity$7(it);
2536           var length = toLength$a(number);
2537           if (number !== length) throw RangeError$b('Wrong length or index');
2538           return length;
2539         };
2540
2541         // IEEE754 conversions based on https://github.com/feross/ieee754
2542         var global$R = global$1o;
2543
2544         var Array$5 = global$R.Array;
2545         var abs$4 = Math.abs;
2546         var pow$2 = Math.pow;
2547         var floor$7 = Math.floor;
2548         var log$2 = Math.log;
2549         var LN2 = Math.LN2;
2550
2551         var pack = function (number, mantissaLength, bytes) {
2552           var buffer = Array$5(bytes);
2553           var exponentLength = bytes * 8 - mantissaLength - 1;
2554           var eMax = (1 << exponentLength) - 1;
2555           var eBias = eMax >> 1;
2556           var rt = mantissaLength === 23 ? pow$2(2, -24) - pow$2(2, -77) : 0;
2557           var sign = number < 0 || number === 0 && 1 / number < 0 ? 1 : 0;
2558           var index = 0;
2559           var exponent, mantissa, c;
2560           number = abs$4(number);
2561           // eslint-disable-next-line no-self-compare -- NaN check
2562           if (number != number || number === Infinity) {
2563             // eslint-disable-next-line no-self-compare -- NaN check
2564             mantissa = number != number ? 1 : 0;
2565             exponent = eMax;
2566           } else {
2567             exponent = floor$7(log$2(number) / LN2);
2568             c = pow$2(2, -exponent);
2569             if (number * c < 1) {
2570               exponent--;
2571               c *= 2;
2572             }
2573             if (exponent + eBias >= 1) {
2574               number += rt / c;
2575             } else {
2576               number += rt * pow$2(2, 1 - eBias);
2577             }
2578             if (number * c >= 2) {
2579               exponent++;
2580               c /= 2;
2581             }
2582             if (exponent + eBias >= eMax) {
2583               mantissa = 0;
2584               exponent = eMax;
2585             } else if (exponent + eBias >= 1) {
2586               mantissa = (number * c - 1) * pow$2(2, mantissaLength);
2587               exponent = exponent + eBias;
2588             } else {
2589               mantissa = number * pow$2(2, eBias - 1) * pow$2(2, mantissaLength);
2590               exponent = 0;
2591             }
2592           }
2593           while (mantissaLength >= 8) {
2594             buffer[index++] = mantissa & 255;
2595             mantissa /= 256;
2596             mantissaLength -= 8;
2597           }
2598           exponent = exponent << mantissaLength | mantissa;
2599           exponentLength += mantissaLength;
2600           while (exponentLength > 0) {
2601             buffer[index++] = exponent & 255;
2602             exponent /= 256;
2603             exponentLength -= 8;
2604           }
2605           buffer[--index] |= sign * 128;
2606           return buffer;
2607         };
2608
2609         var unpack = function (buffer, mantissaLength) {
2610           var bytes = buffer.length;
2611           var exponentLength = bytes * 8 - mantissaLength - 1;
2612           var eMax = (1 << exponentLength) - 1;
2613           var eBias = eMax >> 1;
2614           var nBits = exponentLength - 7;
2615           var index = bytes - 1;
2616           var sign = buffer[index--];
2617           var exponent = sign & 127;
2618           var mantissa;
2619           sign >>= 7;
2620           while (nBits > 0) {
2621             exponent = exponent * 256 + buffer[index--];
2622             nBits -= 8;
2623           }
2624           mantissa = exponent & (1 << -nBits) - 1;
2625           exponent >>= -nBits;
2626           nBits += mantissaLength;
2627           while (nBits > 0) {
2628             mantissa = mantissa * 256 + buffer[index--];
2629             nBits -= 8;
2630           }
2631           if (exponent === 0) {
2632             exponent = 1 - eBias;
2633           } else if (exponent === eMax) {
2634             return mantissa ? NaN : sign ? -Infinity : Infinity;
2635           } else {
2636             mantissa = mantissa + pow$2(2, mantissaLength);
2637             exponent = exponent - eBias;
2638           } return (sign ? -1 : 1) * mantissa * pow$2(2, exponent - mantissaLength);
2639         };
2640
2641         var ieee754$2 = {
2642           pack: pack,
2643           unpack: unpack
2644         };
2645
2646         var toObject$d = toObject$i;
2647         var toAbsoluteIndex$6 = toAbsoluteIndex$9;
2648         var lengthOfArrayLike$e = lengthOfArrayLike$i;
2649
2650         // `Array.prototype.fill` method implementation
2651         // https://tc39.es/ecma262/#sec-array.prototype.fill
2652         var arrayFill$1 = function fill(value /* , start = 0, end = @length */) {
2653           var O = toObject$d(this);
2654           var length = lengthOfArrayLike$e(O);
2655           var argumentsLength = arguments.length;
2656           var index = toAbsoluteIndex$6(argumentsLength > 1 ? arguments[1] : undefined, length);
2657           var end = argumentsLength > 2 ? arguments[2] : undefined;
2658           var endPos = end === undefined ? length : toAbsoluteIndex$6(end, length);
2659           while (endPos > index) O[index++] = value;
2660           return O;
2661         };
2662
2663         var global$Q = global$1o;
2664         var uncurryThis$E = functionUncurryThis;
2665         var DESCRIPTORS$f = descriptors;
2666         var NATIVE_ARRAY_BUFFER$2 = arrayBufferNative;
2667         var FunctionName = functionName;
2668         var createNonEnumerableProperty$5 = createNonEnumerableProperty$b;
2669         var redefineAll$3 = redefineAll$4;
2670         var fails$J = fails$V;
2671         var anInstance$6 = anInstance$7;
2672         var toIntegerOrInfinity$6 = toIntegerOrInfinity$b;
2673         var toLength$9 = toLength$c;
2674         var toIndex$1 = toIndex$2;
2675         var IEEE754 = ieee754$2;
2676         var getPrototypeOf$2 = objectGetPrototypeOf;
2677         var setPrototypeOf$5 = objectSetPrototypeOf;
2678         var getOwnPropertyNames$4 = objectGetOwnPropertyNames.f;
2679         var defineProperty$8 = objectDefineProperty.f;
2680         var arrayFill = arrayFill$1;
2681         var arraySlice$9 = arraySliceSimple;
2682         var setToStringTag$6 = setToStringTag$a;
2683         var InternalStateModule$5 = internalState;
2684
2685         var PROPER_FUNCTION_NAME$2 = FunctionName.PROPER;
2686         var CONFIGURABLE_FUNCTION_NAME = FunctionName.CONFIGURABLE;
2687         var getInternalState$3 = InternalStateModule$5.get;
2688         var setInternalState$5 = InternalStateModule$5.set;
2689         var ARRAY_BUFFER$1 = 'ArrayBuffer';
2690         var DATA_VIEW = 'DataView';
2691         var PROTOTYPE = 'prototype';
2692         var WRONG_LENGTH$1 = 'Wrong length';
2693         var WRONG_INDEX = 'Wrong index';
2694         var NativeArrayBuffer$1 = global$Q[ARRAY_BUFFER$1];
2695         var $ArrayBuffer = NativeArrayBuffer$1;
2696         var ArrayBufferPrototype$1 = $ArrayBuffer && $ArrayBuffer[PROTOTYPE];
2697         var $DataView = global$Q[DATA_VIEW];
2698         var DataViewPrototype$1 = $DataView && $DataView[PROTOTYPE];
2699         var ObjectPrototype$2 = Object.prototype;
2700         var Array$4 = global$Q.Array;
2701         var RangeError$a = global$Q.RangeError;
2702         var fill$1 = uncurryThis$E(arrayFill);
2703         var reverse = uncurryThis$E([].reverse);
2704
2705         var packIEEE754 = IEEE754.pack;
2706         var unpackIEEE754 = IEEE754.unpack;
2707
2708         var packInt8 = function (number) {
2709           return [number & 0xFF];
2710         };
2711
2712         var packInt16 = function (number) {
2713           return [number & 0xFF, number >> 8 & 0xFF];
2714         };
2715
2716         var packInt32 = function (number) {
2717           return [number & 0xFF, number >> 8 & 0xFF, number >> 16 & 0xFF, number >> 24 & 0xFF];
2718         };
2719
2720         var unpackInt32 = function (buffer) {
2721           return buffer[3] << 24 | buffer[2] << 16 | buffer[1] << 8 | buffer[0];
2722         };
2723
2724         var packFloat32 = function (number) {
2725           return packIEEE754(number, 23, 4);
2726         };
2727
2728         var packFloat64 = function (number) {
2729           return packIEEE754(number, 52, 8);
2730         };
2731
2732         var addGetter$1 = function (Constructor, key) {
2733           defineProperty$8(Constructor[PROTOTYPE], key, { get: function () { return getInternalState$3(this)[key]; } });
2734         };
2735
2736         var get$4 = function (view, count, index, isLittleEndian) {
2737           var intIndex = toIndex$1(index);
2738           var store = getInternalState$3(view);
2739           if (intIndex + count > store.byteLength) throw RangeError$a(WRONG_INDEX);
2740           var bytes = getInternalState$3(store.buffer).bytes;
2741           var start = intIndex + store.byteOffset;
2742           var pack = arraySlice$9(bytes, start, start + count);
2743           return isLittleEndian ? pack : reverse(pack);
2744         };
2745
2746         var set$3 = function (view, count, index, conversion, value, isLittleEndian) {
2747           var intIndex = toIndex$1(index);
2748           var store = getInternalState$3(view);
2749           if (intIndex + count > store.byteLength) throw RangeError$a(WRONG_INDEX);
2750           var bytes = getInternalState$3(store.buffer).bytes;
2751           var start = intIndex + store.byteOffset;
2752           var pack = conversion(+value);
2753           for (var i = 0; i < count; i++) bytes[start + i] = pack[isLittleEndian ? i : count - i - 1];
2754         };
2755
2756         if (!NATIVE_ARRAY_BUFFER$2) {
2757           $ArrayBuffer = function ArrayBuffer(length) {
2758             anInstance$6(this, ArrayBufferPrototype$1);
2759             var byteLength = toIndex$1(length);
2760             setInternalState$5(this, {
2761               bytes: fill$1(Array$4(byteLength), 0),
2762               byteLength: byteLength
2763             });
2764             if (!DESCRIPTORS$f) this.byteLength = byteLength;
2765           };
2766
2767           ArrayBufferPrototype$1 = $ArrayBuffer[PROTOTYPE];
2768
2769           $DataView = function DataView(buffer, byteOffset, byteLength) {
2770             anInstance$6(this, DataViewPrototype$1);
2771             anInstance$6(buffer, ArrayBufferPrototype$1);
2772             var bufferLength = getInternalState$3(buffer).byteLength;
2773             var offset = toIntegerOrInfinity$6(byteOffset);
2774             if (offset < 0 || offset > bufferLength) throw RangeError$a('Wrong offset');
2775             byteLength = byteLength === undefined ? bufferLength - offset : toLength$9(byteLength);
2776             if (offset + byteLength > bufferLength) throw RangeError$a(WRONG_LENGTH$1);
2777             setInternalState$5(this, {
2778               buffer: buffer,
2779               byteLength: byteLength,
2780               byteOffset: offset
2781             });
2782             if (!DESCRIPTORS$f) {
2783               this.buffer = buffer;
2784               this.byteLength = byteLength;
2785               this.byteOffset = offset;
2786             }
2787           };
2788
2789           DataViewPrototype$1 = $DataView[PROTOTYPE];
2790
2791           if (DESCRIPTORS$f) {
2792             addGetter$1($ArrayBuffer, 'byteLength');
2793             addGetter$1($DataView, 'buffer');
2794             addGetter$1($DataView, 'byteLength');
2795             addGetter$1($DataView, 'byteOffset');
2796           }
2797
2798           redefineAll$3(DataViewPrototype$1, {
2799             getInt8: function getInt8(byteOffset) {
2800               return get$4(this, 1, byteOffset)[0] << 24 >> 24;
2801             },
2802             getUint8: function getUint8(byteOffset) {
2803               return get$4(this, 1, byteOffset)[0];
2804             },
2805             getInt16: function getInt16(byteOffset /* , littleEndian */) {
2806               var bytes = get$4(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : undefined);
2807               return (bytes[1] << 8 | bytes[0]) << 16 >> 16;
2808             },
2809             getUint16: function getUint16(byteOffset /* , littleEndian */) {
2810               var bytes = get$4(this, 2, byteOffset, arguments.length > 1 ? arguments[1] : undefined);
2811               return bytes[1] << 8 | bytes[0];
2812             },
2813             getInt32: function getInt32(byteOffset /* , littleEndian */) {
2814               return unpackInt32(get$4(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined));
2815             },
2816             getUint32: function getUint32(byteOffset /* , littleEndian */) {
2817               return unpackInt32(get$4(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined)) >>> 0;
2818             },
2819             getFloat32: function getFloat32(byteOffset /* , littleEndian */) {
2820               return unpackIEEE754(get$4(this, 4, byteOffset, arguments.length > 1 ? arguments[1] : undefined), 23);
2821             },
2822             getFloat64: function getFloat64(byteOffset /* , littleEndian */) {
2823               return unpackIEEE754(get$4(this, 8, byteOffset, arguments.length > 1 ? arguments[1] : undefined), 52);
2824             },
2825             setInt8: function setInt8(byteOffset, value) {
2826               set$3(this, 1, byteOffset, packInt8, value);
2827             },
2828             setUint8: function setUint8(byteOffset, value) {
2829               set$3(this, 1, byteOffset, packInt8, value);
2830             },
2831             setInt16: function setInt16(byteOffset, value /* , littleEndian */) {
2832               set$3(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : undefined);
2833             },
2834             setUint16: function setUint16(byteOffset, value /* , littleEndian */) {
2835               set$3(this, 2, byteOffset, packInt16, value, arguments.length > 2 ? arguments[2] : undefined);
2836             },
2837             setInt32: function setInt32(byteOffset, value /* , littleEndian */) {
2838               set$3(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : undefined);
2839             },
2840             setUint32: function setUint32(byteOffset, value /* , littleEndian */) {
2841               set$3(this, 4, byteOffset, packInt32, value, arguments.length > 2 ? arguments[2] : undefined);
2842             },
2843             setFloat32: function setFloat32(byteOffset, value /* , littleEndian */) {
2844               set$3(this, 4, byteOffset, packFloat32, value, arguments.length > 2 ? arguments[2] : undefined);
2845             },
2846             setFloat64: function setFloat64(byteOffset, value /* , littleEndian */) {
2847               set$3(this, 8, byteOffset, packFloat64, value, arguments.length > 2 ? arguments[2] : undefined);
2848             }
2849           });
2850         } else {
2851           var INCORRECT_ARRAY_BUFFER_NAME = PROPER_FUNCTION_NAME$2 && NativeArrayBuffer$1.name !== ARRAY_BUFFER$1;
2852           /* eslint-disable no-new -- required for testing */
2853           if (!fails$J(function () {
2854             NativeArrayBuffer$1(1);
2855           }) || !fails$J(function () {
2856             new NativeArrayBuffer$1(-1);
2857           }) || fails$J(function () {
2858             new NativeArrayBuffer$1();
2859             new NativeArrayBuffer$1(1.5);
2860             new NativeArrayBuffer$1(NaN);
2861             return INCORRECT_ARRAY_BUFFER_NAME && !CONFIGURABLE_FUNCTION_NAME;
2862           })) {
2863           /* eslint-enable no-new -- required for testing */
2864             $ArrayBuffer = function ArrayBuffer(length) {
2865               anInstance$6(this, ArrayBufferPrototype$1);
2866               return new NativeArrayBuffer$1(toIndex$1(length));
2867             };
2868
2869             $ArrayBuffer[PROTOTYPE] = ArrayBufferPrototype$1;
2870
2871             for (var keys$2 = getOwnPropertyNames$4(NativeArrayBuffer$1), j$2 = 0, key$1; keys$2.length > j$2;) {
2872               if (!((key$1 = keys$2[j$2++]) in $ArrayBuffer)) {
2873                 createNonEnumerableProperty$5($ArrayBuffer, key$1, NativeArrayBuffer$1[key$1]);
2874               }
2875             }
2876
2877             ArrayBufferPrototype$1.constructor = $ArrayBuffer;
2878           } else if (INCORRECT_ARRAY_BUFFER_NAME && CONFIGURABLE_FUNCTION_NAME) {
2879             createNonEnumerableProperty$5(NativeArrayBuffer$1, 'name', ARRAY_BUFFER$1);
2880           }
2881
2882           // WebKit bug - the same parent prototype for typed arrays and data view
2883           if (setPrototypeOf$5 && getPrototypeOf$2(DataViewPrototype$1) !== ObjectPrototype$2) {
2884             setPrototypeOf$5(DataViewPrototype$1, ObjectPrototype$2);
2885           }
2886
2887           // iOS Safari 7.x bug
2888           var testView = new $DataView(new $ArrayBuffer(2));
2889           var $setInt8 = uncurryThis$E(DataViewPrototype$1.setInt8);
2890           testView.setInt8(0, 2147483648);
2891           testView.setInt8(1, 2147483649);
2892           if (testView.getInt8(0) || !testView.getInt8(1)) redefineAll$3(DataViewPrototype$1, {
2893             setInt8: function setInt8(byteOffset, value) {
2894               $setInt8(this, byteOffset, value << 24 >> 24);
2895             },
2896             setUint8: function setUint8(byteOffset, value) {
2897               $setInt8(this, byteOffset, value << 24 >> 24);
2898             }
2899           }, { unsafe: true });
2900         }
2901
2902         setToStringTag$6($ArrayBuffer, ARRAY_BUFFER$1);
2903         setToStringTag$6($DataView, DATA_VIEW);
2904
2905         var arrayBuffer = {
2906           ArrayBuffer: $ArrayBuffer,
2907           DataView: $DataView
2908         };
2909
2910         var global$P = global$1o;
2911         var isConstructor$2 = isConstructor$4;
2912         var tryToString$3 = tryToString$5;
2913
2914         var TypeError$f = global$P.TypeError;
2915
2916         // `Assert: IsConstructor(argument) is true`
2917         var aConstructor$3 = function (argument) {
2918           if (isConstructor$2(argument)) return argument;
2919           throw TypeError$f(tryToString$3(argument) + ' is not a constructor');
2920         };
2921
2922         var anObject$g = anObject$n;
2923         var aConstructor$2 = aConstructor$3;
2924         var wellKnownSymbol$h = wellKnownSymbol$t;
2925
2926         var SPECIES$5 = wellKnownSymbol$h('species');
2927
2928         // `SpeciesConstructor` abstract operation
2929         // https://tc39.es/ecma262/#sec-speciesconstructor
2930         var speciesConstructor$5 = function (O, defaultConstructor) {
2931           var C = anObject$g(O).constructor;
2932           var S;
2933           return C === undefined || (S = anObject$g(C)[SPECIES$5]) == undefined ? defaultConstructor : aConstructor$2(S);
2934         };
2935
2936         var $$19 = _export;
2937         var uncurryThis$D = functionUncurryThis;
2938         var fails$I = fails$V;
2939         var ArrayBufferModule$2 = arrayBuffer;
2940         var anObject$f = anObject$n;
2941         var toAbsoluteIndex$5 = toAbsoluteIndex$9;
2942         var toLength$8 = toLength$c;
2943         var speciesConstructor$4 = speciesConstructor$5;
2944
2945         var ArrayBuffer$4 = ArrayBufferModule$2.ArrayBuffer;
2946         var DataView$2 = ArrayBufferModule$2.DataView;
2947         var DataViewPrototype = DataView$2.prototype;
2948         var un$ArrayBufferSlice = uncurryThis$D(ArrayBuffer$4.prototype.slice);
2949         var getUint8 = uncurryThis$D(DataViewPrototype.getUint8);
2950         var setUint8 = uncurryThis$D(DataViewPrototype.setUint8);
2951
2952         var INCORRECT_SLICE = fails$I(function () {
2953           return !new ArrayBuffer$4(2).slice(1, undefined).byteLength;
2954         });
2955
2956         // `ArrayBuffer.prototype.slice` method
2957         // https://tc39.es/ecma262/#sec-arraybuffer.prototype.slice
2958         $$19({ target: 'ArrayBuffer', proto: true, unsafe: true, forced: INCORRECT_SLICE }, {
2959           slice: function slice(start, end) {
2960             if (un$ArrayBufferSlice && end === undefined) {
2961               return un$ArrayBufferSlice(anObject$f(this), start); // FF fix
2962             }
2963             var length = anObject$f(this).byteLength;
2964             var first = toAbsoluteIndex$5(start, length);
2965             var fin = toAbsoluteIndex$5(end === undefined ? length : end, length);
2966             var result = new (speciesConstructor$4(this, ArrayBuffer$4))(toLength$8(fin - first));
2967             var viewSource = new DataView$2(this);
2968             var viewTarget = new DataView$2(result);
2969             var index = 0;
2970             while (first < fin) {
2971               setUint8(viewTarget, index++, getUint8(viewSource, first++));
2972             } return result;
2973           }
2974         });
2975
2976         var $$18 = _export;
2977         var ArrayBufferModule$1 = arrayBuffer;
2978         var NATIVE_ARRAY_BUFFER$1 = arrayBufferNative;
2979
2980         // `DataView` constructor
2981         // https://tc39.es/ecma262/#sec-dataview-constructor
2982         $$18({ global: true, forced: !NATIVE_ARRAY_BUFFER$1 }, {
2983           DataView: ArrayBufferModule$1.DataView
2984         });
2985
2986         var NATIVE_ARRAY_BUFFER = arrayBufferNative;
2987         var DESCRIPTORS$e = descriptors;
2988         var global$O = global$1o;
2989         var isCallable$9 = isCallable$r;
2990         var isObject$k = isObject$s;
2991         var hasOwn$9 = hasOwnProperty_1;
2992         var classof$7 = classof$d;
2993         var tryToString$2 = tryToString$5;
2994         var createNonEnumerableProperty$4 = createNonEnumerableProperty$b;
2995         var redefine$9 = redefine$h.exports;
2996         var defineProperty$7 = objectDefineProperty.f;
2997         var isPrototypeOf$5 = objectIsPrototypeOf;
2998         var getPrototypeOf$1 = objectGetPrototypeOf;
2999         var setPrototypeOf$4 = objectSetPrototypeOf;
3000         var wellKnownSymbol$g = wellKnownSymbol$t;
3001         var uid$1 = uid$5;
3002
3003         var Int8Array$4 = global$O.Int8Array;
3004         var Int8ArrayPrototype$1 = Int8Array$4 && Int8Array$4.prototype;
3005         var Uint8ClampedArray$1 = global$O.Uint8ClampedArray;
3006         var Uint8ClampedArrayPrototype = Uint8ClampedArray$1 && Uint8ClampedArray$1.prototype;
3007         var TypedArray$1 = Int8Array$4 && getPrototypeOf$1(Int8Array$4);
3008         var TypedArrayPrototype$2 = Int8ArrayPrototype$1 && getPrototypeOf$1(Int8ArrayPrototype$1);
3009         var ObjectPrototype$1 = Object.prototype;
3010         var TypeError$e = global$O.TypeError;
3011
3012         var TO_STRING_TAG = wellKnownSymbol$g('toStringTag');
3013         var TYPED_ARRAY_TAG$1 = uid$1('TYPED_ARRAY_TAG');
3014         var TYPED_ARRAY_CONSTRUCTOR$2 = uid$1('TYPED_ARRAY_CONSTRUCTOR');
3015         // Fixing native typed arrays in Opera Presto crashes the browser, see #595
3016         var NATIVE_ARRAY_BUFFER_VIEWS$3 = NATIVE_ARRAY_BUFFER && !!setPrototypeOf$4 && classof$7(global$O.opera) !== 'Opera';
3017         var TYPED_ARRAY_TAG_REQUIRED = false;
3018         var NAME$1, Constructor, Prototype;
3019
3020         var TypedArrayConstructorsList = {
3021           Int8Array: 1,
3022           Uint8Array: 1,
3023           Uint8ClampedArray: 1,
3024           Int16Array: 2,
3025           Uint16Array: 2,
3026           Int32Array: 4,
3027           Uint32Array: 4,
3028           Float32Array: 4,
3029           Float64Array: 8
3030         };
3031
3032         var BigIntArrayConstructorsList = {
3033           BigInt64Array: 8,
3034           BigUint64Array: 8
3035         };
3036
3037         var isView = function isView(it) {
3038           if (!isObject$k(it)) return false;
3039           var klass = classof$7(it);
3040           return klass === 'DataView'
3041             || hasOwn$9(TypedArrayConstructorsList, klass)
3042             || hasOwn$9(BigIntArrayConstructorsList, klass);
3043         };
3044
3045         var isTypedArray$1 = function (it) {
3046           if (!isObject$k(it)) return false;
3047           var klass = classof$7(it);
3048           return hasOwn$9(TypedArrayConstructorsList, klass)
3049             || hasOwn$9(BigIntArrayConstructorsList, klass);
3050         };
3051
3052         var aTypedArray$m = function (it) {
3053           if (isTypedArray$1(it)) return it;
3054           throw TypeError$e('Target is not a typed array');
3055         };
3056
3057         var aTypedArrayConstructor$3 = function (C) {
3058           if (isCallable$9(C) && (!setPrototypeOf$4 || isPrototypeOf$5(TypedArray$1, C))) return C;
3059           throw TypeError$e(tryToString$2(C) + ' is not a typed array constructor');
3060         };
3061
3062         var exportTypedArrayMethod$n = function (KEY, property, forced, options) {
3063           if (!DESCRIPTORS$e) return;
3064           if (forced) for (var ARRAY in TypedArrayConstructorsList) {
3065             var TypedArrayConstructor = global$O[ARRAY];
3066             if (TypedArrayConstructor && hasOwn$9(TypedArrayConstructor.prototype, KEY)) try {
3067               delete TypedArrayConstructor.prototype[KEY];
3068             } catch (error) {
3069               // old WebKit bug - some methods are non-configurable
3070               try {
3071                 TypedArrayConstructor.prototype[KEY] = property;
3072               } catch (error2) { /* empty */ }
3073             }
3074           }
3075           if (!TypedArrayPrototype$2[KEY] || forced) {
3076             redefine$9(TypedArrayPrototype$2, KEY, forced ? property
3077               : NATIVE_ARRAY_BUFFER_VIEWS$3 && Int8ArrayPrototype$1[KEY] || property, options);
3078           }
3079         };
3080
3081         var exportTypedArrayStaticMethod$1 = function (KEY, property, forced) {
3082           var ARRAY, TypedArrayConstructor;
3083           if (!DESCRIPTORS$e) return;
3084           if (setPrototypeOf$4) {
3085             if (forced) for (ARRAY in TypedArrayConstructorsList) {
3086               TypedArrayConstructor = global$O[ARRAY];
3087               if (TypedArrayConstructor && hasOwn$9(TypedArrayConstructor, KEY)) try {
3088                 delete TypedArrayConstructor[KEY];
3089               } catch (error) { /* empty */ }
3090             }
3091             if (!TypedArray$1[KEY] || forced) {
3092               // V8 ~ Chrome 49-50 `%TypedArray%` methods are non-writable non-configurable
3093               try {
3094                 return redefine$9(TypedArray$1, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS$3 && TypedArray$1[KEY] || property);
3095               } catch (error) { /* empty */ }
3096             } else return;
3097           }
3098           for (ARRAY in TypedArrayConstructorsList) {
3099             TypedArrayConstructor = global$O[ARRAY];
3100             if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) {
3101               redefine$9(TypedArrayConstructor, KEY, property);
3102             }
3103           }
3104         };
3105
3106         for (NAME$1 in TypedArrayConstructorsList) {
3107           Constructor = global$O[NAME$1];
3108           Prototype = Constructor && Constructor.prototype;
3109           if (Prototype) createNonEnumerableProperty$4(Prototype, TYPED_ARRAY_CONSTRUCTOR$2, Constructor);
3110           else NATIVE_ARRAY_BUFFER_VIEWS$3 = false;
3111         }
3112
3113         for (NAME$1 in BigIntArrayConstructorsList) {
3114           Constructor = global$O[NAME$1];
3115           Prototype = Constructor && Constructor.prototype;
3116           if (Prototype) createNonEnumerableProperty$4(Prototype, TYPED_ARRAY_CONSTRUCTOR$2, Constructor);
3117         }
3118
3119         // WebKit bug - typed arrays constructors prototype is Object.prototype
3120         if (!NATIVE_ARRAY_BUFFER_VIEWS$3 || !isCallable$9(TypedArray$1) || TypedArray$1 === Function.prototype) {
3121           // eslint-disable-next-line no-shadow -- safe
3122           TypedArray$1 = function TypedArray() {
3123             throw TypeError$e('Incorrect invocation');
3124           };
3125           if (NATIVE_ARRAY_BUFFER_VIEWS$3) for (NAME$1 in TypedArrayConstructorsList) {
3126             if (global$O[NAME$1]) setPrototypeOf$4(global$O[NAME$1], TypedArray$1);
3127           }
3128         }
3129
3130         if (!NATIVE_ARRAY_BUFFER_VIEWS$3 || !TypedArrayPrototype$2 || TypedArrayPrototype$2 === ObjectPrototype$1) {
3131           TypedArrayPrototype$2 = TypedArray$1.prototype;
3132           if (NATIVE_ARRAY_BUFFER_VIEWS$3) for (NAME$1 in TypedArrayConstructorsList) {
3133             if (global$O[NAME$1]) setPrototypeOf$4(global$O[NAME$1].prototype, TypedArrayPrototype$2);
3134           }
3135         }
3136
3137         // WebKit bug - one more object in Uint8ClampedArray prototype chain
3138         if (NATIVE_ARRAY_BUFFER_VIEWS$3 && getPrototypeOf$1(Uint8ClampedArrayPrototype) !== TypedArrayPrototype$2) {
3139           setPrototypeOf$4(Uint8ClampedArrayPrototype, TypedArrayPrototype$2);
3140         }
3141
3142         if (DESCRIPTORS$e && !hasOwn$9(TypedArrayPrototype$2, TO_STRING_TAG)) {
3143           TYPED_ARRAY_TAG_REQUIRED = true;
3144           defineProperty$7(TypedArrayPrototype$2, TO_STRING_TAG, { get: function () {
3145             return isObject$k(this) ? this[TYPED_ARRAY_TAG$1] : undefined;
3146           } });
3147           for (NAME$1 in TypedArrayConstructorsList) if (global$O[NAME$1]) {
3148             createNonEnumerableProperty$4(global$O[NAME$1], TYPED_ARRAY_TAG$1, NAME$1);
3149           }
3150         }
3151
3152         var arrayBufferViewCore = {
3153           NATIVE_ARRAY_BUFFER_VIEWS: NATIVE_ARRAY_BUFFER_VIEWS$3,
3154           TYPED_ARRAY_CONSTRUCTOR: TYPED_ARRAY_CONSTRUCTOR$2,
3155           TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQUIRED && TYPED_ARRAY_TAG$1,
3156           aTypedArray: aTypedArray$m,
3157           aTypedArrayConstructor: aTypedArrayConstructor$3,
3158           exportTypedArrayMethod: exportTypedArrayMethod$n,
3159           exportTypedArrayStaticMethod: exportTypedArrayStaticMethod$1,
3160           isView: isView,
3161           isTypedArray: isTypedArray$1,
3162           TypedArray: TypedArray$1,
3163           TypedArrayPrototype: TypedArrayPrototype$2
3164         };
3165
3166         var $$17 = _export;
3167         var ArrayBufferViewCore$o = arrayBufferViewCore;
3168
3169         var NATIVE_ARRAY_BUFFER_VIEWS$2 = ArrayBufferViewCore$o.NATIVE_ARRAY_BUFFER_VIEWS;
3170
3171         // `ArrayBuffer.isView` method
3172         // https://tc39.es/ecma262/#sec-arraybuffer.isview
3173         $$17({ target: 'ArrayBuffer', stat: true, forced: !NATIVE_ARRAY_BUFFER_VIEWS$2 }, {
3174           isView: ArrayBufferViewCore$o.isView
3175         });
3176
3177         var getBuiltIn$4 = getBuiltIn$b;
3178         var definePropertyModule$1 = objectDefineProperty;
3179         var wellKnownSymbol$f = wellKnownSymbol$t;
3180         var DESCRIPTORS$d = descriptors;
3181
3182         var SPECIES$4 = wellKnownSymbol$f('species');
3183
3184         var setSpecies$5 = function (CONSTRUCTOR_NAME) {
3185           var Constructor = getBuiltIn$4(CONSTRUCTOR_NAME);
3186           var defineProperty = definePropertyModule$1.f;
3187
3188           if (DESCRIPTORS$d && Constructor && !Constructor[SPECIES$4]) {
3189             defineProperty(Constructor, SPECIES$4, {
3190               configurable: true,
3191               get: function () { return this; }
3192             });
3193           }
3194         };
3195
3196         var $$16 = _export;
3197         var global$N = global$1o;
3198         var arrayBufferModule = arrayBuffer;
3199         var setSpecies$4 = setSpecies$5;
3200
3201         var ARRAY_BUFFER = 'ArrayBuffer';
3202         var ArrayBuffer$3 = arrayBufferModule[ARRAY_BUFFER];
3203         var NativeArrayBuffer = global$N[ARRAY_BUFFER];
3204
3205         // `ArrayBuffer` constructor
3206         // https://tc39.es/ecma262/#sec-arraybuffer-constructor
3207         $$16({ global: true, forced: NativeArrayBuffer !== ArrayBuffer$3 }, {
3208           ArrayBuffer: ArrayBuffer$3
3209         });
3210
3211         setSpecies$4(ARRAY_BUFFER);
3212
3213         var fails$H = fails$V;
3214
3215         var arrayMethodIsStrict$9 = function (METHOD_NAME, argument) {
3216           var method = [][METHOD_NAME];
3217           return !!method && fails$H(function () {
3218             // eslint-disable-next-line no-useless-call,no-throw-literal -- required for testing
3219             method.call(null, argument || function () { throw 1; }, 1);
3220           });
3221         };
3222
3223         /* eslint-disable es/no-array-prototype-indexof -- required for testing */
3224         var $$15 = _export;
3225         var uncurryThis$C = functionUncurryThis;
3226         var $IndexOf = arrayIncludes.indexOf;
3227         var arrayMethodIsStrict$8 = arrayMethodIsStrict$9;
3228
3229         var un$IndexOf = uncurryThis$C([].indexOf);
3230
3231         var NEGATIVE_ZERO$1 = !!un$IndexOf && 1 / un$IndexOf([1], 1, -0) < 0;
3232         var STRICT_METHOD$8 = arrayMethodIsStrict$8('indexOf');
3233
3234         // `Array.prototype.indexOf` method
3235         // https://tc39.es/ecma262/#sec-array.prototype.indexof
3236         $$15({ target: 'Array', proto: true, forced: NEGATIVE_ZERO$1 || !STRICT_METHOD$8 }, {
3237           indexOf: function indexOf(searchElement /* , fromIndex = 0 */) {
3238             var fromIndex = arguments.length > 1 ? arguments[1] : undefined;
3239             return NEGATIVE_ZERO$1
3240               // convert -0 to +0
3241               ? un$IndexOf(this, searchElement, fromIndex) || 0
3242               : $IndexOf(this, searchElement, fromIndex);
3243           }
3244         });
3245
3246         var anObject$e = anObject$n;
3247
3248         // `RegExp.prototype.flags` getter implementation
3249         // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
3250         var regexpFlags$1 = function () {
3251           var that = anObject$e(this);
3252           var result = '';
3253           if (that.global) result += 'g';
3254           if (that.ignoreCase) result += 'i';
3255           if (that.multiline) result += 'm';
3256           if (that.dotAll) result += 's';
3257           if (that.unicode) result += 'u';
3258           if (that.sticky) result += 'y';
3259           return result;
3260         };
3261
3262         var fails$G = fails$V;
3263         var global$M = global$1o;
3264
3265         // babel-minify and Closure Compiler transpiles RegExp('a', 'y') -> /a/y and it causes SyntaxError
3266         var $RegExp$2 = global$M.RegExp;
3267
3268         var UNSUPPORTED_Y$3 = fails$G(function () {
3269           var re = $RegExp$2('a', 'y');
3270           re.lastIndex = 2;
3271           return re.exec('abcd') != null;
3272         });
3273
3274         // UC Browser bug
3275         // https://github.com/zloirock/core-js/issues/1008
3276         var MISSED_STICKY$1 = UNSUPPORTED_Y$3 || fails$G(function () {
3277           return !$RegExp$2('a', 'y').sticky;
3278         });
3279
3280         var BROKEN_CARET = UNSUPPORTED_Y$3 || fails$G(function () {
3281           // https://bugzilla.mozilla.org/show_bug.cgi?id=773687
3282           var re = $RegExp$2('^r', 'gy');
3283           re.lastIndex = 2;
3284           return re.exec('str') != null;
3285         });
3286
3287         var regexpStickyHelpers = {
3288           BROKEN_CARET: BROKEN_CARET,
3289           MISSED_STICKY: MISSED_STICKY$1,
3290           UNSUPPORTED_Y: UNSUPPORTED_Y$3
3291         };
3292
3293         var fails$F = fails$V;
3294         var global$L = global$1o;
3295
3296         // babel-minify and Closure Compiler transpiles RegExp('.', 's') -> /./s and it causes SyntaxError
3297         var $RegExp$1 = global$L.RegExp;
3298
3299         var regexpUnsupportedDotAll = fails$F(function () {
3300           var re = $RegExp$1('.', 's');
3301           return !(re.dotAll && re.exec('\n') && re.flags === 's');
3302         });
3303
3304         var fails$E = fails$V;
3305         var global$K = global$1o;
3306
3307         // babel-minify and Closure Compiler transpiles RegExp('(?<a>b)', 'g') -> /(?<a>b)/g and it causes SyntaxError
3308         var $RegExp = global$K.RegExp;
3309
3310         var regexpUnsupportedNcg = fails$E(function () {
3311           var re = $RegExp('(?<a>b)', 'g');
3312           return re.exec('b').groups.a !== 'b' ||
3313             'b'.replace(re, '$<a>c') !== 'bc';
3314         });
3315
3316         /* eslint-disable regexp/no-empty-capturing-group, regexp/no-empty-group, regexp/no-lazy-ends -- testing */
3317         /* eslint-disable regexp/no-useless-quantifier -- testing */
3318         var call$i = functionCall;
3319         var uncurryThis$B = functionUncurryThis;
3320         var toString$g = toString$k;
3321         var regexpFlags = regexpFlags$1;
3322         var stickyHelpers$2 = regexpStickyHelpers;
3323         var shared = shared$5.exports;
3324         var create$8 = objectCreate;
3325         var getInternalState$2 = internalState.get;
3326         var UNSUPPORTED_DOT_ALL$1 = regexpUnsupportedDotAll;
3327         var UNSUPPORTED_NCG$1 = regexpUnsupportedNcg;
3328
3329         var nativeReplace = shared('native-string-replace', String.prototype.replace);
3330         var nativeExec = RegExp.prototype.exec;
3331         var patchedExec = nativeExec;
3332         var charAt$6 = uncurryThis$B(''.charAt);
3333         var indexOf = uncurryThis$B(''.indexOf);
3334         var replace$7 = uncurryThis$B(''.replace);
3335         var stringSlice$9 = uncurryThis$B(''.slice);
3336
3337         var UPDATES_LAST_INDEX_WRONG = (function () {
3338           var re1 = /a/;
3339           var re2 = /b*/g;
3340           call$i(nativeExec, re1, 'a');
3341           call$i(nativeExec, re2, 'a');
3342           return re1.lastIndex !== 0 || re2.lastIndex !== 0;
3343         })();
3344
3345         var UNSUPPORTED_Y$2 = stickyHelpers$2.BROKEN_CARET;
3346
3347         // nonparticipating capturing group, copied from es5-shim's String#split patch.
3348         var NPCG_INCLUDED = /()??/.exec('')[1] !== undefined;
3349
3350         var PATCH = UPDATES_LAST_INDEX_WRONG || NPCG_INCLUDED || UNSUPPORTED_Y$2 || UNSUPPORTED_DOT_ALL$1 || UNSUPPORTED_NCG$1;
3351
3352         if (PATCH) {
3353           patchedExec = function exec(string) {
3354             var re = this;
3355             var state = getInternalState$2(re);
3356             var str = toString$g(string);
3357             var raw = state.raw;
3358             var result, reCopy, lastIndex, match, i, object, group;
3359
3360             if (raw) {
3361               raw.lastIndex = re.lastIndex;
3362               result = call$i(patchedExec, raw, str);
3363               re.lastIndex = raw.lastIndex;
3364               return result;
3365             }
3366
3367             var groups = state.groups;
3368             var sticky = UNSUPPORTED_Y$2 && re.sticky;
3369             var flags = call$i(regexpFlags, re);
3370             var source = re.source;
3371             var charsAdded = 0;
3372             var strCopy = str;
3373
3374             if (sticky) {
3375               flags = replace$7(flags, 'y', '');
3376               if (indexOf(flags, 'g') === -1) {
3377                 flags += 'g';
3378               }
3379
3380               strCopy = stringSlice$9(str, re.lastIndex);
3381               // Support anchored sticky behavior.
3382               if (re.lastIndex > 0 && (!re.multiline || re.multiline && charAt$6(str, re.lastIndex - 1) !== '\n')) {
3383                 source = '(?: ' + source + ')';
3384                 strCopy = ' ' + strCopy;
3385                 charsAdded++;
3386               }
3387               // ^(? + rx + ) is needed, in combination with some str slicing, to
3388               // simulate the 'y' flag.
3389               reCopy = new RegExp('^(?:' + source + ')', flags);
3390             }
3391
3392             if (NPCG_INCLUDED) {
3393               reCopy = new RegExp('^' + source + '$(?!\\s)', flags);
3394             }
3395             if (UPDATES_LAST_INDEX_WRONG) lastIndex = re.lastIndex;
3396
3397             match = call$i(nativeExec, sticky ? reCopy : re, strCopy);
3398
3399             if (sticky) {
3400               if (match) {
3401                 match.input = stringSlice$9(match.input, charsAdded);
3402                 match[0] = stringSlice$9(match[0], charsAdded);
3403                 match.index = re.lastIndex;
3404                 re.lastIndex += match[0].length;
3405               } else re.lastIndex = 0;
3406             } else if (UPDATES_LAST_INDEX_WRONG && match) {
3407               re.lastIndex = re.global ? match.index + match[0].length : lastIndex;
3408             }
3409             if (NPCG_INCLUDED && match && match.length > 1) {
3410               // Fix browsers whose `exec` methods don't consistently return `undefined`
3411               // for NPCG, like IE8. NOTE: This doesn' work for /(.?)?/
3412               call$i(nativeReplace, match[0], reCopy, function () {
3413                 for (i = 1; i < arguments.length - 2; i++) {
3414                   if (arguments[i] === undefined) match[i] = undefined;
3415                 }
3416               });
3417             }
3418
3419             if (match && groups) {
3420               match.groups = object = create$8(null);
3421               for (i = 0; i < groups.length; i++) {
3422                 group = groups[i];
3423                 object[group[0]] = match[group[1]];
3424               }
3425             }
3426
3427             return match;
3428           };
3429         }
3430
3431         var regexpExec$3 = patchedExec;
3432
3433         var $$14 = _export;
3434         var exec$5 = regexpExec$3;
3435
3436         // `RegExp.prototype.exec` method
3437         // https://tc39.es/ecma262/#sec-regexp.prototype.exec
3438         $$14({ target: 'RegExp', proto: true, forced: /./.exec !== exec$5 }, {
3439           exec: exec$5
3440         });
3441
3442         var fails$D = fails$V;
3443         var wellKnownSymbol$e = wellKnownSymbol$t;
3444         var V8_VERSION$2 = engineV8Version;
3445
3446         var SPECIES$3 = wellKnownSymbol$e('species');
3447
3448         var arrayMethodHasSpeciesSupport$5 = function (METHOD_NAME) {
3449           // We can't use this feature detection in V8 since it causes
3450           // deoptimization and serious performance degradation
3451           // https://github.com/zloirock/core-js/issues/677
3452           return V8_VERSION$2 >= 51 || !fails$D(function () {
3453             var array = [];
3454             var constructor = array.constructor = {};
3455             constructor[SPECIES$3] = function () {
3456               return { foo: 1 };
3457             };
3458             return array[METHOD_NAME](Boolean).foo !== 1;
3459           });
3460         };
3461
3462         var $$13 = _export;
3463         var $map$1 = arrayIteration.map;
3464         var arrayMethodHasSpeciesSupport$4 = arrayMethodHasSpeciesSupport$5;
3465
3466         var HAS_SPECIES_SUPPORT$3 = arrayMethodHasSpeciesSupport$4('map');
3467
3468         // `Array.prototype.map` method
3469         // https://tc39.es/ecma262/#sec-array.prototype.map
3470         // with adding support of @@species
3471         $$13({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$3 }, {
3472           map: function map(callbackfn /* , thisArg */) {
3473             return $map$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
3474           }
3475         });
3476
3477         var $forEach$1 = arrayIteration.forEach;
3478         var arrayMethodIsStrict$7 = arrayMethodIsStrict$9;
3479
3480         var STRICT_METHOD$7 = arrayMethodIsStrict$7('forEach');
3481
3482         // `Array.prototype.forEach` method implementation
3483         // https://tc39.es/ecma262/#sec-array.prototype.foreach
3484         var arrayForEach = !STRICT_METHOD$7 ? function forEach(callbackfn /* , thisArg */) {
3485           return $forEach$1(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
3486         // eslint-disable-next-line es/no-array-prototype-foreach -- safe
3487         } : [].forEach;
3488
3489         var $$12 = _export;
3490         var forEach$3 = arrayForEach;
3491
3492         // `Array.prototype.forEach` method
3493         // https://tc39.es/ecma262/#sec-array.prototype.foreach
3494         // eslint-disable-next-line es/no-array-prototype-foreach -- safe
3495         $$12({ target: 'Array', proto: true, forced: [].forEach != forEach$3 }, {
3496           forEach: forEach$3
3497         });
3498
3499         var global$J = global$1o;
3500         var DOMIterables = domIterables;
3501         var DOMTokenListPrototype = domTokenListPrototype;
3502         var forEach$2 = arrayForEach;
3503         var createNonEnumerableProperty$3 = createNonEnumerableProperty$b;
3504
3505         var handlePrototype = function (CollectionPrototype) {
3506           // some Chrome versions have non-configurable methods on DOMTokenList
3507           if (CollectionPrototype && CollectionPrototype.forEach !== forEach$2) try {
3508             createNonEnumerableProperty$3(CollectionPrototype, 'forEach', forEach$2);
3509           } catch (error) {
3510             CollectionPrototype.forEach = forEach$2;
3511           }
3512         };
3513
3514         for (var COLLECTION_NAME in DOMIterables) {
3515           if (DOMIterables[COLLECTION_NAME]) {
3516             handlePrototype(global$J[COLLECTION_NAME] && global$J[COLLECTION_NAME].prototype);
3517           }
3518         }
3519
3520         handlePrototype(DOMTokenListPrototype);
3521
3522         var $$11 = _export;
3523         var isArray$5 = isArray$8;
3524
3525         // `Array.isArray` method
3526         // https://tc39.es/ecma262/#sec-array.isarray
3527         $$11({ target: 'Array', stat: true }, {
3528           isArray: isArray$5
3529         });
3530
3531         var $$10 = _export;
3532         var fails$C = fails$V;
3533         var getOwnPropertyNames$3 = objectGetOwnPropertyNamesExternal.f;
3534
3535         // eslint-disable-next-line es/no-object-getownpropertynames -- required for testing
3536         var FAILS_ON_PRIMITIVES$5 = fails$C(function () { return !Object.getOwnPropertyNames(1); });
3537
3538         // `Object.getOwnPropertyNames` method
3539         // https://tc39.es/ecma262/#sec-object.getownpropertynames
3540         $$10({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$5 }, {
3541           getOwnPropertyNames: getOwnPropertyNames$3
3542         });
3543
3544         var global$I = global$1o;
3545
3546         var nativePromiseConstructor = global$I.Promise;
3547
3548         var wellKnownSymbol$d = wellKnownSymbol$t;
3549         var Iterators$1 = iterators;
3550
3551         var ITERATOR$7 = wellKnownSymbol$d('iterator');
3552         var ArrayPrototype = Array.prototype;
3553
3554         // check on default Array iterator
3555         var isArrayIteratorMethod$3 = function (it) {
3556           return it !== undefined && (Iterators$1.Array === it || ArrayPrototype[ITERATOR$7] === it);
3557         };
3558
3559         var classof$6 = classof$d;
3560         var getMethod$5 = getMethod$7;
3561         var Iterators = iterators;
3562         var wellKnownSymbol$c = wellKnownSymbol$t;
3563
3564         var ITERATOR$6 = wellKnownSymbol$c('iterator');
3565
3566         var getIteratorMethod$5 = function (it) {
3567           if (it != undefined) return getMethod$5(it, ITERATOR$6)
3568             || getMethod$5(it, '@@iterator')
3569             || Iterators[classof$6(it)];
3570         };
3571
3572         var global$H = global$1o;
3573         var call$h = functionCall;
3574         var aCallable$7 = aCallable$a;
3575         var anObject$d = anObject$n;
3576         var tryToString$1 = tryToString$5;
3577         var getIteratorMethod$4 = getIteratorMethod$5;
3578
3579         var TypeError$d = global$H.TypeError;
3580
3581         var getIterator$4 = function (argument, usingIterator) {
3582           var iteratorMethod = arguments.length < 2 ? getIteratorMethod$4(argument) : usingIterator;
3583           if (aCallable$7(iteratorMethod)) return anObject$d(call$h(iteratorMethod, argument));
3584           throw TypeError$d(tryToString$1(argument) + ' is not iterable');
3585         };
3586
3587         var call$g = functionCall;
3588         var anObject$c = anObject$n;
3589         var getMethod$4 = getMethod$7;
3590
3591         var iteratorClose$2 = function (iterator, kind, value) {
3592           var innerResult, innerError;
3593           anObject$c(iterator);
3594           try {
3595             innerResult = getMethod$4(iterator, 'return');
3596             if (!innerResult) {
3597               if (kind === 'throw') throw value;
3598               return value;
3599             }
3600             innerResult = call$g(innerResult, iterator);
3601           } catch (error) {
3602             innerError = true;
3603             innerResult = error;
3604           }
3605           if (kind === 'throw') throw value;
3606           if (innerError) throw innerResult;
3607           anObject$c(innerResult);
3608           return value;
3609         };
3610
3611         var global$G = global$1o;
3612         var bind$d = functionBindContext;
3613         var call$f = functionCall;
3614         var anObject$b = anObject$n;
3615         var tryToString = tryToString$5;
3616         var isArrayIteratorMethod$2 = isArrayIteratorMethod$3;
3617         var lengthOfArrayLike$d = lengthOfArrayLike$i;
3618         var isPrototypeOf$4 = objectIsPrototypeOf;
3619         var getIterator$3 = getIterator$4;
3620         var getIteratorMethod$3 = getIteratorMethod$5;
3621         var iteratorClose$1 = iteratorClose$2;
3622
3623         var TypeError$c = global$G.TypeError;
3624
3625         var Result = function (stopped, result) {
3626           this.stopped = stopped;
3627           this.result = result;
3628         };
3629
3630         var ResultPrototype = Result.prototype;
3631
3632         var iterate$3 = function (iterable, unboundFunction, options) {
3633           var that = options && options.that;
3634           var AS_ENTRIES = !!(options && options.AS_ENTRIES);
3635           var IS_ITERATOR = !!(options && options.IS_ITERATOR);
3636           var INTERRUPTED = !!(options && options.INTERRUPTED);
3637           var fn = bind$d(unboundFunction, that);
3638           var iterator, iterFn, index, length, result, next, step;
3639
3640           var stop = function (condition) {
3641             if (iterator) iteratorClose$1(iterator, 'normal', condition);
3642             return new Result(true, condition);
3643           };
3644
3645           var callFn = function (value) {
3646             if (AS_ENTRIES) {
3647               anObject$b(value);
3648               return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]);
3649             } return INTERRUPTED ? fn(value, stop) : fn(value);
3650           };
3651
3652           if (IS_ITERATOR) {
3653             iterator = iterable;
3654           } else {
3655             iterFn = getIteratorMethod$3(iterable);
3656             if (!iterFn) throw TypeError$c(tryToString(iterable) + ' is not iterable');
3657             // optimisation for array iterators
3658             if (isArrayIteratorMethod$2(iterFn)) {
3659               for (index = 0, length = lengthOfArrayLike$d(iterable); length > index; index++) {
3660                 result = callFn(iterable[index]);
3661                 if (result && isPrototypeOf$4(ResultPrototype, result)) return result;
3662               } return new Result(false);
3663             }
3664             iterator = getIterator$3(iterable, iterFn);
3665           }
3666
3667           next = iterator.next;
3668           while (!(step = call$f(next, iterator)).done) {
3669             try {
3670               result = callFn(step.value);
3671             } catch (error) {
3672               iteratorClose$1(iterator, 'throw', error);
3673             }
3674             if (typeof result == 'object' && result && isPrototypeOf$4(ResultPrototype, result)) return result;
3675           } return new Result(false);
3676         };
3677
3678         var wellKnownSymbol$b = wellKnownSymbol$t;
3679
3680         var ITERATOR$5 = wellKnownSymbol$b('iterator');
3681         var SAFE_CLOSING = false;
3682
3683         try {
3684           var called = 0;
3685           var iteratorWithReturn = {
3686             next: function () {
3687               return { done: !!called++ };
3688             },
3689             'return': function () {
3690               SAFE_CLOSING = true;
3691             }
3692           };
3693           iteratorWithReturn[ITERATOR$5] = function () {
3694             return this;
3695           };
3696           // eslint-disable-next-line es/no-array-from, no-throw-literal -- required for testing
3697           Array.from(iteratorWithReturn, function () { throw 2; });
3698         } catch (error) { /* empty */ }
3699
3700         var checkCorrectnessOfIteration$4 = function (exec, SKIP_CLOSING) {
3701           if (!SKIP_CLOSING && !SAFE_CLOSING) return false;
3702           var ITERATION_SUPPORT = false;
3703           try {
3704             var object = {};
3705             object[ITERATOR$5] = function () {
3706               return {
3707                 next: function () {
3708                   return { done: ITERATION_SUPPORT = true };
3709                 }
3710               };
3711             };
3712             exec(object);
3713           } catch (error) { /* empty */ }
3714           return ITERATION_SUPPORT;
3715         };
3716
3717         var global$F = global$1o;
3718
3719         var TypeError$b = global$F.TypeError;
3720
3721         var validateArgumentsLength$4 = function (passed, required) {
3722           if (passed < required) throw TypeError$b('Not enough arguments');
3723           return passed;
3724         };
3725
3726         var userAgent$6 = engineUserAgent;
3727
3728         var engineIsIos = /(?:ipad|iphone|ipod).*applewebkit/i.test(userAgent$6);
3729
3730         var classof$5 = classofRaw$1;
3731         var global$E = global$1o;
3732
3733         var engineIsNode = classof$5(global$E.process) == 'process';
3734
3735         var global$D = global$1o;
3736         var apply$7 = functionApply;
3737         var bind$c = functionBindContext;
3738         var isCallable$8 = isCallable$r;
3739         var hasOwn$8 = hasOwnProperty_1;
3740         var fails$B = fails$V;
3741         var html = html$2;
3742         var arraySlice$8 = arraySlice$b;
3743         var createElement = documentCreateElement$2;
3744         var validateArgumentsLength$3 = validateArgumentsLength$4;
3745         var IS_IOS$1 = engineIsIos;
3746         var IS_NODE$4 = engineIsNode;
3747
3748         var set$2 = global$D.setImmediate;
3749         var clear = global$D.clearImmediate;
3750         var process$3 = global$D.process;
3751         var Dispatch$1 = global$D.Dispatch;
3752         var Function$3 = global$D.Function;
3753         var MessageChannel = global$D.MessageChannel;
3754         var String$2 = global$D.String;
3755         var counter = 0;
3756         var queue$1 = {};
3757         var ONREADYSTATECHANGE = 'onreadystatechange';
3758         var location$1, defer, channel, port;
3759
3760         try {
3761           // Deno throws a ReferenceError on `location` access without `--location` flag
3762           location$1 = global$D.location;
3763         } catch (error) { /* empty */ }
3764
3765         var run = function (id) {
3766           if (hasOwn$8(queue$1, id)) {
3767             var fn = queue$1[id];
3768             delete queue$1[id];
3769             fn();
3770           }
3771         };
3772
3773         var runner = function (id) {
3774           return function () {
3775             run(id);
3776           };
3777         };
3778
3779         var listener = function (event) {
3780           run(event.data);
3781         };
3782
3783         var post = function (id) {
3784           // old engines have not location.origin
3785           global$D.postMessage(String$2(id), location$1.protocol + '//' + location$1.host);
3786         };
3787
3788         // Node.js 0.9+ & IE10+ has setImmediate, otherwise:
3789         if (!set$2 || !clear) {
3790           set$2 = function setImmediate(handler) {
3791             validateArgumentsLength$3(arguments.length, 1);
3792             var fn = isCallable$8(handler) ? handler : Function$3(handler);
3793             var args = arraySlice$8(arguments, 1);
3794             queue$1[++counter] = function () {
3795               apply$7(fn, undefined, args);
3796             };
3797             defer(counter);
3798             return counter;
3799           };
3800           clear = function clearImmediate(id) {
3801             delete queue$1[id];
3802           };
3803           // Node.js 0.8-
3804           if (IS_NODE$4) {
3805             defer = function (id) {
3806               process$3.nextTick(runner(id));
3807             };
3808           // Sphere (JS game engine) Dispatch API
3809           } else if (Dispatch$1 && Dispatch$1.now) {
3810             defer = function (id) {
3811               Dispatch$1.now(runner(id));
3812             };
3813           // Browsers with MessageChannel, includes WebWorkers
3814           // except iOS - https://github.com/zloirock/core-js/issues/624
3815           } else if (MessageChannel && !IS_IOS$1) {
3816             channel = new MessageChannel();
3817             port = channel.port2;
3818             channel.port1.onmessage = listener;
3819             defer = bind$c(port.postMessage, port);
3820           // Browsers with postMessage, skip WebWorkers
3821           // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
3822           } else if (
3823             global$D.addEventListener &&
3824             isCallable$8(global$D.postMessage) &&
3825             !global$D.importScripts &&
3826             location$1 && location$1.protocol !== 'file:' &&
3827             !fails$B(post)
3828           ) {
3829             defer = post;
3830             global$D.addEventListener('message', listener, false);
3831           // IE8-
3832           } else if (ONREADYSTATECHANGE in createElement('script')) {
3833             defer = function (id) {
3834               html.appendChild(createElement('script'))[ONREADYSTATECHANGE] = function () {
3835                 html.removeChild(this);
3836                 run(id);
3837               };
3838             };
3839           // Rest old browsers
3840           } else {
3841             defer = function (id) {
3842               setTimeout(runner(id), 0);
3843             };
3844           }
3845         }
3846
3847         var task$1 = {
3848           set: set$2,
3849           clear: clear
3850         };
3851
3852         var userAgent$5 = engineUserAgent;
3853         var global$C = global$1o;
3854
3855         var engineIsIosPebble = /ipad|iphone|ipod/i.test(userAgent$5) && global$C.Pebble !== undefined;
3856
3857         var userAgent$4 = engineUserAgent;
3858
3859         var engineIsWebosWebkit = /web0s(?!.*chrome)/i.test(userAgent$4);
3860
3861         var global$B = global$1o;
3862         var bind$b = functionBindContext;
3863         var getOwnPropertyDescriptor$3 = objectGetOwnPropertyDescriptor.f;
3864         var macrotask = task$1.set;
3865         var IS_IOS = engineIsIos;
3866         var IS_IOS_PEBBLE = engineIsIosPebble;
3867         var IS_WEBOS_WEBKIT = engineIsWebosWebkit;
3868         var IS_NODE$3 = engineIsNode;
3869
3870         var MutationObserver = global$B.MutationObserver || global$B.WebKitMutationObserver;
3871         var document$2 = global$B.document;
3872         var process$2 = global$B.process;
3873         var Promise$1 = global$B.Promise;
3874         // Node.js 11 shows ExperimentalWarning on getting `queueMicrotask`
3875         var queueMicrotaskDescriptor = getOwnPropertyDescriptor$3(global$B, 'queueMicrotask');
3876         var queueMicrotask = queueMicrotaskDescriptor && queueMicrotaskDescriptor.value;
3877
3878         var flush, head, last, notify$1, toggle, node, promise, then;
3879
3880         // modern engines have queueMicrotask method
3881         if (!queueMicrotask) {
3882           flush = function () {
3883             var parent, fn;
3884             if (IS_NODE$3 && (parent = process$2.domain)) parent.exit();
3885             while (head) {
3886               fn = head.fn;
3887               head = head.next;
3888               try {
3889                 fn();
3890               } catch (error) {
3891                 if (head) notify$1();
3892                 else last = undefined;
3893                 throw error;
3894               }
3895             } last = undefined;
3896             if (parent) parent.enter();
3897           };
3898
3899           // browsers with MutationObserver, except iOS - https://github.com/zloirock/core-js/issues/339
3900           // also except WebOS Webkit https://github.com/zloirock/core-js/issues/898
3901           if (!IS_IOS && !IS_NODE$3 && !IS_WEBOS_WEBKIT && MutationObserver && document$2) {
3902             toggle = true;
3903             node = document$2.createTextNode('');
3904             new MutationObserver(flush).observe(node, { characterData: true });
3905             notify$1 = function () {
3906               node.data = toggle = !toggle;
3907             };
3908           // environments with maybe non-completely correct, but existent Promise
3909           } else if (!IS_IOS_PEBBLE && Promise$1 && Promise$1.resolve) {
3910             // Promise.resolve without an argument throws an error in LG WebOS 2
3911             promise = Promise$1.resolve(undefined);
3912             // workaround of WebKit ~ iOS Safari 10.1 bug
3913             promise.constructor = Promise$1;
3914             then = bind$b(promise.then, promise);
3915             notify$1 = function () {
3916               then(flush);
3917             };
3918           // Node.js without promises
3919           } else if (IS_NODE$3) {
3920             notify$1 = function () {
3921               process$2.nextTick(flush);
3922             };
3923           // for other environments - macrotask based on:
3924           // - setImmediate
3925           // - MessageChannel
3926           // - window.postMessag
3927           // - onreadystatechange
3928           // - setTimeout
3929           } else {
3930             // strange IE + webpack dev server bug - use .bind(global)
3931             macrotask = bind$b(macrotask, global$B);
3932             notify$1 = function () {
3933               macrotask(flush);
3934             };
3935           }
3936         }
3937
3938         var microtask$1 = queueMicrotask || function (fn) {
3939           var task = { fn: fn, next: undefined };
3940           if (last) last.next = task;
3941           if (!head) {
3942             head = task;
3943             notify$1();
3944           } last = task;
3945         };
3946
3947         var newPromiseCapability$2 = {};
3948
3949         var aCallable$6 = aCallable$a;
3950
3951         var PromiseCapability = function (C) {
3952           var resolve, reject;
3953           this.promise = new C(function ($$resolve, $$reject) {
3954             if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');
3955             resolve = $$resolve;
3956             reject = $$reject;
3957           });
3958           this.resolve = aCallable$6(resolve);
3959           this.reject = aCallable$6(reject);
3960         };
3961
3962         // `NewPromiseCapability` abstract operation
3963         // https://tc39.es/ecma262/#sec-newpromisecapability
3964         newPromiseCapability$2.f = function (C) {
3965           return new PromiseCapability(C);
3966         };
3967
3968         var anObject$a = anObject$n;
3969         var isObject$j = isObject$s;
3970         var newPromiseCapability$1 = newPromiseCapability$2;
3971
3972         var promiseResolve$2 = function (C, x) {
3973           anObject$a(C);
3974           if (isObject$j(x) && x.constructor === C) return x;
3975           var promiseCapability = newPromiseCapability$1.f(C);
3976           var resolve = promiseCapability.resolve;
3977           resolve(x);
3978           return promiseCapability.promise;
3979         };
3980
3981         var global$A = global$1o;
3982
3983         var hostReportErrors$1 = function (a, b) {
3984           var console = global$A.console;
3985           if (console && console.error) {
3986             arguments.length == 1 ? console.error(a) : console.error(a, b);
3987           }
3988         };
3989
3990         var perform$1 = function (exec) {
3991           try {
3992             return { error: false, value: exec() };
3993           } catch (error) {
3994             return { error: true, value: error };
3995           }
3996         };
3997
3998         var Queue$1 = function () {
3999           this.head = null;
4000           this.tail = null;
4001         };
4002
4003         Queue$1.prototype = {
4004           add: function (item) {
4005             var entry = { item: item, next: null };
4006             if (this.head) this.tail.next = entry;
4007             else this.head = entry;
4008             this.tail = entry;
4009           },
4010           get: function () {
4011             var entry = this.head;
4012             if (entry) {
4013               this.head = entry.next;
4014               if (this.tail === entry) this.tail = null;
4015               return entry.item;
4016             }
4017           }
4018         };
4019
4020         var queue = Queue$1;
4021
4022         var engineIsBrowser = typeof window == 'object';
4023
4024         var $$$ = _export;
4025         var global$z = global$1o;
4026         var getBuiltIn$3 = getBuiltIn$b;
4027         var call$e = functionCall;
4028         var NativePromise$1 = nativePromiseConstructor;
4029         var redefine$8 = redefine$h.exports;
4030         var redefineAll$2 = redefineAll$4;
4031         var setPrototypeOf$3 = objectSetPrototypeOf;
4032         var setToStringTag$5 = setToStringTag$a;
4033         var setSpecies$3 = setSpecies$5;
4034         var aCallable$5 = aCallable$a;
4035         var isCallable$7 = isCallable$r;
4036         var isObject$i = isObject$s;
4037         var anInstance$5 = anInstance$7;
4038         var inspectSource = inspectSource$4;
4039         var iterate$2 = iterate$3;
4040         var checkCorrectnessOfIteration$3 = checkCorrectnessOfIteration$4;
4041         var speciesConstructor$3 = speciesConstructor$5;
4042         var task = task$1.set;
4043         var microtask = microtask$1;
4044         var promiseResolve$1 = promiseResolve$2;
4045         var hostReportErrors = hostReportErrors$1;
4046         var newPromiseCapabilityModule = newPromiseCapability$2;
4047         var perform = perform$1;
4048         var Queue = queue;
4049         var InternalStateModule$4 = internalState;
4050         var isForced$3 = isForced_1;
4051         var wellKnownSymbol$a = wellKnownSymbol$t;
4052         var IS_BROWSER = engineIsBrowser;
4053         var IS_NODE$2 = engineIsNode;
4054         var V8_VERSION$1 = engineV8Version;
4055
4056         var SPECIES$2 = wellKnownSymbol$a('species');
4057         var PROMISE = 'Promise';
4058
4059         var getInternalState$1 = InternalStateModule$4.getterFor(PROMISE);
4060         var setInternalState$4 = InternalStateModule$4.set;
4061         var getInternalPromiseState = InternalStateModule$4.getterFor(PROMISE);
4062         var NativePromisePrototype = NativePromise$1 && NativePromise$1.prototype;
4063         var PromiseConstructor = NativePromise$1;
4064         var PromisePrototype = NativePromisePrototype;
4065         var TypeError$a = global$z.TypeError;
4066         var document$1 = global$z.document;
4067         var process$1 = global$z.process;
4068         var newPromiseCapability = newPromiseCapabilityModule.f;
4069         var newGenericPromiseCapability = newPromiseCapability;
4070
4071         var DISPATCH_EVENT = !!(document$1 && document$1.createEvent && global$z.dispatchEvent);
4072         var NATIVE_REJECTION_EVENT = isCallable$7(global$z.PromiseRejectionEvent);
4073         var UNHANDLED_REJECTION = 'unhandledrejection';
4074         var REJECTION_HANDLED = 'rejectionhandled';
4075         var PENDING = 0;
4076         var FULFILLED = 1;
4077         var REJECTED = 2;
4078         var HANDLED = 1;
4079         var UNHANDLED = 2;
4080         var SUBCLASSING = false;
4081
4082         var Internal, OwnPromiseCapability, PromiseWrapper, nativeThen;
4083
4084         var FORCED$g = isForced$3(PROMISE, function () {
4085           var PROMISE_CONSTRUCTOR_SOURCE = inspectSource(PromiseConstructor);
4086           var GLOBAL_CORE_JS_PROMISE = PROMISE_CONSTRUCTOR_SOURCE !== String(PromiseConstructor);
4087           // V8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables
4088           // https://bugs.chromium.org/p/chromium/issues/detail?id=830565
4089           // We can't detect it synchronously, so just check versions
4090           if (!GLOBAL_CORE_JS_PROMISE && V8_VERSION$1 === 66) return true;
4091           // We can't use @@species feature detection in V8 since it causes
4092           // deoptimization and performance degradation
4093           // https://github.com/zloirock/core-js/issues/679
4094           if (V8_VERSION$1 >= 51 && /native code/.test(PROMISE_CONSTRUCTOR_SOURCE)) return false;
4095           // Detect correctness of subclassing with @@species support
4096           var promise = new PromiseConstructor(function (resolve) { resolve(1); });
4097           var FakePromise = function (exec) {
4098             exec(function () { /* empty */ }, function () { /* empty */ });
4099           };
4100           var constructor = promise.constructor = {};
4101           constructor[SPECIES$2] = FakePromise;
4102           SUBCLASSING = promise.then(function () { /* empty */ }) instanceof FakePromise;
4103           if (!SUBCLASSING) return true;
4104           // Unhandled rejections tracking support, NodeJS Promise without it fails @@species test
4105           return !GLOBAL_CORE_JS_PROMISE && IS_BROWSER && !NATIVE_REJECTION_EVENT;
4106         });
4107
4108         var INCORRECT_ITERATION$1 = FORCED$g || !checkCorrectnessOfIteration$3(function (iterable) {
4109           PromiseConstructor.all(iterable)['catch'](function () { /* empty */ });
4110         });
4111
4112         // helpers
4113         var isThenable = function (it) {
4114           var then;
4115           return isObject$i(it) && isCallable$7(then = it.then) ? then : false;
4116         };
4117
4118         var callReaction = function (reaction, state) {
4119           var value = state.value;
4120           var ok = state.state == FULFILLED;
4121           var handler = ok ? reaction.ok : reaction.fail;
4122           var resolve = reaction.resolve;
4123           var reject = reaction.reject;
4124           var domain = reaction.domain;
4125           var result, then, exited;
4126           try {
4127             if (handler) {
4128               if (!ok) {
4129                 if (state.rejection === UNHANDLED) onHandleUnhandled(state);
4130                 state.rejection = HANDLED;
4131               }
4132               if (handler === true) result = value;
4133               else {
4134                 if (domain) domain.enter();
4135                 result = handler(value); // can throw
4136                 if (domain) {
4137                   domain.exit();
4138                   exited = true;
4139                 }
4140               }
4141               if (result === reaction.promise) {
4142                 reject(TypeError$a('Promise-chain cycle'));
4143               } else if (then = isThenable(result)) {
4144                 call$e(then, result, resolve, reject);
4145               } else resolve(result);
4146             } else reject(value);
4147           } catch (error) {
4148             if (domain && !exited) domain.exit();
4149             reject(error);
4150           }
4151         };
4152
4153         var notify = function (state, isReject) {
4154           if (state.notified) return;
4155           state.notified = true;
4156           microtask(function () {
4157             var reactions = state.reactions;
4158             var reaction;
4159             while (reaction = reactions.get()) {
4160               callReaction(reaction, state);
4161             }
4162             state.notified = false;
4163             if (isReject && !state.rejection) onUnhandled(state);
4164           });
4165         };
4166
4167         var dispatchEvent$1 = function (name, promise, reason) {
4168           var event, handler;
4169           if (DISPATCH_EVENT) {
4170             event = document$1.createEvent('Event');
4171             event.promise = promise;
4172             event.reason = reason;
4173             event.initEvent(name, false, true);
4174             global$z.dispatchEvent(event);
4175           } else event = { promise: promise, reason: reason };
4176           if (!NATIVE_REJECTION_EVENT && (handler = global$z['on' + name])) handler(event);
4177           else if (name === UNHANDLED_REJECTION) hostReportErrors('Unhandled promise rejection', reason);
4178         };
4179
4180         var onUnhandled = function (state) {
4181           call$e(task, global$z, function () {
4182             var promise = state.facade;
4183             var value = state.value;
4184             var IS_UNHANDLED = isUnhandled(state);
4185             var result;
4186             if (IS_UNHANDLED) {
4187               result = perform(function () {
4188                 if (IS_NODE$2) {
4189                   process$1.emit('unhandledRejection', value, promise);
4190                 } else dispatchEvent$1(UNHANDLED_REJECTION, promise, value);
4191               });
4192               // Browsers should not trigger `rejectionHandled` event if it was handled here, NodeJS - should
4193               state.rejection = IS_NODE$2 || isUnhandled(state) ? UNHANDLED : HANDLED;
4194               if (result.error) throw result.value;
4195             }
4196           });
4197         };
4198
4199         var isUnhandled = function (state) {
4200           return state.rejection !== HANDLED && !state.parent;
4201         };
4202
4203         var onHandleUnhandled = function (state) {
4204           call$e(task, global$z, function () {
4205             var promise = state.facade;
4206             if (IS_NODE$2) {
4207               process$1.emit('rejectionHandled', promise);
4208             } else dispatchEvent$1(REJECTION_HANDLED, promise, state.value);
4209           });
4210         };
4211
4212         var bind$a = function (fn, state, unwrap) {
4213           return function (value) {
4214             fn(state, value, unwrap);
4215           };
4216         };
4217
4218         var internalReject = function (state, value, unwrap) {
4219           if (state.done) return;
4220           state.done = true;
4221           if (unwrap) state = unwrap;
4222           state.value = value;
4223           state.state = REJECTED;
4224           notify(state, true);
4225         };
4226
4227         var internalResolve = function (state, value, unwrap) {
4228           if (state.done) return;
4229           state.done = true;
4230           if (unwrap) state = unwrap;
4231           try {
4232             if (state.facade === value) throw TypeError$a("Promise can't be resolved itself");
4233             var then = isThenable(value);
4234             if (then) {
4235               microtask(function () {
4236                 var wrapper = { done: false };
4237                 try {
4238                   call$e(then, value,
4239                     bind$a(internalResolve, wrapper, state),
4240                     bind$a(internalReject, wrapper, state)
4241                   );
4242                 } catch (error) {
4243                   internalReject(wrapper, error, state);
4244                 }
4245               });
4246             } else {
4247               state.value = value;
4248               state.state = FULFILLED;
4249               notify(state, false);
4250             }
4251           } catch (error) {
4252             internalReject({ done: false }, error, state);
4253           }
4254         };
4255
4256         // constructor polyfill
4257         if (FORCED$g) {
4258           // 25.4.3.1 Promise(executor)
4259           PromiseConstructor = function Promise(executor) {
4260             anInstance$5(this, PromisePrototype);
4261             aCallable$5(executor);
4262             call$e(Internal, this);
4263             var state = getInternalState$1(this);
4264             try {
4265               executor(bind$a(internalResolve, state), bind$a(internalReject, state));
4266             } catch (error) {
4267               internalReject(state, error);
4268             }
4269           };
4270           PromisePrototype = PromiseConstructor.prototype;
4271           // eslint-disable-next-line no-unused-vars -- required for `.length`
4272           Internal = function Promise(executor) {
4273             setInternalState$4(this, {
4274               type: PROMISE,
4275               done: false,
4276               notified: false,
4277               parent: false,
4278               reactions: new Queue(),
4279               rejection: false,
4280               state: PENDING,
4281               value: undefined
4282             });
4283           };
4284           Internal.prototype = redefineAll$2(PromisePrototype, {
4285             // `Promise.prototype.then` method
4286             // https://tc39.es/ecma262/#sec-promise.prototype.then
4287             // eslint-disable-next-line unicorn/no-thenable -- safe
4288             then: function then(onFulfilled, onRejected) {
4289               var state = getInternalPromiseState(this);
4290               var reaction = newPromiseCapability(speciesConstructor$3(this, PromiseConstructor));
4291               state.parent = true;
4292               reaction.ok = isCallable$7(onFulfilled) ? onFulfilled : true;
4293               reaction.fail = isCallable$7(onRejected) && onRejected;
4294               reaction.domain = IS_NODE$2 ? process$1.domain : undefined;
4295               if (state.state == PENDING) state.reactions.add(reaction);
4296               else microtask(function () {
4297                 callReaction(reaction, state);
4298               });
4299               return reaction.promise;
4300             },
4301             // `Promise.prototype.catch` method
4302             // https://tc39.es/ecma262/#sec-promise.prototype.catch
4303             'catch': function (onRejected) {
4304               return this.then(undefined, onRejected);
4305             }
4306           });
4307           OwnPromiseCapability = function () {
4308             var promise = new Internal();
4309             var state = getInternalState$1(promise);
4310             this.promise = promise;
4311             this.resolve = bind$a(internalResolve, state);
4312             this.reject = bind$a(internalReject, state);
4313           };
4314           newPromiseCapabilityModule.f = newPromiseCapability = function (C) {
4315             return C === PromiseConstructor || C === PromiseWrapper
4316               ? new OwnPromiseCapability(C)
4317               : newGenericPromiseCapability(C);
4318           };
4319
4320           if (isCallable$7(NativePromise$1) && NativePromisePrototype !== Object.prototype) {
4321             nativeThen = NativePromisePrototype.then;
4322
4323             if (!SUBCLASSING) {
4324               // make `Promise#then` return a polyfilled `Promise` for native promise-based APIs
4325               redefine$8(NativePromisePrototype, 'then', function then(onFulfilled, onRejected) {
4326                 var that = this;
4327                 return new PromiseConstructor(function (resolve, reject) {
4328                   call$e(nativeThen, that, resolve, reject);
4329                 }).then(onFulfilled, onRejected);
4330               // https://github.com/zloirock/core-js/issues/640
4331               }, { unsafe: true });
4332
4333               // makes sure that native promise-based APIs `Promise#catch` properly works with patched `Promise#then`
4334               redefine$8(NativePromisePrototype, 'catch', PromisePrototype['catch'], { unsafe: true });
4335             }
4336
4337             // make `.constructor === Promise` work for native promise-based APIs
4338             try {
4339               delete NativePromisePrototype.constructor;
4340             } catch (error) { /* empty */ }
4341
4342             // make `instanceof Promise` work for native promise-based APIs
4343             if (setPrototypeOf$3) {
4344               setPrototypeOf$3(NativePromisePrototype, PromisePrototype);
4345             }
4346           }
4347         }
4348
4349         $$$({ global: true, wrap: true, forced: FORCED$g }, {
4350           Promise: PromiseConstructor
4351         });
4352
4353         setToStringTag$5(PromiseConstructor, PROMISE, false);
4354         setSpecies$3(PROMISE);
4355
4356         PromiseWrapper = getBuiltIn$3(PROMISE);
4357
4358         // statics
4359         $$$({ target: PROMISE, stat: true, forced: FORCED$g }, {
4360           // `Promise.reject` method
4361           // https://tc39.es/ecma262/#sec-promise.reject
4362           reject: function reject(r) {
4363             var capability = newPromiseCapability(this);
4364             call$e(capability.reject, undefined, r);
4365             return capability.promise;
4366           }
4367         });
4368
4369         $$$({ target: PROMISE, stat: true, forced: FORCED$g }, {
4370           // `Promise.resolve` method
4371           // https://tc39.es/ecma262/#sec-promise.resolve
4372           resolve: function resolve(x) {
4373             return promiseResolve$1(this, x);
4374           }
4375         });
4376
4377         $$$({ target: PROMISE, stat: true, forced: INCORRECT_ITERATION$1 }, {
4378           // `Promise.all` method
4379           // https://tc39.es/ecma262/#sec-promise.all
4380           all: function all(iterable) {
4381             var C = this;
4382             var capability = newPromiseCapability(C);
4383             var resolve = capability.resolve;
4384             var reject = capability.reject;
4385             var result = perform(function () {
4386               var $promiseResolve = aCallable$5(C.resolve);
4387               var values = [];
4388               var counter = 0;
4389               var remaining = 1;
4390               iterate$2(iterable, function (promise) {
4391                 var index = counter++;
4392                 var alreadyCalled = false;
4393                 remaining++;
4394                 call$e($promiseResolve, C, promise).then(function (value) {
4395                   if (alreadyCalled) return;
4396                   alreadyCalled = true;
4397                   values[index] = value;
4398                   --remaining || resolve(values);
4399                 }, reject);
4400               });
4401               --remaining || resolve(values);
4402             });
4403             if (result.error) reject(result.value);
4404             return capability.promise;
4405           },
4406           // `Promise.race` method
4407           // https://tc39.es/ecma262/#sec-promise.race
4408           race: function race(iterable) {
4409             var C = this;
4410             var capability = newPromiseCapability(C);
4411             var reject = capability.reject;
4412             var result = perform(function () {
4413               var $promiseResolve = aCallable$5(C.resolve);
4414               iterate$2(iterable, function (promise) {
4415                 call$e($promiseResolve, C, promise).then(capability.resolve, reject);
4416               });
4417             });
4418             if (result.error) reject(result.value);
4419             return capability.promise;
4420           }
4421         });
4422
4423         var typedArrayConstructor = {exports: {}};
4424
4425         /* eslint-disable no-new -- required for testing */
4426
4427         var global$y = global$1o;
4428         var fails$A = fails$V;
4429         var checkCorrectnessOfIteration$2 = checkCorrectnessOfIteration$4;
4430         var NATIVE_ARRAY_BUFFER_VIEWS$1 = arrayBufferViewCore.NATIVE_ARRAY_BUFFER_VIEWS;
4431
4432         var ArrayBuffer$2 = global$y.ArrayBuffer;
4433         var Int8Array$3 = global$y.Int8Array;
4434
4435         var typedArrayConstructorsRequireWrappers = !NATIVE_ARRAY_BUFFER_VIEWS$1 || !fails$A(function () {
4436           Int8Array$3(1);
4437         }) || !fails$A(function () {
4438           new Int8Array$3(-1);
4439         }) || !checkCorrectnessOfIteration$2(function (iterable) {
4440           new Int8Array$3();
4441           new Int8Array$3(null);
4442           new Int8Array$3(1.5);
4443           new Int8Array$3(iterable);
4444         }, true) || fails$A(function () {
4445           // Safari (11+) bug - a reason why even Safari 13 should load a typed array polyfill
4446           return new Int8Array$3(new ArrayBuffer$2(2), 1, undefined).length !== 1;
4447         });
4448
4449         var isObject$h = isObject$s;
4450
4451         var floor$6 = Math.floor;
4452
4453         // `IsIntegralNumber` abstract operation
4454         // https://tc39.es/ecma262/#sec-isintegralnumber
4455         // eslint-disable-next-line es/no-number-isinteger -- safe
4456         var isIntegralNumber$1 = Number.isInteger || function isInteger(it) {
4457           return !isObject$h(it) && isFinite(it) && floor$6(it) === it;
4458         };
4459
4460         var global$x = global$1o;
4461         var toIntegerOrInfinity$5 = toIntegerOrInfinity$b;
4462
4463         var RangeError$9 = global$x.RangeError;
4464
4465         var toPositiveInteger$1 = function (it) {
4466           var result = toIntegerOrInfinity$5(it);
4467           if (result < 0) throw RangeError$9("The argument can't be less than 0");
4468           return result;
4469         };
4470
4471         var global$w = global$1o;
4472         var toPositiveInteger = toPositiveInteger$1;
4473
4474         var RangeError$8 = global$w.RangeError;
4475
4476         var toOffset$2 = function (it, BYTES) {
4477           var offset = toPositiveInteger(it);
4478           if (offset % BYTES) throw RangeError$8('Wrong offset');
4479           return offset;
4480         };
4481
4482         var bind$9 = functionBindContext;
4483         var call$d = functionCall;
4484         var aConstructor$1 = aConstructor$3;
4485         var toObject$c = toObject$i;
4486         var lengthOfArrayLike$c = lengthOfArrayLike$i;
4487         var getIterator$2 = getIterator$4;
4488         var getIteratorMethod$2 = getIteratorMethod$5;
4489         var isArrayIteratorMethod$1 = isArrayIteratorMethod$3;
4490         var aTypedArrayConstructor$2 = arrayBufferViewCore.aTypedArrayConstructor;
4491
4492         var typedArrayFrom$2 = function from(source /* , mapfn, thisArg */) {
4493           var C = aConstructor$1(this);
4494           var O = toObject$c(source);
4495           var argumentsLength = arguments.length;
4496           var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
4497           var mapping = mapfn !== undefined;
4498           var iteratorMethod = getIteratorMethod$2(O);
4499           var i, length, result, step, iterator, next;
4500           if (iteratorMethod && !isArrayIteratorMethod$1(iteratorMethod)) {
4501             iterator = getIterator$2(O, iteratorMethod);
4502             next = iterator.next;
4503             O = [];
4504             while (!(step = call$d(next, iterator)).done) {
4505               O.push(step.value);
4506             }
4507           }
4508           if (mapping && argumentsLength > 2) {
4509             mapfn = bind$9(mapfn, arguments[2]);
4510           }
4511           length = lengthOfArrayLike$c(O);
4512           result = new (aTypedArrayConstructor$2(C))(length);
4513           for (i = 0; length > i; i++) {
4514             result[i] = mapping ? mapfn(O[i], i) : O[i];
4515           }
4516           return result;
4517         };
4518
4519         var isCallable$6 = isCallable$r;
4520         var isObject$g = isObject$s;
4521         var setPrototypeOf$2 = objectSetPrototypeOf;
4522
4523         // makes subclassing work correct for wrapped built-ins
4524         var inheritIfRequired$4 = function ($this, dummy, Wrapper) {
4525           var NewTarget, NewTargetPrototype;
4526           if (
4527             // it can work only with native `setPrototypeOf`
4528             setPrototypeOf$2 &&
4529             // we haven't completely correct pre-ES6 way for getting `new.target`, so use this
4530             isCallable$6(NewTarget = dummy.constructor) &&
4531             NewTarget !== Wrapper &&
4532             isObject$g(NewTargetPrototype = NewTarget.prototype) &&
4533             NewTargetPrototype !== Wrapper.prototype
4534           ) setPrototypeOf$2($this, NewTargetPrototype);
4535           return $this;
4536         };
4537
4538         var $$_ = _export;
4539         var global$v = global$1o;
4540         var call$c = functionCall;
4541         var DESCRIPTORS$c = descriptors;
4542         var TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS$1 = typedArrayConstructorsRequireWrappers;
4543         var ArrayBufferViewCore$n = arrayBufferViewCore;
4544         var ArrayBufferModule = arrayBuffer;
4545         var anInstance$4 = anInstance$7;
4546         var createPropertyDescriptor$1 = createPropertyDescriptor$7;
4547         var createNonEnumerableProperty$2 = createNonEnumerableProperty$b;
4548         var isIntegralNumber = isIntegralNumber$1;
4549         var toLength$7 = toLength$c;
4550         var toIndex = toIndex$2;
4551         var toOffset$1 = toOffset$2;
4552         var toPropertyKey = toPropertyKey$5;
4553         var hasOwn$7 = hasOwnProperty_1;
4554         var classof$4 = classof$d;
4555         var isObject$f = isObject$s;
4556         var isSymbol$2 = isSymbol$6;
4557         var create$7 = objectCreate;
4558         var isPrototypeOf$3 = objectIsPrototypeOf;
4559         var setPrototypeOf$1 = objectSetPrototypeOf;
4560         var getOwnPropertyNames$2 = objectGetOwnPropertyNames.f;
4561         var typedArrayFrom$1 = typedArrayFrom$2;
4562         var forEach$1 = arrayIteration.forEach;
4563         var setSpecies$2 = setSpecies$5;
4564         var definePropertyModule = objectDefineProperty;
4565         var getOwnPropertyDescriptorModule$1 = objectGetOwnPropertyDescriptor;
4566         var InternalStateModule$3 = internalState;
4567         var inheritIfRequired$3 = inheritIfRequired$4;
4568
4569         var getInternalState = InternalStateModule$3.get;
4570         var setInternalState$3 = InternalStateModule$3.set;
4571         var nativeDefineProperty = definePropertyModule.f;
4572         var nativeGetOwnPropertyDescriptor$1 = getOwnPropertyDescriptorModule$1.f;
4573         var round = Math.round;
4574         var RangeError$7 = global$v.RangeError;
4575         var ArrayBuffer$1 = ArrayBufferModule.ArrayBuffer;
4576         var ArrayBufferPrototype = ArrayBuffer$1.prototype;
4577         var DataView$1 = ArrayBufferModule.DataView;
4578         var NATIVE_ARRAY_BUFFER_VIEWS = ArrayBufferViewCore$n.NATIVE_ARRAY_BUFFER_VIEWS;
4579         var TYPED_ARRAY_CONSTRUCTOR$1 = ArrayBufferViewCore$n.TYPED_ARRAY_CONSTRUCTOR;
4580         var TYPED_ARRAY_TAG = ArrayBufferViewCore$n.TYPED_ARRAY_TAG;
4581         var TypedArray = ArrayBufferViewCore$n.TypedArray;
4582         var TypedArrayPrototype$1 = ArrayBufferViewCore$n.TypedArrayPrototype;
4583         var aTypedArrayConstructor$1 = ArrayBufferViewCore$n.aTypedArrayConstructor;
4584         var isTypedArray = ArrayBufferViewCore$n.isTypedArray;
4585         var BYTES_PER_ELEMENT = 'BYTES_PER_ELEMENT';
4586         var WRONG_LENGTH = 'Wrong length';
4587
4588         var fromList = function (C, list) {
4589           aTypedArrayConstructor$1(C);
4590           var index = 0;
4591           var length = list.length;
4592           var result = new C(length);
4593           while (length > index) result[index] = list[index++];
4594           return result;
4595         };
4596
4597         var addGetter = function (it, key) {
4598           nativeDefineProperty(it, key, { get: function () {
4599             return getInternalState(this)[key];
4600           } });
4601         };
4602
4603         var isArrayBuffer = function (it) {
4604           var klass;
4605           return isPrototypeOf$3(ArrayBufferPrototype, it) || (klass = classof$4(it)) == 'ArrayBuffer' || klass == 'SharedArrayBuffer';
4606         };
4607
4608         var isTypedArrayIndex = function (target, key) {
4609           return isTypedArray(target)
4610             && !isSymbol$2(key)
4611             && key in target
4612             && isIntegralNumber(+key)
4613             && key >= 0;
4614         };
4615
4616         var wrappedGetOwnPropertyDescriptor = function getOwnPropertyDescriptor(target, key) {
4617           key = toPropertyKey(key);
4618           return isTypedArrayIndex(target, key)
4619             ? createPropertyDescriptor$1(2, target[key])
4620             : nativeGetOwnPropertyDescriptor$1(target, key);
4621         };
4622
4623         var wrappedDefineProperty = function defineProperty(target, key, descriptor) {
4624           key = toPropertyKey(key);
4625           if (isTypedArrayIndex(target, key)
4626             && isObject$f(descriptor)
4627             && hasOwn$7(descriptor, 'value')
4628             && !hasOwn$7(descriptor, 'get')
4629             && !hasOwn$7(descriptor, 'set')
4630             // TODO: add validation descriptor w/o calling accessors
4631             && !descriptor.configurable
4632             && (!hasOwn$7(descriptor, 'writable') || descriptor.writable)
4633             && (!hasOwn$7(descriptor, 'enumerable') || descriptor.enumerable)
4634           ) {
4635             target[key] = descriptor.value;
4636             return target;
4637           } return nativeDefineProperty(target, key, descriptor);
4638         };
4639
4640         if (DESCRIPTORS$c) {
4641           if (!NATIVE_ARRAY_BUFFER_VIEWS) {
4642             getOwnPropertyDescriptorModule$1.f = wrappedGetOwnPropertyDescriptor;
4643             definePropertyModule.f = wrappedDefineProperty;
4644             addGetter(TypedArrayPrototype$1, 'buffer');
4645             addGetter(TypedArrayPrototype$1, 'byteOffset');
4646             addGetter(TypedArrayPrototype$1, 'byteLength');
4647             addGetter(TypedArrayPrototype$1, 'length');
4648           }
4649
4650           $$_({ target: 'Object', stat: true, forced: !NATIVE_ARRAY_BUFFER_VIEWS }, {
4651             getOwnPropertyDescriptor: wrappedGetOwnPropertyDescriptor,
4652             defineProperty: wrappedDefineProperty
4653           });
4654
4655           typedArrayConstructor.exports = function (TYPE, wrapper, CLAMPED) {
4656             var BYTES = TYPE.match(/\d+$/)[0] / 8;
4657             var CONSTRUCTOR_NAME = TYPE + (CLAMPED ? 'Clamped' : '') + 'Array';
4658             var GETTER = 'get' + TYPE;
4659             var SETTER = 'set' + TYPE;
4660             var NativeTypedArrayConstructor = global$v[CONSTRUCTOR_NAME];
4661             var TypedArrayConstructor = NativeTypedArrayConstructor;
4662             var TypedArrayConstructorPrototype = TypedArrayConstructor && TypedArrayConstructor.prototype;
4663             var exported = {};
4664
4665             var getter = function (that, index) {
4666               var data = getInternalState(that);
4667               return data.view[GETTER](index * BYTES + data.byteOffset, true);
4668             };
4669
4670             var setter = function (that, index, value) {
4671               var data = getInternalState(that);
4672               if (CLAMPED) value = (value = round(value)) < 0 ? 0 : value > 0xFF ? 0xFF : value & 0xFF;
4673               data.view[SETTER](index * BYTES + data.byteOffset, value, true);
4674             };
4675
4676             var addElement = function (that, index) {
4677               nativeDefineProperty(that, index, {
4678                 get: function () {
4679                   return getter(this, index);
4680                 },
4681                 set: function (value) {
4682                   return setter(this, index, value);
4683                 },
4684                 enumerable: true
4685               });
4686             };
4687
4688             if (!NATIVE_ARRAY_BUFFER_VIEWS) {
4689               TypedArrayConstructor = wrapper(function (that, data, offset, $length) {
4690                 anInstance$4(that, TypedArrayConstructorPrototype);
4691                 var index = 0;
4692                 var byteOffset = 0;
4693                 var buffer, byteLength, length;
4694                 if (!isObject$f(data)) {
4695                   length = toIndex(data);
4696                   byteLength = length * BYTES;
4697                   buffer = new ArrayBuffer$1(byteLength);
4698                 } else if (isArrayBuffer(data)) {
4699                   buffer = data;
4700                   byteOffset = toOffset$1(offset, BYTES);
4701                   var $len = data.byteLength;
4702                   if ($length === undefined) {
4703                     if ($len % BYTES) throw RangeError$7(WRONG_LENGTH);
4704                     byteLength = $len - byteOffset;
4705                     if (byteLength < 0) throw RangeError$7(WRONG_LENGTH);
4706                   } else {
4707                     byteLength = toLength$7($length) * BYTES;
4708                     if (byteLength + byteOffset > $len) throw RangeError$7(WRONG_LENGTH);
4709                   }
4710                   length = byteLength / BYTES;
4711                 } else if (isTypedArray(data)) {
4712                   return fromList(TypedArrayConstructor, data);
4713                 } else {
4714                   return call$c(typedArrayFrom$1, TypedArrayConstructor, data);
4715                 }
4716                 setInternalState$3(that, {
4717                   buffer: buffer,
4718                   byteOffset: byteOffset,
4719                   byteLength: byteLength,
4720                   length: length,
4721                   view: new DataView$1(buffer)
4722                 });
4723                 while (index < length) addElement(that, index++);
4724               });
4725
4726               if (setPrototypeOf$1) setPrototypeOf$1(TypedArrayConstructor, TypedArray);
4727               TypedArrayConstructorPrototype = TypedArrayConstructor.prototype = create$7(TypedArrayPrototype$1);
4728             } else if (TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS$1) {
4729               TypedArrayConstructor = wrapper(function (dummy, data, typedArrayOffset, $length) {
4730                 anInstance$4(dummy, TypedArrayConstructorPrototype);
4731                 return inheritIfRequired$3(function () {
4732                   if (!isObject$f(data)) return new NativeTypedArrayConstructor(toIndex(data));
4733                   if (isArrayBuffer(data)) return $length !== undefined
4734                     ? new NativeTypedArrayConstructor(data, toOffset$1(typedArrayOffset, BYTES), $length)
4735                     : typedArrayOffset !== undefined
4736                       ? new NativeTypedArrayConstructor(data, toOffset$1(typedArrayOffset, BYTES))
4737                       : new NativeTypedArrayConstructor(data);
4738                   if (isTypedArray(data)) return fromList(TypedArrayConstructor, data);
4739                   return call$c(typedArrayFrom$1, TypedArrayConstructor, data);
4740                 }(), dummy, TypedArrayConstructor);
4741               });
4742
4743               if (setPrototypeOf$1) setPrototypeOf$1(TypedArrayConstructor, TypedArray);
4744               forEach$1(getOwnPropertyNames$2(NativeTypedArrayConstructor), function (key) {
4745                 if (!(key in TypedArrayConstructor)) {
4746                   createNonEnumerableProperty$2(TypedArrayConstructor, key, NativeTypedArrayConstructor[key]);
4747                 }
4748               });
4749               TypedArrayConstructor.prototype = TypedArrayConstructorPrototype;
4750             }
4751
4752             if (TypedArrayConstructorPrototype.constructor !== TypedArrayConstructor) {
4753               createNonEnumerableProperty$2(TypedArrayConstructorPrototype, 'constructor', TypedArrayConstructor);
4754             }
4755
4756             createNonEnumerableProperty$2(TypedArrayConstructorPrototype, TYPED_ARRAY_CONSTRUCTOR$1, TypedArrayConstructor);
4757
4758             if (TYPED_ARRAY_TAG) {
4759               createNonEnumerableProperty$2(TypedArrayConstructorPrototype, TYPED_ARRAY_TAG, CONSTRUCTOR_NAME);
4760             }
4761
4762             exported[CONSTRUCTOR_NAME] = TypedArrayConstructor;
4763
4764             $$_({
4765               global: true, forced: TypedArrayConstructor != NativeTypedArrayConstructor, sham: !NATIVE_ARRAY_BUFFER_VIEWS
4766             }, exported);
4767
4768             if (!(BYTES_PER_ELEMENT in TypedArrayConstructor)) {
4769               createNonEnumerableProperty$2(TypedArrayConstructor, BYTES_PER_ELEMENT, BYTES);
4770             }
4771
4772             if (!(BYTES_PER_ELEMENT in TypedArrayConstructorPrototype)) {
4773               createNonEnumerableProperty$2(TypedArrayConstructorPrototype, BYTES_PER_ELEMENT, BYTES);
4774             }
4775
4776             setSpecies$2(CONSTRUCTOR_NAME);
4777           };
4778         } else typedArrayConstructor.exports = function () { /* empty */ };
4779
4780         var createTypedArrayConstructor$1 = typedArrayConstructor.exports;
4781
4782         // `Uint8Array` constructor
4783         // https://tc39.es/ecma262/#sec-typedarray-objects
4784         createTypedArrayConstructor$1('Uint8', function (init) {
4785           return function Uint8Array(data, byteOffset, length) {
4786             return init(this, data, byteOffset, length);
4787           };
4788         });
4789
4790         var toObject$b = toObject$i;
4791         var toAbsoluteIndex$4 = toAbsoluteIndex$9;
4792         var lengthOfArrayLike$b = lengthOfArrayLike$i;
4793
4794         var min$7 = Math.min;
4795
4796         // `Array.prototype.copyWithin` method implementation
4797         // https://tc39.es/ecma262/#sec-array.prototype.copywithin
4798         // eslint-disable-next-line es/no-array-prototype-copywithin -- safe
4799         var arrayCopyWithin = [].copyWithin || function copyWithin(target /* = 0 */, start /* = 0, end = @length */) {
4800           var O = toObject$b(this);
4801           var len = lengthOfArrayLike$b(O);
4802           var to = toAbsoluteIndex$4(target, len);
4803           var from = toAbsoluteIndex$4(start, len);
4804           var end = arguments.length > 2 ? arguments[2] : undefined;
4805           var count = min$7((end === undefined ? len : toAbsoluteIndex$4(end, len)) - from, len - to);
4806           var inc = 1;
4807           if (from < to && to < from + count) {
4808             inc = -1;
4809             from += count - 1;
4810             to += count - 1;
4811           }
4812           while (count-- > 0) {
4813             if (from in O) O[to] = O[from];
4814             else delete O[to];
4815             to += inc;
4816             from += inc;
4817           } return O;
4818         };
4819
4820         var uncurryThis$A = functionUncurryThis;
4821         var ArrayBufferViewCore$m = arrayBufferViewCore;
4822         var $ArrayCopyWithin = arrayCopyWithin;
4823
4824         var u$ArrayCopyWithin = uncurryThis$A($ArrayCopyWithin);
4825         var aTypedArray$l = ArrayBufferViewCore$m.aTypedArray;
4826         var exportTypedArrayMethod$m = ArrayBufferViewCore$m.exportTypedArrayMethod;
4827
4828         // `%TypedArray%.prototype.copyWithin` method
4829         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.copywithin
4830         exportTypedArrayMethod$m('copyWithin', function copyWithin(target, start /* , end */) {
4831           return u$ArrayCopyWithin(aTypedArray$l(this), target, start, arguments.length > 2 ? arguments[2] : undefined);
4832         });
4833
4834         var ArrayBufferViewCore$l = arrayBufferViewCore;
4835         var $every$1 = arrayIteration.every;
4836
4837         var aTypedArray$k = ArrayBufferViewCore$l.aTypedArray;
4838         var exportTypedArrayMethod$l = ArrayBufferViewCore$l.exportTypedArrayMethod;
4839
4840         // `%TypedArray%.prototype.every` method
4841         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.every
4842         exportTypedArrayMethod$l('every', function every(callbackfn /* , thisArg */) {
4843           return $every$1(aTypedArray$k(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
4844         });
4845
4846         var ArrayBufferViewCore$k = arrayBufferViewCore;
4847         var call$b = functionCall;
4848         var $fill = arrayFill$1;
4849
4850         var aTypedArray$j = ArrayBufferViewCore$k.aTypedArray;
4851         var exportTypedArrayMethod$k = ArrayBufferViewCore$k.exportTypedArrayMethod;
4852
4853         // `%TypedArray%.prototype.fill` method
4854         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.fill
4855         exportTypedArrayMethod$k('fill', function fill(value /* , start, end */) {
4856           var length = arguments.length;
4857           return call$b(
4858             $fill,
4859             aTypedArray$j(this),
4860             value,
4861             length > 1 ? arguments[1] : undefined,
4862             length > 2 ? arguments[2] : undefined
4863           );
4864         });
4865
4866         var lengthOfArrayLike$a = lengthOfArrayLike$i;
4867
4868         var arrayFromConstructorAndList$1 = function (Constructor, list) {
4869           var index = 0;
4870           var length = lengthOfArrayLike$a(list);
4871           var result = new Constructor(length);
4872           while (length > index) result[index] = list[index++];
4873           return result;
4874         };
4875
4876         var ArrayBufferViewCore$j = arrayBufferViewCore;
4877         var speciesConstructor$2 = speciesConstructor$5;
4878
4879         var TYPED_ARRAY_CONSTRUCTOR = ArrayBufferViewCore$j.TYPED_ARRAY_CONSTRUCTOR;
4880         var aTypedArrayConstructor = ArrayBufferViewCore$j.aTypedArrayConstructor;
4881
4882         // a part of `TypedArraySpeciesCreate` abstract operation
4883         // https://tc39.es/ecma262/#typedarray-species-create
4884         var typedArraySpeciesConstructor$4 = function (originalArray) {
4885           return aTypedArrayConstructor(speciesConstructor$2(originalArray, originalArray[TYPED_ARRAY_CONSTRUCTOR]));
4886         };
4887
4888         var arrayFromConstructorAndList = arrayFromConstructorAndList$1;
4889         var typedArraySpeciesConstructor$3 = typedArraySpeciesConstructor$4;
4890
4891         var typedArrayFromSpeciesAndList = function (instance, list) {
4892           return arrayFromConstructorAndList(typedArraySpeciesConstructor$3(instance), list);
4893         };
4894
4895         var ArrayBufferViewCore$i = arrayBufferViewCore;
4896         var $filter$1 = arrayIteration.filter;
4897         var fromSpeciesAndList = typedArrayFromSpeciesAndList;
4898
4899         var aTypedArray$i = ArrayBufferViewCore$i.aTypedArray;
4900         var exportTypedArrayMethod$j = ArrayBufferViewCore$i.exportTypedArrayMethod;
4901
4902         // `%TypedArray%.prototype.filter` method
4903         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.filter
4904         exportTypedArrayMethod$j('filter', function filter(callbackfn /* , thisArg */) {
4905           var list = $filter$1(aTypedArray$i(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
4906           return fromSpeciesAndList(this, list);
4907         });
4908
4909         var ArrayBufferViewCore$h = arrayBufferViewCore;
4910         var $find$1 = arrayIteration.find;
4911
4912         var aTypedArray$h = ArrayBufferViewCore$h.aTypedArray;
4913         var exportTypedArrayMethod$i = ArrayBufferViewCore$h.exportTypedArrayMethod;
4914
4915         // `%TypedArray%.prototype.find` method
4916         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.find
4917         exportTypedArrayMethod$i('find', function find(predicate /* , thisArg */) {
4918           return $find$1(aTypedArray$h(this), predicate, arguments.length > 1 ? arguments[1] : undefined);
4919         });
4920
4921         var ArrayBufferViewCore$g = arrayBufferViewCore;
4922         var $findIndex$1 = arrayIteration.findIndex;
4923
4924         var aTypedArray$g = ArrayBufferViewCore$g.aTypedArray;
4925         var exportTypedArrayMethod$h = ArrayBufferViewCore$g.exportTypedArrayMethod;
4926
4927         // `%TypedArray%.prototype.findIndex` method
4928         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.findindex
4929         exportTypedArrayMethod$h('findIndex', function findIndex(predicate /* , thisArg */) {
4930           return $findIndex$1(aTypedArray$g(this), predicate, arguments.length > 1 ? arguments[1] : undefined);
4931         });
4932
4933         var ArrayBufferViewCore$f = arrayBufferViewCore;
4934         var $forEach = arrayIteration.forEach;
4935
4936         var aTypedArray$f = ArrayBufferViewCore$f.aTypedArray;
4937         var exportTypedArrayMethod$g = ArrayBufferViewCore$f.exportTypedArrayMethod;
4938
4939         // `%TypedArray%.prototype.forEach` method
4940         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.foreach
4941         exportTypedArrayMethod$g('forEach', function forEach(callbackfn /* , thisArg */) {
4942           $forEach(aTypedArray$f(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
4943         });
4944
4945         var ArrayBufferViewCore$e = arrayBufferViewCore;
4946         var $includes$1 = arrayIncludes.includes;
4947
4948         var aTypedArray$e = ArrayBufferViewCore$e.aTypedArray;
4949         var exportTypedArrayMethod$f = ArrayBufferViewCore$e.exportTypedArrayMethod;
4950
4951         // `%TypedArray%.prototype.includes` method
4952         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.includes
4953         exportTypedArrayMethod$f('includes', function includes(searchElement /* , fromIndex */) {
4954           return $includes$1(aTypedArray$e(this), searchElement, arguments.length > 1 ? arguments[1] : undefined);
4955         });
4956
4957         var ArrayBufferViewCore$d = arrayBufferViewCore;
4958         var $indexOf = arrayIncludes.indexOf;
4959
4960         var aTypedArray$d = ArrayBufferViewCore$d.aTypedArray;
4961         var exportTypedArrayMethod$e = ArrayBufferViewCore$d.exportTypedArrayMethod;
4962
4963         // `%TypedArray%.prototype.indexOf` method
4964         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.indexof
4965         exportTypedArrayMethod$e('indexOf', function indexOf(searchElement /* , fromIndex */) {
4966           return $indexOf(aTypedArray$d(this), searchElement, arguments.length > 1 ? arguments[1] : undefined);
4967         });
4968
4969         var global$u = global$1o;
4970         var fails$z = fails$V;
4971         var uncurryThis$z = functionUncurryThis;
4972         var ArrayBufferViewCore$c = arrayBufferViewCore;
4973         var ArrayIterators = es_array_iterator;
4974         var wellKnownSymbol$9 = wellKnownSymbol$t;
4975
4976         var ITERATOR$4 = wellKnownSymbol$9('iterator');
4977         var Uint8Array$2 = global$u.Uint8Array;
4978         var arrayValues = uncurryThis$z(ArrayIterators.values);
4979         var arrayKeys = uncurryThis$z(ArrayIterators.keys);
4980         var arrayEntries = uncurryThis$z(ArrayIterators.entries);
4981         var aTypedArray$c = ArrayBufferViewCore$c.aTypedArray;
4982         var exportTypedArrayMethod$d = ArrayBufferViewCore$c.exportTypedArrayMethod;
4983         var TypedArrayPrototype = Uint8Array$2 && Uint8Array$2.prototype;
4984
4985         var GENERIC = !fails$z(function () {
4986           TypedArrayPrototype[ITERATOR$4].call([1]);
4987         });
4988
4989         var ITERATOR_IS_VALUES = !!TypedArrayPrototype
4990           && TypedArrayPrototype.values
4991           && TypedArrayPrototype[ITERATOR$4] === TypedArrayPrototype.values
4992           && TypedArrayPrototype.values.name === 'values';
4993
4994         var typedArrayValues = function values() {
4995           return arrayValues(aTypedArray$c(this));
4996         };
4997
4998         // `%TypedArray%.prototype.entries` method
4999         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.entries
5000         exportTypedArrayMethod$d('entries', function entries() {
5001           return arrayEntries(aTypedArray$c(this));
5002         }, GENERIC);
5003         // `%TypedArray%.prototype.keys` method
5004         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.keys
5005         exportTypedArrayMethod$d('keys', function keys() {
5006           return arrayKeys(aTypedArray$c(this));
5007         }, GENERIC);
5008         // `%TypedArray%.prototype.values` method
5009         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.values
5010         exportTypedArrayMethod$d('values', typedArrayValues, GENERIC || !ITERATOR_IS_VALUES, { name: 'values' });
5011         // `%TypedArray%.prototype[@@iterator]` method
5012         // https://tc39.es/ecma262/#sec-%typedarray%.prototype-@@iterator
5013         exportTypedArrayMethod$d(ITERATOR$4, typedArrayValues, GENERIC || !ITERATOR_IS_VALUES, { name: 'values' });
5014
5015         var ArrayBufferViewCore$b = arrayBufferViewCore;
5016         var uncurryThis$y = functionUncurryThis;
5017
5018         var aTypedArray$b = ArrayBufferViewCore$b.aTypedArray;
5019         var exportTypedArrayMethod$c = ArrayBufferViewCore$b.exportTypedArrayMethod;
5020         var $join = uncurryThis$y([].join);
5021
5022         // `%TypedArray%.prototype.join` method
5023         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.join
5024         exportTypedArrayMethod$c('join', function join(separator) {
5025           return $join(aTypedArray$b(this), separator);
5026         });
5027
5028         /* eslint-disable es/no-array-prototype-lastindexof -- safe */
5029         var apply$6 = functionApply;
5030         var toIndexedObject$5 = toIndexedObject$d;
5031         var toIntegerOrInfinity$4 = toIntegerOrInfinity$b;
5032         var lengthOfArrayLike$9 = lengthOfArrayLike$i;
5033         var arrayMethodIsStrict$6 = arrayMethodIsStrict$9;
5034
5035         var min$6 = Math.min;
5036         var $lastIndexOf$1 = [].lastIndexOf;
5037         var NEGATIVE_ZERO = !!$lastIndexOf$1 && 1 / [1].lastIndexOf(1, -0) < 0;
5038         var STRICT_METHOD$6 = arrayMethodIsStrict$6('lastIndexOf');
5039         var FORCED$f = NEGATIVE_ZERO || !STRICT_METHOD$6;
5040
5041         // `Array.prototype.lastIndexOf` method implementation
5042         // https://tc39.es/ecma262/#sec-array.prototype.lastindexof
5043         var arrayLastIndexOf = FORCED$f ? function lastIndexOf(searchElement /* , fromIndex = @[*-1] */) {
5044           // convert -0 to +0
5045           if (NEGATIVE_ZERO) return apply$6($lastIndexOf$1, this, arguments) || 0;
5046           var O = toIndexedObject$5(this);
5047           var length = lengthOfArrayLike$9(O);
5048           var index = length - 1;
5049           if (arguments.length > 1) index = min$6(index, toIntegerOrInfinity$4(arguments[1]));
5050           if (index < 0) index = length + index;
5051           for (;index >= 0; index--) if (index in O && O[index] === searchElement) return index || 0;
5052           return -1;
5053         } : $lastIndexOf$1;
5054
5055         var ArrayBufferViewCore$a = arrayBufferViewCore;
5056         var apply$5 = functionApply;
5057         var $lastIndexOf = arrayLastIndexOf;
5058
5059         var aTypedArray$a = ArrayBufferViewCore$a.aTypedArray;
5060         var exportTypedArrayMethod$b = ArrayBufferViewCore$a.exportTypedArrayMethod;
5061
5062         // `%TypedArray%.prototype.lastIndexOf` method
5063         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.lastindexof
5064         exportTypedArrayMethod$b('lastIndexOf', function lastIndexOf(searchElement /* , fromIndex */) {
5065           var length = arguments.length;
5066           return apply$5($lastIndexOf, aTypedArray$a(this), length > 1 ? [searchElement, arguments[1]] : [searchElement]);
5067         });
5068
5069         var ArrayBufferViewCore$9 = arrayBufferViewCore;
5070         var $map = arrayIteration.map;
5071         var typedArraySpeciesConstructor$2 = typedArraySpeciesConstructor$4;
5072
5073         var aTypedArray$9 = ArrayBufferViewCore$9.aTypedArray;
5074         var exportTypedArrayMethod$a = ArrayBufferViewCore$9.exportTypedArrayMethod;
5075
5076         // `%TypedArray%.prototype.map` method
5077         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.map
5078         exportTypedArrayMethod$a('map', function map(mapfn /* , thisArg */) {
5079           return $map(aTypedArray$9(this), mapfn, arguments.length > 1 ? arguments[1] : undefined, function (O, length) {
5080             return new (typedArraySpeciesConstructor$2(O))(length);
5081           });
5082         });
5083
5084         var global$t = global$1o;
5085         var aCallable$4 = aCallable$a;
5086         var toObject$a = toObject$i;
5087         var IndexedObject$2 = indexedObject;
5088         var lengthOfArrayLike$8 = lengthOfArrayLike$i;
5089
5090         var TypeError$9 = global$t.TypeError;
5091
5092         // `Array.prototype.{ reduce, reduceRight }` methods implementation
5093         var createMethod$3 = function (IS_RIGHT) {
5094           return function (that, callbackfn, argumentsLength, memo) {
5095             aCallable$4(callbackfn);
5096             var O = toObject$a(that);
5097             var self = IndexedObject$2(O);
5098             var length = lengthOfArrayLike$8(O);
5099             var index = IS_RIGHT ? length - 1 : 0;
5100             var i = IS_RIGHT ? -1 : 1;
5101             if (argumentsLength < 2) while (true) {
5102               if (index in self) {
5103                 memo = self[index];
5104                 index += i;
5105                 break;
5106               }
5107               index += i;
5108               if (IS_RIGHT ? index < 0 : length <= index) {
5109                 throw TypeError$9('Reduce of empty array with no initial value');
5110               }
5111             }
5112             for (;IS_RIGHT ? index >= 0 : length > index; index += i) if (index in self) {
5113               memo = callbackfn(memo, self[index], index, O);
5114             }
5115             return memo;
5116           };
5117         };
5118
5119         var arrayReduce = {
5120           // `Array.prototype.reduce` method
5121           // https://tc39.es/ecma262/#sec-array.prototype.reduce
5122           left: createMethod$3(false),
5123           // `Array.prototype.reduceRight` method
5124           // https://tc39.es/ecma262/#sec-array.prototype.reduceright
5125           right: createMethod$3(true)
5126         };
5127
5128         var ArrayBufferViewCore$8 = arrayBufferViewCore;
5129         var $reduce$1 = arrayReduce.left;
5130
5131         var aTypedArray$8 = ArrayBufferViewCore$8.aTypedArray;
5132         var exportTypedArrayMethod$9 = ArrayBufferViewCore$8.exportTypedArrayMethod;
5133
5134         // `%TypedArray%.prototype.reduce` method
5135         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduce
5136         exportTypedArrayMethod$9('reduce', function reduce(callbackfn /* , initialValue */) {
5137           var length = arguments.length;
5138           return $reduce$1(aTypedArray$8(this), callbackfn, length, length > 1 ? arguments[1] : undefined);
5139         });
5140
5141         var ArrayBufferViewCore$7 = arrayBufferViewCore;
5142         var $reduceRight$1 = arrayReduce.right;
5143
5144         var aTypedArray$7 = ArrayBufferViewCore$7.aTypedArray;
5145         var exportTypedArrayMethod$8 = ArrayBufferViewCore$7.exportTypedArrayMethod;
5146
5147         // `%TypedArray%.prototype.reduceRicht` method
5148         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reduceright
5149         exportTypedArrayMethod$8('reduceRight', function reduceRight(callbackfn /* , initialValue */) {
5150           var length = arguments.length;
5151           return $reduceRight$1(aTypedArray$7(this), callbackfn, length, length > 1 ? arguments[1] : undefined);
5152         });
5153
5154         var ArrayBufferViewCore$6 = arrayBufferViewCore;
5155
5156         var aTypedArray$6 = ArrayBufferViewCore$6.aTypedArray;
5157         var exportTypedArrayMethod$7 = ArrayBufferViewCore$6.exportTypedArrayMethod;
5158         var floor$5 = Math.floor;
5159
5160         // `%TypedArray%.prototype.reverse` method
5161         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.reverse
5162         exportTypedArrayMethod$7('reverse', function reverse() {
5163           var that = this;
5164           var length = aTypedArray$6(that).length;
5165           var middle = floor$5(length / 2);
5166           var index = 0;
5167           var value;
5168           while (index < middle) {
5169             value = that[index];
5170             that[index++] = that[--length];
5171             that[length] = value;
5172           } return that;
5173         });
5174
5175         var global$s = global$1o;
5176         var call$a = functionCall;
5177         var ArrayBufferViewCore$5 = arrayBufferViewCore;
5178         var lengthOfArrayLike$7 = lengthOfArrayLike$i;
5179         var toOffset = toOffset$2;
5180         var toIndexedObject$4 = toObject$i;
5181         var fails$y = fails$V;
5182
5183         var RangeError$6 = global$s.RangeError;
5184         var Int8Array$2 = global$s.Int8Array;
5185         var Int8ArrayPrototype = Int8Array$2 && Int8Array$2.prototype;
5186         var $set = Int8ArrayPrototype && Int8ArrayPrototype.set;
5187         var aTypedArray$5 = ArrayBufferViewCore$5.aTypedArray;
5188         var exportTypedArrayMethod$6 = ArrayBufferViewCore$5.exportTypedArrayMethod;
5189
5190         var WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS = !fails$y(function () {
5191           // eslint-disable-next-line es/no-typed-arrays -- required for testing
5192           var array = new Uint8ClampedArray(2);
5193           call$a($set, array, { length: 1, 0: 3 }, 1);
5194           return array[1] !== 3;
5195         });
5196
5197         // https://bugs.chromium.org/p/v8/issues/detail?id=11294 and other
5198         var TO_OBJECT_BUG = WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS && ArrayBufferViewCore$5.NATIVE_ARRAY_BUFFER_VIEWS && fails$y(function () {
5199           var array = new Int8Array$2(2);
5200           array.set(1);
5201           array.set('2', 1);
5202           return array[0] !== 0 || array[1] !== 2;
5203         });
5204
5205         // `%TypedArray%.prototype.set` method
5206         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.set
5207         exportTypedArrayMethod$6('set', function set(arrayLike /* , offset */) {
5208           aTypedArray$5(this);
5209           var offset = toOffset(arguments.length > 1 ? arguments[1] : undefined, 1);
5210           var src = toIndexedObject$4(arrayLike);
5211           if (WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS) return call$a($set, this, src, offset);
5212           var length = this.length;
5213           var len = lengthOfArrayLike$7(src);
5214           var index = 0;
5215           if (len + offset > length) throw RangeError$6('Wrong length');
5216           while (index < len) this[offset + index] = src[index++];
5217         }, !WORKS_WITH_OBJECTS_AND_GEERIC_ON_TYPED_ARRAYS || TO_OBJECT_BUG);
5218
5219         var ArrayBufferViewCore$4 = arrayBufferViewCore;
5220         var typedArraySpeciesConstructor$1 = typedArraySpeciesConstructor$4;
5221         var fails$x = fails$V;
5222         var arraySlice$7 = arraySlice$b;
5223
5224         var aTypedArray$4 = ArrayBufferViewCore$4.aTypedArray;
5225         var exportTypedArrayMethod$5 = ArrayBufferViewCore$4.exportTypedArrayMethod;
5226
5227         var FORCED$e = fails$x(function () {
5228           // eslint-disable-next-line es/no-typed-arrays -- required for testing
5229           new Int8Array(1).slice();
5230         });
5231
5232         // `%TypedArray%.prototype.slice` method
5233         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.slice
5234         exportTypedArrayMethod$5('slice', function slice(start, end) {
5235           var list = arraySlice$7(aTypedArray$4(this), start, end);
5236           var C = typedArraySpeciesConstructor$1(this);
5237           var index = 0;
5238           var length = list.length;
5239           var result = new C(length);
5240           while (length > index) result[index] = list[index++];
5241           return result;
5242         }, FORCED$e);
5243
5244         var ArrayBufferViewCore$3 = arrayBufferViewCore;
5245         var $some$1 = arrayIteration.some;
5246
5247         var aTypedArray$3 = ArrayBufferViewCore$3.aTypedArray;
5248         var exportTypedArrayMethod$4 = ArrayBufferViewCore$3.exportTypedArrayMethod;
5249
5250         // `%TypedArray%.prototype.some` method
5251         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.some
5252         exportTypedArrayMethod$4('some', function some(callbackfn /* , thisArg */) {
5253           return $some$1(aTypedArray$3(this), callbackfn, arguments.length > 1 ? arguments[1] : undefined);
5254         });
5255
5256         var arraySlice$6 = arraySliceSimple;
5257
5258         var floor$4 = Math.floor;
5259
5260         var mergeSort = function (array, comparefn) {
5261           var length = array.length;
5262           var middle = floor$4(length / 2);
5263           return length < 8 ? insertionSort(array, comparefn) : merge$5(
5264             array,
5265             mergeSort(arraySlice$6(array, 0, middle), comparefn),
5266             mergeSort(arraySlice$6(array, middle), comparefn),
5267             comparefn
5268           );
5269         };
5270
5271         var insertionSort = function (array, comparefn) {
5272           var length = array.length;
5273           var i = 1;
5274           var element, j;
5275
5276           while (i < length) {
5277             j = i;
5278             element = array[i];
5279             while (j && comparefn(array[j - 1], element) > 0) {
5280               array[j] = array[--j];
5281             }
5282             if (j !== i++) array[j] = element;
5283           } return array;
5284         };
5285
5286         var merge$5 = function (array, left, right, comparefn) {
5287           var llength = left.length;
5288           var rlength = right.length;
5289           var lindex = 0;
5290           var rindex = 0;
5291
5292           while (lindex < llength || rindex < rlength) {
5293             array[lindex + rindex] = (lindex < llength && rindex < rlength)
5294               ? comparefn(left[lindex], right[rindex]) <= 0 ? left[lindex++] : right[rindex++]
5295               : lindex < llength ? left[lindex++] : right[rindex++];
5296           } return array;
5297         };
5298
5299         var arraySort$1 = mergeSort;
5300
5301         var userAgent$3 = engineUserAgent;
5302
5303         var firefox = userAgent$3.match(/firefox\/(\d+)/i);
5304
5305         var engineFfVersion = !!firefox && +firefox[1];
5306
5307         var UA = engineUserAgent;
5308
5309         var engineIsIeOrEdge = /MSIE|Trident/.test(UA);
5310
5311         var userAgent$2 = engineUserAgent;
5312
5313         var webkit = userAgent$2.match(/AppleWebKit\/(\d+)\./);
5314
5315         var engineWebkitVersion = !!webkit && +webkit[1];
5316
5317         var global$r = global$1o;
5318         var uncurryThis$x = functionUncurryThis;
5319         var fails$w = fails$V;
5320         var aCallable$3 = aCallable$a;
5321         var internalSort$1 = arraySort$1;
5322         var ArrayBufferViewCore$2 = arrayBufferViewCore;
5323         var FF$1 = engineFfVersion;
5324         var IE_OR_EDGE$1 = engineIsIeOrEdge;
5325         var V8$1 = engineV8Version;
5326         var WEBKIT$1 = engineWebkitVersion;
5327
5328         var Array$3 = global$r.Array;
5329         var aTypedArray$2 = ArrayBufferViewCore$2.aTypedArray;
5330         var exportTypedArrayMethod$3 = ArrayBufferViewCore$2.exportTypedArrayMethod;
5331         var Uint16Array = global$r.Uint16Array;
5332         var un$Sort$1 = Uint16Array && uncurryThis$x(Uint16Array.prototype.sort);
5333
5334         // WebKit
5335         var ACCEPT_INCORRECT_ARGUMENTS = !!un$Sort$1 && !(fails$w(function () {
5336           un$Sort$1(new Uint16Array(2), null);
5337         }) && fails$w(function () {
5338           un$Sort$1(new Uint16Array(2), {});
5339         }));
5340
5341         var STABLE_SORT$1 = !!un$Sort$1 && !fails$w(function () {
5342           // feature detection can be too slow, so check engines versions
5343           if (V8$1) return V8$1 < 74;
5344           if (FF$1) return FF$1 < 67;
5345           if (IE_OR_EDGE$1) return true;
5346           if (WEBKIT$1) return WEBKIT$1 < 602;
5347
5348           var array = new Uint16Array(516);
5349           var expected = Array$3(516);
5350           var index, mod;
5351
5352           for (index = 0; index < 516; index++) {
5353             mod = index % 4;
5354             array[index] = 515 - index;
5355             expected[index] = index - 2 * mod + 3;
5356           }
5357
5358           un$Sort$1(array, function (a, b) {
5359             return (a / 4 | 0) - (b / 4 | 0);
5360           });
5361
5362           for (index = 0; index < 516; index++) {
5363             if (array[index] !== expected[index]) return true;
5364           }
5365         });
5366
5367         var getSortCompare$1 = function (comparefn) {
5368           return function (x, y) {
5369             if (comparefn !== undefined) return +comparefn(x, y) || 0;
5370             // eslint-disable-next-line no-self-compare -- NaN check
5371             if (y !== y) return -1;
5372             // eslint-disable-next-line no-self-compare -- NaN check
5373             if (x !== x) return 1;
5374             if (x === 0 && y === 0) return 1 / x > 0 && 1 / y < 0 ? 1 : -1;
5375             return x > y;
5376           };
5377         };
5378
5379         // `%TypedArray%.prototype.sort` method
5380         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort
5381         exportTypedArrayMethod$3('sort', function sort(comparefn) {
5382           if (comparefn !== undefined) aCallable$3(comparefn);
5383           if (STABLE_SORT$1) return un$Sort$1(this, comparefn);
5384
5385           return internalSort$1(aTypedArray$2(this), getSortCompare$1(comparefn));
5386         }, !STABLE_SORT$1 || ACCEPT_INCORRECT_ARGUMENTS);
5387
5388         var ArrayBufferViewCore$1 = arrayBufferViewCore;
5389         var toLength$6 = toLength$c;
5390         var toAbsoluteIndex$3 = toAbsoluteIndex$9;
5391         var typedArraySpeciesConstructor = typedArraySpeciesConstructor$4;
5392
5393         var aTypedArray$1 = ArrayBufferViewCore$1.aTypedArray;
5394         var exportTypedArrayMethod$2 = ArrayBufferViewCore$1.exportTypedArrayMethod;
5395
5396         // `%TypedArray%.prototype.subarray` method
5397         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.subarray
5398         exportTypedArrayMethod$2('subarray', function subarray(begin, end) {
5399           var O = aTypedArray$1(this);
5400           var length = O.length;
5401           var beginIndex = toAbsoluteIndex$3(begin, length);
5402           var C = typedArraySpeciesConstructor(O);
5403           return new C(
5404             O.buffer,
5405             O.byteOffset + beginIndex * O.BYTES_PER_ELEMENT,
5406             toLength$6((end === undefined ? length : toAbsoluteIndex$3(end, length)) - beginIndex)
5407           );
5408         });
5409
5410         var global$q = global$1o;
5411         var apply$4 = functionApply;
5412         var ArrayBufferViewCore = arrayBufferViewCore;
5413         var fails$v = fails$V;
5414         var arraySlice$5 = arraySlice$b;
5415
5416         var Int8Array$1 = global$q.Int8Array;
5417         var aTypedArray = ArrayBufferViewCore.aTypedArray;
5418         var exportTypedArrayMethod$1 = ArrayBufferViewCore.exportTypedArrayMethod;
5419         var $toLocaleString = [].toLocaleString;
5420
5421         // iOS Safari 6.x fails here
5422         var TO_LOCALE_STRING_BUG = !!Int8Array$1 && fails$v(function () {
5423           $toLocaleString.call(new Int8Array$1(1));
5424         });
5425
5426         var FORCED$d = fails$v(function () {
5427           return [1, 2].toLocaleString() != new Int8Array$1([1, 2]).toLocaleString();
5428         }) || !fails$v(function () {
5429           Int8Array$1.prototype.toLocaleString.call([1, 2]);
5430         });
5431
5432         // `%TypedArray%.prototype.toLocaleString` method
5433         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.tolocalestring
5434         exportTypedArrayMethod$1('toLocaleString', function toLocaleString() {
5435           return apply$4(
5436             $toLocaleString,
5437             TO_LOCALE_STRING_BUG ? arraySlice$5(aTypedArray(this)) : aTypedArray(this),
5438             arraySlice$5(arguments)
5439           );
5440         }, FORCED$d);
5441
5442         var exportTypedArrayMethod = arrayBufferViewCore.exportTypedArrayMethod;
5443         var fails$u = fails$V;
5444         var global$p = global$1o;
5445         var uncurryThis$w = functionUncurryThis;
5446
5447         var Uint8Array$1 = global$p.Uint8Array;
5448         var Uint8ArrayPrototype = Uint8Array$1 && Uint8Array$1.prototype || {};
5449         var arrayToString = [].toString;
5450         var join$5 = uncurryThis$w([].join);
5451
5452         if (fails$u(function () { arrayToString.call({}); })) {
5453           arrayToString = function toString() {
5454             return join$5(this);
5455           };
5456         }
5457
5458         var IS_NOT_ARRAY_METHOD = Uint8ArrayPrototype.toString != arrayToString;
5459
5460         // `%TypedArray%.prototype.toString` method
5461         // https://tc39.es/ecma262/#sec-%typedarray%.prototype.tostring
5462         exportTypedArrayMethod('toString', arrayToString, IS_NOT_ARRAY_METHOD);
5463
5464         var $$Z = _export;
5465         var uncurryThis$v = functionUncurryThis;
5466         var IndexedObject$1 = indexedObject;
5467         var toIndexedObject$3 = toIndexedObject$d;
5468         var arrayMethodIsStrict$5 = arrayMethodIsStrict$9;
5469
5470         var un$Join = uncurryThis$v([].join);
5471
5472         var ES3_STRINGS = IndexedObject$1 != Object;
5473         var STRICT_METHOD$5 = arrayMethodIsStrict$5('join', ',');
5474
5475         // `Array.prototype.join` method
5476         // https://tc39.es/ecma262/#sec-array.prototype.join
5477         $$Z({ target: 'Array', proto: true, forced: ES3_STRINGS || !STRICT_METHOD$5 }, {
5478           join: function join(separator) {
5479             return un$Join(toIndexedObject$3(this), separator === undefined ? ',' : separator);
5480           }
5481         });
5482
5483         var $$Y = _export;
5484         var global$o = global$1o;
5485         var isArray$4 = isArray$8;
5486         var isConstructor$1 = isConstructor$4;
5487         var isObject$e = isObject$s;
5488         var toAbsoluteIndex$2 = toAbsoluteIndex$9;
5489         var lengthOfArrayLike$6 = lengthOfArrayLike$i;
5490         var toIndexedObject$2 = toIndexedObject$d;
5491         var createProperty$3 = createProperty$5;
5492         var wellKnownSymbol$8 = wellKnownSymbol$t;
5493         var arrayMethodHasSpeciesSupport$3 = arrayMethodHasSpeciesSupport$5;
5494         var un$Slice = arraySlice$b;
5495
5496         var HAS_SPECIES_SUPPORT$2 = arrayMethodHasSpeciesSupport$3('slice');
5497
5498         var SPECIES$1 = wellKnownSymbol$8('species');
5499         var Array$2 = global$o.Array;
5500         var max$3 = Math.max;
5501
5502         // `Array.prototype.slice` method
5503         // https://tc39.es/ecma262/#sec-array.prototype.slice
5504         // fallback for not array-like ES3 strings and DOM objects
5505         $$Y({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$2 }, {
5506           slice: function slice(start, end) {
5507             var O = toIndexedObject$2(this);
5508             var length = lengthOfArrayLike$6(O);
5509             var k = toAbsoluteIndex$2(start, length);
5510             var fin = toAbsoluteIndex$2(end === undefined ? length : end, length);
5511             // inline `ArraySpeciesCreate` for usage native `Array#slice` where it's possible
5512             var Constructor, result, n;
5513             if (isArray$4(O)) {
5514               Constructor = O.constructor;
5515               // cross-realm fallback
5516               if (isConstructor$1(Constructor) && (Constructor === Array$2 || isArray$4(Constructor.prototype))) {
5517                 Constructor = undefined;
5518               } else if (isObject$e(Constructor)) {
5519                 Constructor = Constructor[SPECIES$1];
5520                 if (Constructor === null) Constructor = undefined;
5521               }
5522               if (Constructor === Array$2 || Constructor === undefined) {
5523                 return un$Slice(O, k, fin);
5524               }
5525             }
5526             result = new (Constructor === undefined ? Array$2 : Constructor)(max$3(fin - k, 0));
5527             for (n = 0; k < fin; k++, n++) if (k in O) createProperty$3(result, n, O[k]);
5528             result.length = n;
5529             return result;
5530           }
5531         });
5532
5533         var fails$t = fails$V;
5534         var wellKnownSymbol$7 = wellKnownSymbol$t;
5535         var IS_PURE = isPure;
5536
5537         var ITERATOR$3 = wellKnownSymbol$7('iterator');
5538
5539         var nativeUrl = !fails$t(function () {
5540           // eslint-disable-next-line unicorn/relative-url-style -- required for testing
5541           var url = new URL('b?a=1&b=2&c=3', 'http://a');
5542           var searchParams = url.searchParams;
5543           var result = '';
5544           url.pathname = 'c%20d';
5545           searchParams.forEach(function (value, key) {
5546             searchParams['delete']('b');
5547             result += key + value;
5548           });
5549           return (IS_PURE && !url.toJSON)
5550             || !searchParams.sort
5551             || url.href !== 'http://a/c%20d?a=1&c=3'
5552             || searchParams.get('c') !== '3'
5553             || String(new URLSearchParams('?a=1')) !== 'a=1'
5554             || !searchParams[ITERATOR$3]
5555             // throws in Edge
5556             || new URL('https://a@b').username !== 'a'
5557             || new URLSearchParams(new URLSearchParams('a=b')).get('a') !== 'b'
5558             // not punycoded in Edge
5559             || new URL('http://тест').host !== 'xn--e1aybc'
5560             // not escaped in Chrome 62-
5561             || new URL('http://a#б').hash !== '#%D0%B1'
5562             // fails in Chrome 66-
5563             || result !== 'a1c3'
5564             // throws in Safari
5565             || new URL('http://x', undefined).host !== 'x';
5566         });
5567
5568         // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env`
5569
5570         var $$X = _export;
5571         var global$n = global$1o;
5572         var getBuiltIn$2 = getBuiltIn$b;
5573         var call$9 = functionCall;
5574         var uncurryThis$u = functionUncurryThis;
5575         var USE_NATIVE_URL$1 = nativeUrl;
5576         var redefine$7 = redefine$h.exports;
5577         var redefineAll$1 = redefineAll$4;
5578         var setToStringTag$4 = setToStringTag$a;
5579         var createIteratorConstructor = createIteratorConstructor$2;
5580         var InternalStateModule$2 = internalState;
5581         var anInstance$3 = anInstance$7;
5582         var isCallable$5 = isCallable$r;
5583         var hasOwn$6 = hasOwnProperty_1;
5584         var bind$8 = functionBindContext;
5585         var classof$3 = classof$d;
5586         var anObject$9 = anObject$n;
5587         var isObject$d = isObject$s;
5588         var $toString$2 = toString$k;
5589         var create$6 = objectCreate;
5590         var createPropertyDescriptor = createPropertyDescriptor$7;
5591         var getIterator$1 = getIterator$4;
5592         var getIteratorMethod$1 = getIteratorMethod$5;
5593         var validateArgumentsLength$2 = validateArgumentsLength$4;
5594         var wellKnownSymbol$6 = wellKnownSymbol$t;
5595         var arraySort = arraySort$1;
5596
5597         var ITERATOR$2 = wellKnownSymbol$6('iterator');
5598         var URL_SEARCH_PARAMS = 'URLSearchParams';
5599         var URL_SEARCH_PARAMS_ITERATOR = URL_SEARCH_PARAMS + 'Iterator';
5600         var setInternalState$2 = InternalStateModule$2.set;
5601         var getInternalParamsState = InternalStateModule$2.getterFor(URL_SEARCH_PARAMS);
5602         var getInternalIteratorState = InternalStateModule$2.getterFor(URL_SEARCH_PARAMS_ITERATOR);
5603
5604         var n$Fetch = getBuiltIn$2('fetch');
5605         var N$Request = getBuiltIn$2('Request');
5606         var Headers$1 = getBuiltIn$2('Headers');
5607         var RequestPrototype = N$Request && N$Request.prototype;
5608         var HeadersPrototype = Headers$1 && Headers$1.prototype;
5609         var RegExp$1 = global$n.RegExp;
5610         var TypeError$8 = global$n.TypeError;
5611         var decodeURIComponent$1 = global$n.decodeURIComponent;
5612         var encodeURIComponent$1 = global$n.encodeURIComponent;
5613         var charAt$5 = uncurryThis$u(''.charAt);
5614         var join$4 = uncurryThis$u([].join);
5615         var push$7 = uncurryThis$u([].push);
5616         var replace$6 = uncurryThis$u(''.replace);
5617         var shift$1 = uncurryThis$u([].shift);
5618         var splice = uncurryThis$u([].splice);
5619         var split$3 = uncurryThis$u(''.split);
5620         var stringSlice$8 = uncurryThis$u(''.slice);
5621
5622         var plus = /\+/g;
5623         var sequences = Array(4);
5624
5625         var percentSequence = function (bytes) {
5626           return sequences[bytes - 1] || (sequences[bytes - 1] = RegExp$1('((?:%[\\da-f]{2}){' + bytes + '})', 'gi'));
5627         };
5628
5629         var percentDecode = function (sequence) {
5630           try {
5631             return decodeURIComponent$1(sequence);
5632           } catch (error) {
5633             return sequence;
5634           }
5635         };
5636
5637         var deserialize = function (it) {
5638           var result = replace$6(it, plus, ' ');
5639           var bytes = 4;
5640           try {
5641             return decodeURIComponent$1(result);
5642           } catch (error) {
5643             while (bytes) {
5644               result = replace$6(result, percentSequence(bytes--), percentDecode);
5645             }
5646             return result;
5647           }
5648         };
5649
5650         var find$1 = /[!'()~]|%20/g;
5651
5652         var replacements = {
5653           '!': '%21',
5654           "'": '%27',
5655           '(': '%28',
5656           ')': '%29',
5657           '~': '%7E',
5658           '%20': '+'
5659         };
5660
5661         var replacer = function (match) {
5662           return replacements[match];
5663         };
5664
5665         var serialize = function (it) {
5666           return replace$6(encodeURIComponent$1(it), find$1, replacer);
5667         };
5668
5669         var URLSearchParamsIterator = createIteratorConstructor(function Iterator(params, kind) {
5670           setInternalState$2(this, {
5671             type: URL_SEARCH_PARAMS_ITERATOR,
5672             iterator: getIterator$1(getInternalParamsState(params).entries),
5673             kind: kind
5674           });
5675         }, 'Iterator', function next() {
5676           var state = getInternalIteratorState(this);
5677           var kind = state.kind;
5678           var step = state.iterator.next();
5679           var entry = step.value;
5680           if (!step.done) {
5681             step.value = kind === 'keys' ? entry.key : kind === 'values' ? entry.value : [entry.key, entry.value];
5682           } return step;
5683         }, true);
5684
5685         var URLSearchParamsState = function (init) {
5686           this.entries = [];
5687           this.url = null;
5688
5689           if (init !== undefined) {
5690             if (isObject$d(init)) this.parseObject(init);
5691             else this.parseQuery(typeof init == 'string' ? charAt$5(init, 0) === '?' ? stringSlice$8(init, 1) : init : $toString$2(init));
5692           }
5693         };
5694
5695         URLSearchParamsState.prototype = {
5696           type: URL_SEARCH_PARAMS,
5697           bindURL: function (url) {
5698             this.url = url;
5699             this.update();
5700           },
5701           parseObject: function (object) {
5702             var iteratorMethod = getIteratorMethod$1(object);
5703             var iterator, next, step, entryIterator, entryNext, first, second;
5704
5705             if (iteratorMethod) {
5706               iterator = getIterator$1(object, iteratorMethod);
5707               next = iterator.next;
5708               while (!(step = call$9(next, iterator)).done) {
5709                 entryIterator = getIterator$1(anObject$9(step.value));
5710                 entryNext = entryIterator.next;
5711                 if (
5712                   (first = call$9(entryNext, entryIterator)).done ||
5713                   (second = call$9(entryNext, entryIterator)).done ||
5714                   !call$9(entryNext, entryIterator).done
5715                 ) throw TypeError$8('Expected sequence with length 2');
5716                 push$7(this.entries, { key: $toString$2(first.value), value: $toString$2(second.value) });
5717               }
5718             } else for (var key in object) if (hasOwn$6(object, key)) {
5719               push$7(this.entries, { key: key, value: $toString$2(object[key]) });
5720             }
5721           },
5722           parseQuery: function (query) {
5723             if (query) {
5724               var attributes = split$3(query, '&');
5725               var index = 0;
5726               var attribute, entry;
5727               while (index < attributes.length) {
5728                 attribute = attributes[index++];
5729                 if (attribute.length) {
5730                   entry = split$3(attribute, '=');
5731                   push$7(this.entries, {
5732                     key: deserialize(shift$1(entry)),
5733                     value: deserialize(join$4(entry, '='))
5734                   });
5735                 }
5736               }
5737             }
5738           },
5739           serialize: function () {
5740             var entries = this.entries;
5741             var result = [];
5742             var index = 0;
5743             var entry;
5744             while (index < entries.length) {
5745               entry = entries[index++];
5746               push$7(result, serialize(entry.key) + '=' + serialize(entry.value));
5747             } return join$4(result, '&');
5748           },
5749           update: function () {
5750             this.entries.length = 0;
5751             this.parseQuery(this.url.query);
5752           },
5753           updateURL: function () {
5754             if (this.url) this.url.update();
5755           }
5756         };
5757
5758         // `URLSearchParams` constructor
5759         // https://url.spec.whatwg.org/#interface-urlsearchparams
5760         var URLSearchParamsConstructor = function URLSearchParams(/* init */) {
5761           anInstance$3(this, URLSearchParamsPrototype);
5762           var init = arguments.length > 0 ? arguments[0] : undefined;
5763           setInternalState$2(this, new URLSearchParamsState(init));
5764         };
5765
5766         var URLSearchParamsPrototype = URLSearchParamsConstructor.prototype;
5767
5768         redefineAll$1(URLSearchParamsPrototype, {
5769           // `URLSearchParams.prototype.append` method
5770           // https://url.spec.whatwg.org/#dom-urlsearchparams-append
5771           append: function append(name, value) {
5772             validateArgumentsLength$2(arguments.length, 2);
5773             var state = getInternalParamsState(this);
5774             push$7(state.entries, { key: $toString$2(name), value: $toString$2(value) });
5775             state.updateURL();
5776           },
5777           // `URLSearchParams.prototype.delete` method
5778           // https://url.spec.whatwg.org/#dom-urlsearchparams-delete
5779           'delete': function (name) {
5780             validateArgumentsLength$2(arguments.length, 1);
5781             var state = getInternalParamsState(this);
5782             var entries = state.entries;
5783             var key = $toString$2(name);
5784             var index = 0;
5785             while (index < entries.length) {
5786               if (entries[index].key === key) splice(entries, index, 1);
5787               else index++;
5788             }
5789             state.updateURL();
5790           },
5791           // `URLSearchParams.prototype.get` method
5792           // https://url.spec.whatwg.org/#dom-urlsearchparams-get
5793           get: function get(name) {
5794             validateArgumentsLength$2(arguments.length, 1);
5795             var entries = getInternalParamsState(this).entries;
5796             var key = $toString$2(name);
5797             var index = 0;
5798             for (; index < entries.length; index++) {
5799               if (entries[index].key === key) return entries[index].value;
5800             }
5801             return null;
5802           },
5803           // `URLSearchParams.prototype.getAll` method
5804           // https://url.spec.whatwg.org/#dom-urlsearchparams-getall
5805           getAll: function getAll(name) {
5806             validateArgumentsLength$2(arguments.length, 1);
5807             var entries = getInternalParamsState(this).entries;
5808             var key = $toString$2(name);
5809             var result = [];
5810             var index = 0;
5811             for (; index < entries.length; index++) {
5812               if (entries[index].key === key) push$7(result, entries[index].value);
5813             }
5814             return result;
5815           },
5816           // `URLSearchParams.prototype.has` method
5817           // https://url.spec.whatwg.org/#dom-urlsearchparams-has
5818           has: function has(name) {
5819             validateArgumentsLength$2(arguments.length, 1);
5820             var entries = getInternalParamsState(this).entries;
5821             var key = $toString$2(name);
5822             var index = 0;
5823             while (index < entries.length) {
5824               if (entries[index++].key === key) return true;
5825             }
5826             return false;
5827           },
5828           // `URLSearchParams.prototype.set` method
5829           // https://url.spec.whatwg.org/#dom-urlsearchparams-set
5830           set: function set(name, value) {
5831             validateArgumentsLength$2(arguments.length, 1);
5832             var state = getInternalParamsState(this);
5833             var entries = state.entries;
5834             var found = false;
5835             var key = $toString$2(name);
5836             var val = $toString$2(value);
5837             var index = 0;
5838             var entry;
5839             for (; index < entries.length; index++) {
5840               entry = entries[index];
5841               if (entry.key === key) {
5842                 if (found) splice(entries, index--, 1);
5843                 else {
5844                   found = true;
5845                   entry.value = val;
5846                 }
5847               }
5848             }
5849             if (!found) push$7(entries, { key: key, value: val });
5850             state.updateURL();
5851           },
5852           // `URLSearchParams.prototype.sort` method
5853           // https://url.spec.whatwg.org/#dom-urlsearchparams-sort
5854           sort: function sort() {
5855             var state = getInternalParamsState(this);
5856             arraySort(state.entries, function (a, b) {
5857               return a.key > b.key ? 1 : -1;
5858             });
5859             state.updateURL();
5860           },
5861           // `URLSearchParams.prototype.forEach` method
5862           forEach: function forEach(callback /* , thisArg */) {
5863             var entries = getInternalParamsState(this).entries;
5864             var boundFunction = bind$8(callback, arguments.length > 1 ? arguments[1] : undefined);
5865             var index = 0;
5866             var entry;
5867             while (index < entries.length) {
5868               entry = entries[index++];
5869               boundFunction(entry.value, entry.key, this);
5870             }
5871           },
5872           // `URLSearchParams.prototype.keys` method
5873           keys: function keys() {
5874             return new URLSearchParamsIterator(this, 'keys');
5875           },
5876           // `URLSearchParams.prototype.values` method
5877           values: function values() {
5878             return new URLSearchParamsIterator(this, 'values');
5879           },
5880           // `URLSearchParams.prototype.entries` method
5881           entries: function entries() {
5882             return new URLSearchParamsIterator(this, 'entries');
5883           }
5884         }, { enumerable: true });
5885
5886         // `URLSearchParams.prototype[@@iterator]` method
5887         redefine$7(URLSearchParamsPrototype, ITERATOR$2, URLSearchParamsPrototype.entries, { name: 'entries' });
5888
5889         // `URLSearchParams.prototype.toString` method
5890         // https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior
5891         redefine$7(URLSearchParamsPrototype, 'toString', function toString() {
5892           return getInternalParamsState(this).serialize();
5893         }, { enumerable: true });
5894
5895         setToStringTag$4(URLSearchParamsConstructor, URL_SEARCH_PARAMS);
5896
5897         $$X({ global: true, forced: !USE_NATIVE_URL$1 }, {
5898           URLSearchParams: URLSearchParamsConstructor
5899         });
5900
5901         // Wrap `fetch` and `Request` for correct work with polyfilled `URLSearchParams`
5902         if (!USE_NATIVE_URL$1 && isCallable$5(Headers$1)) {
5903           var headersHas = uncurryThis$u(HeadersPrototype.has);
5904           var headersSet = uncurryThis$u(HeadersPrototype.set);
5905
5906           var wrapRequestOptions = function (init) {
5907             if (isObject$d(init)) {
5908               var body = init.body;
5909               var headers;
5910               if (classof$3(body) === URL_SEARCH_PARAMS) {
5911                 headers = init.headers ? new Headers$1(init.headers) : new Headers$1();
5912                 if (!headersHas(headers, 'content-type')) {
5913                   headersSet(headers, 'content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
5914                 }
5915                 return create$6(init, {
5916                   body: createPropertyDescriptor(0, $toString$2(body)),
5917                   headers: createPropertyDescriptor(0, headers)
5918                 });
5919               }
5920             } return init;
5921           };
5922
5923           if (isCallable$5(n$Fetch)) {
5924             $$X({ global: true, enumerable: true, forced: true }, {
5925               fetch: function fetch(input /* , init */) {
5926                 return n$Fetch(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});
5927               }
5928             });
5929           }
5930
5931           if (isCallable$5(N$Request)) {
5932             var RequestConstructor = function Request(input /* , init */) {
5933               anInstance$3(this, RequestPrototype);
5934               return new N$Request(input, arguments.length > 1 ? wrapRequestOptions(arguments[1]) : {});
5935             };
5936
5937             RequestPrototype.constructor = RequestConstructor;
5938             RequestConstructor.prototype = RequestPrototype;
5939
5940             $$X({ global: true, forced: true }, {
5941               Request: RequestConstructor
5942             });
5943           }
5944         }
5945
5946         var web_urlSearchParams = {
5947           URLSearchParams: URLSearchParamsConstructor,
5948           getState: getInternalParamsState
5949         };
5950
5951         var uncurryThis$t = functionUncurryThis;
5952         var PROPER_FUNCTION_NAME$1 = functionName.PROPER;
5953         var redefine$6 = redefine$h.exports;
5954         var anObject$8 = anObject$n;
5955         var isPrototypeOf$2 = objectIsPrototypeOf;
5956         var $toString$1 = toString$k;
5957         var fails$s = fails$V;
5958         var regExpFlags$2 = regexpFlags$1;
5959
5960         var TO_STRING = 'toString';
5961         var RegExpPrototype$3 = RegExp.prototype;
5962         var n$ToString = RegExpPrototype$3[TO_STRING];
5963         var getFlags$1 = uncurryThis$t(regExpFlags$2);
5964
5965         var NOT_GENERIC = fails$s(function () { return n$ToString.call({ source: 'a', flags: 'b' }) != '/a/b'; });
5966         // FF44- RegExp#toString has a wrong name
5967         var INCORRECT_NAME = PROPER_FUNCTION_NAME$1 && n$ToString.name != TO_STRING;
5968
5969         // `RegExp.prototype.toString` method
5970         // https://tc39.es/ecma262/#sec-regexp.prototype.tostring
5971         if (NOT_GENERIC || INCORRECT_NAME) {
5972           redefine$6(RegExp.prototype, TO_STRING, function toString() {
5973             var R = anObject$8(this);
5974             var p = $toString$1(R.source);
5975             var rf = R.flags;
5976             var f = $toString$1(rf === undefined && isPrototypeOf$2(RegExpPrototype$3, R) && !('flags' in RegExpPrototype$3) ? getFlags$1(R) : rf);
5977             return '/' + p + '/' + f;
5978           }, { unsafe: true });
5979         }
5980
5981         // TODO: Remove from `core-js@4` since it's moved to entry points
5982
5983         var uncurryThis$s = functionUncurryThis;
5984         var redefine$5 = redefine$h.exports;
5985         var regexpExec$2 = regexpExec$3;
5986         var fails$r = fails$V;
5987         var wellKnownSymbol$5 = wellKnownSymbol$t;
5988         var createNonEnumerableProperty$1 = createNonEnumerableProperty$b;
5989
5990         var SPECIES = wellKnownSymbol$5('species');
5991         var RegExpPrototype$2 = RegExp.prototype;
5992
5993         var fixRegexpWellKnownSymbolLogic = function (KEY, exec, FORCED, SHAM) {
5994           var SYMBOL = wellKnownSymbol$5(KEY);
5995
5996           var DELEGATES_TO_SYMBOL = !fails$r(function () {
5997             // String methods call symbol-named RegEp methods
5998             var O = {};
5999             O[SYMBOL] = function () { return 7; };
6000             return ''[KEY](O) != 7;
6001           });
6002
6003           var DELEGATES_TO_EXEC = DELEGATES_TO_SYMBOL && !fails$r(function () {
6004             // Symbol-named RegExp methods call .exec
6005             var execCalled = false;
6006             var re = /a/;
6007
6008             if (KEY === 'split') {
6009               // We can't use real regex here since it causes deoptimization
6010               // and serious performance degradation in V8
6011               // https://github.com/zloirock/core-js/issues/306
6012               re = {};
6013               // RegExp[@@split] doesn't call the regex's exec method, but first creates
6014               // a new one. We need to return the patched regex when creating the new one.
6015               re.constructor = {};
6016               re.constructor[SPECIES] = function () { return re; };
6017               re.flags = '';
6018               re[SYMBOL] = /./[SYMBOL];
6019             }
6020
6021             re.exec = function () { execCalled = true; return null; };
6022
6023             re[SYMBOL]('');
6024             return !execCalled;
6025           });
6026
6027           if (
6028             !DELEGATES_TO_SYMBOL ||
6029             !DELEGATES_TO_EXEC ||
6030             FORCED
6031           ) {
6032             var uncurriedNativeRegExpMethod = uncurryThis$s(/./[SYMBOL]);
6033             var methods = exec(SYMBOL, ''[KEY], function (nativeMethod, regexp, str, arg2, forceStringMethod) {
6034               var uncurriedNativeMethod = uncurryThis$s(nativeMethod);
6035               var $exec = regexp.exec;
6036               if ($exec === regexpExec$2 || $exec === RegExpPrototype$2.exec) {
6037                 if (DELEGATES_TO_SYMBOL && !forceStringMethod) {
6038                   // The native String method already delegates to @@method (this
6039                   // polyfilled function), leasing to infinite recursion.
6040                   // We avoid it by directly calling the native @@method method.
6041                   return { done: true, value: uncurriedNativeRegExpMethod(regexp, str, arg2) };
6042                 }
6043                 return { done: true, value: uncurriedNativeMethod(str, regexp, arg2) };
6044               }
6045               return { done: false };
6046             });
6047
6048             redefine$5(String.prototype, KEY, methods[0]);
6049             redefine$5(RegExpPrototype$2, SYMBOL, methods[1]);
6050           }
6051
6052           if (SHAM) createNonEnumerableProperty$1(RegExpPrototype$2[SYMBOL], 'sham', true);
6053         };
6054
6055         var charAt$4 = stringMultibyte.charAt;
6056
6057         // `AdvanceStringIndex` abstract operation
6058         // https://tc39.es/ecma262/#sec-advancestringindex
6059         var advanceStringIndex$3 = function (S, index, unicode) {
6060           return index + (unicode ? charAt$4(S, index).length : 1);
6061         };
6062
6063         var uncurryThis$r = functionUncurryThis;
6064         var toObject$9 = toObject$i;
6065
6066         var floor$3 = Math.floor;
6067         var charAt$3 = uncurryThis$r(''.charAt);
6068         var replace$5 = uncurryThis$r(''.replace);
6069         var stringSlice$7 = uncurryThis$r(''.slice);
6070         var SUBSTITUTION_SYMBOLS = /\$([$&'`]|\d{1,2}|<[^>]*>)/g;
6071         var SUBSTITUTION_SYMBOLS_NO_NAMED = /\$([$&'`]|\d{1,2})/g;
6072
6073         // `GetSubstitution` abstract operation
6074         // https://tc39.es/ecma262/#sec-getsubstitution
6075         var getSubstitution$1 = function (matched, str, position, captures, namedCaptures, replacement) {
6076           var tailPos = position + matched.length;
6077           var m = captures.length;
6078           var symbols = SUBSTITUTION_SYMBOLS_NO_NAMED;
6079           if (namedCaptures !== undefined) {
6080             namedCaptures = toObject$9(namedCaptures);
6081             symbols = SUBSTITUTION_SYMBOLS;
6082           }
6083           return replace$5(replacement, symbols, function (match, ch) {
6084             var capture;
6085             switch (charAt$3(ch, 0)) {
6086               case '$': return '$';
6087               case '&': return matched;
6088               case '`': return stringSlice$7(str, 0, position);
6089               case "'": return stringSlice$7(str, tailPos);
6090               case '<':
6091                 capture = namedCaptures[stringSlice$7(ch, 1, -1)];
6092                 break;
6093               default: // \d\d?
6094                 var n = +ch;
6095                 if (n === 0) return match;
6096                 if (n > m) {
6097                   var f = floor$3(n / 10);
6098                   if (f === 0) return match;
6099                   if (f <= m) return captures[f - 1] === undefined ? charAt$3(ch, 1) : captures[f - 1] + charAt$3(ch, 1);
6100                   return match;
6101                 }
6102                 capture = captures[n - 1];
6103             }
6104             return capture === undefined ? '' : capture;
6105           });
6106         };
6107
6108         var global$m = global$1o;
6109         var call$8 = functionCall;
6110         var anObject$7 = anObject$n;
6111         var isCallable$4 = isCallable$r;
6112         var classof$2 = classofRaw$1;
6113         var regexpExec$1 = regexpExec$3;
6114
6115         var TypeError$7 = global$m.TypeError;
6116
6117         // `RegExpExec` abstract operation
6118         // https://tc39.es/ecma262/#sec-regexpexec
6119         var regexpExecAbstract = function (R, S) {
6120           var exec = R.exec;
6121           if (isCallable$4(exec)) {
6122             var result = call$8(exec, R, S);
6123             if (result !== null) anObject$7(result);
6124             return result;
6125           }
6126           if (classof$2(R) === 'RegExp') return call$8(regexpExec$1, R, S);
6127           throw TypeError$7('RegExp#exec called on incompatible receiver');
6128         };
6129
6130         var apply$3 = functionApply;
6131         var call$7 = functionCall;
6132         var uncurryThis$q = functionUncurryThis;
6133         var fixRegExpWellKnownSymbolLogic$3 = fixRegexpWellKnownSymbolLogic;
6134         var fails$q = fails$V;
6135         var anObject$6 = anObject$n;
6136         var isCallable$3 = isCallable$r;
6137         var toIntegerOrInfinity$3 = toIntegerOrInfinity$b;
6138         var toLength$5 = toLength$c;
6139         var toString$f = toString$k;
6140         var requireObjectCoercible$a = requireObjectCoercible$e;
6141         var advanceStringIndex$2 = advanceStringIndex$3;
6142         var getMethod$3 = getMethod$7;
6143         var getSubstitution = getSubstitution$1;
6144         var regExpExec$3 = regexpExecAbstract;
6145         var wellKnownSymbol$4 = wellKnownSymbol$t;
6146
6147         var REPLACE = wellKnownSymbol$4('replace');
6148         var max$2 = Math.max;
6149         var min$5 = Math.min;
6150         var concat$2 = uncurryThis$q([].concat);
6151         var push$6 = uncurryThis$q([].push);
6152         var stringIndexOf$2 = uncurryThis$q(''.indexOf);
6153         var stringSlice$6 = uncurryThis$q(''.slice);
6154
6155         var maybeToString = function (it) {
6156           return it === undefined ? it : String(it);
6157         };
6158
6159         // IE <= 11 replaces $0 with the whole match, as if it was $&
6160         // https://stackoverflow.com/questions/6024666/getting-ie-to-replace-a-regex-with-the-literal-string-0
6161         var REPLACE_KEEPS_$0 = (function () {
6162           // eslint-disable-next-line regexp/prefer-escape-replacement-dollar-char -- required for testing
6163           return 'a'.replace(/./, '$0') === '$0';
6164         })();
6165
6166         // Safari <= 13.0.3(?) substitutes nth capture where n>m with an empty string
6167         var REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE = (function () {
6168           if (/./[REPLACE]) {
6169             return /./[REPLACE]('a', '$0') === '';
6170           }
6171           return false;
6172         })();
6173
6174         var REPLACE_SUPPORTS_NAMED_GROUPS = !fails$q(function () {
6175           var re = /./;
6176           re.exec = function () {
6177             var result = [];
6178             result.groups = { a: '7' };
6179             return result;
6180           };
6181           // eslint-disable-next-line regexp/no-useless-dollar-replacements -- false positive
6182           return ''.replace(re, '$<a>') !== '7';
6183         });
6184
6185         // @@replace logic
6186         fixRegExpWellKnownSymbolLogic$3('replace', function (_, nativeReplace, maybeCallNative) {
6187           var UNSAFE_SUBSTITUTE = REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE ? '$' : '$0';
6188
6189           return [
6190             // `String.prototype.replace` method
6191             // https://tc39.es/ecma262/#sec-string.prototype.replace
6192             function replace(searchValue, replaceValue) {
6193               var O = requireObjectCoercible$a(this);
6194               var replacer = searchValue == undefined ? undefined : getMethod$3(searchValue, REPLACE);
6195               return replacer
6196                 ? call$7(replacer, searchValue, O, replaceValue)
6197                 : call$7(nativeReplace, toString$f(O), searchValue, replaceValue);
6198             },
6199             // `RegExp.prototype[@@replace]` method
6200             // https://tc39.es/ecma262/#sec-regexp.prototype-@@replace
6201             function (string, replaceValue) {
6202               var rx = anObject$6(this);
6203               var S = toString$f(string);
6204
6205               if (
6206                 typeof replaceValue == 'string' &&
6207                 stringIndexOf$2(replaceValue, UNSAFE_SUBSTITUTE) === -1 &&
6208                 stringIndexOf$2(replaceValue, '$<') === -1
6209               ) {
6210                 var res = maybeCallNative(nativeReplace, rx, S, replaceValue);
6211                 if (res.done) return res.value;
6212               }
6213
6214               var functionalReplace = isCallable$3(replaceValue);
6215               if (!functionalReplace) replaceValue = toString$f(replaceValue);
6216
6217               var global = rx.global;
6218               if (global) {
6219                 var fullUnicode = rx.unicode;
6220                 rx.lastIndex = 0;
6221               }
6222               var results = [];
6223               while (true) {
6224                 var result = regExpExec$3(rx, S);
6225                 if (result === null) break;
6226
6227                 push$6(results, result);
6228                 if (!global) break;
6229
6230                 var matchStr = toString$f(result[0]);
6231                 if (matchStr === '') rx.lastIndex = advanceStringIndex$2(S, toLength$5(rx.lastIndex), fullUnicode);
6232               }
6233
6234               var accumulatedResult = '';
6235               var nextSourcePosition = 0;
6236               for (var i = 0; i < results.length; i++) {
6237                 result = results[i];
6238
6239                 var matched = toString$f(result[0]);
6240                 var position = max$2(min$5(toIntegerOrInfinity$3(result.index), S.length), 0);
6241                 var captures = [];
6242                 // NOTE: This is equivalent to
6243                 //   captures = result.slice(1).map(maybeToString)
6244                 // but for some reason `nativeSlice.call(result, 1, result.length)` (called in
6245                 // the slice polyfill when slicing native arrays) "doesn't work" in safari 9 and
6246                 // causes a crash (https://pastebin.com/N21QzeQA) when trying to debug it.
6247                 for (var j = 1; j < result.length; j++) push$6(captures, maybeToString(result[j]));
6248                 var namedCaptures = result.groups;
6249                 if (functionalReplace) {
6250                   var replacerArgs = concat$2([matched], captures, position, S);
6251                   if (namedCaptures !== undefined) push$6(replacerArgs, namedCaptures);
6252                   var replacement = toString$f(apply$3(replaceValue, undefined, replacerArgs));
6253                 } else {
6254                   replacement = getSubstitution(matched, S, position, captures, namedCaptures, replaceValue);
6255                 }
6256                 if (position >= nextSourcePosition) {
6257                   accumulatedResult += stringSlice$6(S, nextSourcePosition, position) + replacement;
6258                   nextSourcePosition = position + matched.length;
6259                 }
6260               }
6261               return accumulatedResult + stringSlice$6(S, nextSourcePosition);
6262             }
6263           ];
6264         }, !REPLACE_SUPPORTS_NAMED_GROUPS || !REPLACE_KEEPS_$0 || REGEXP_REPLACE_SUBSTITUTES_UNDEFINED_CAPTURE);
6265
6266         var isObject$c = isObject$s;
6267         var classof$1 = classofRaw$1;
6268         var wellKnownSymbol$3 = wellKnownSymbol$t;
6269
6270         var MATCH$2 = wellKnownSymbol$3('match');
6271
6272         // `IsRegExp` abstract operation
6273         // https://tc39.es/ecma262/#sec-isregexp
6274         var isRegexp = function (it) {
6275           var isRegExp;
6276           return isObject$c(it) && ((isRegExp = it[MATCH$2]) !== undefined ? !!isRegExp : classof$1(it) == 'RegExp');
6277         };
6278
6279         var apply$2 = functionApply;
6280         var call$6 = functionCall;
6281         var uncurryThis$p = functionUncurryThis;
6282         var fixRegExpWellKnownSymbolLogic$2 = fixRegexpWellKnownSymbolLogic;
6283         var isRegExp$2 = isRegexp;
6284         var anObject$5 = anObject$n;
6285         var requireObjectCoercible$9 = requireObjectCoercible$e;
6286         var speciesConstructor$1 = speciesConstructor$5;
6287         var advanceStringIndex$1 = advanceStringIndex$3;
6288         var toLength$4 = toLength$c;
6289         var toString$e = toString$k;
6290         var getMethod$2 = getMethod$7;
6291         var arraySlice$4 = arraySliceSimple;
6292         var callRegExpExec = regexpExecAbstract;
6293         var regexpExec = regexpExec$3;
6294         var stickyHelpers$1 = regexpStickyHelpers;
6295         var fails$p = fails$V;
6296
6297         var UNSUPPORTED_Y$1 = stickyHelpers$1.UNSUPPORTED_Y;
6298         var MAX_UINT32 = 0xFFFFFFFF;
6299         var min$4 = Math.min;
6300         var $push = [].push;
6301         var exec$4 = uncurryThis$p(/./.exec);
6302         var push$5 = uncurryThis$p($push);
6303         var stringSlice$5 = uncurryThis$p(''.slice);
6304
6305         // Chrome 51 has a buggy "split" implementation when RegExp#exec !== nativeExec
6306         // Weex JS has frozen built-in prototypes, so use try / catch wrapper
6307         var SPLIT_WORKS_WITH_OVERWRITTEN_EXEC = !fails$p(function () {
6308           // eslint-disable-next-line regexp/no-empty-group -- required for testing
6309           var re = /(?:)/;
6310           var originalExec = re.exec;
6311           re.exec = function () { return originalExec.apply(this, arguments); };
6312           var result = 'ab'.split(re);
6313           return result.length !== 2 || result[0] !== 'a' || result[1] !== 'b';
6314         });
6315
6316         // @@split logic
6317         fixRegExpWellKnownSymbolLogic$2('split', function (SPLIT, nativeSplit, maybeCallNative) {
6318           var internalSplit;
6319           if (
6320             'abbc'.split(/(b)*/)[1] == 'c' ||
6321             // eslint-disable-next-line regexp/no-empty-group -- required for testing
6322             'test'.split(/(?:)/, -1).length != 4 ||
6323             'ab'.split(/(?:ab)*/).length != 2 ||
6324             '.'.split(/(.?)(.?)/).length != 4 ||
6325             // eslint-disable-next-line regexp/no-empty-capturing-group, regexp/no-empty-group -- required for testing
6326             '.'.split(/()()/).length > 1 ||
6327             ''.split(/.?/).length
6328           ) {
6329             // based on es5-shim implementation, need to rework it
6330             internalSplit = function (separator, limit) {
6331               var string = toString$e(requireObjectCoercible$9(this));
6332               var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
6333               if (lim === 0) return [];
6334               if (separator === undefined) return [string];
6335               // If `separator` is not a regex, use native split
6336               if (!isRegExp$2(separator)) {
6337                 return call$6(nativeSplit, string, separator, lim);
6338               }
6339               var output = [];
6340               var flags = (separator.ignoreCase ? 'i' : '') +
6341                           (separator.multiline ? 'm' : '') +
6342                           (separator.unicode ? 'u' : '') +
6343                           (separator.sticky ? 'y' : '');
6344               var lastLastIndex = 0;
6345               // Make `global` and avoid `lastIndex` issues by working with a copy
6346               var separatorCopy = new RegExp(separator.source, flags + 'g');
6347               var match, lastIndex, lastLength;
6348               while (match = call$6(regexpExec, separatorCopy, string)) {
6349                 lastIndex = separatorCopy.lastIndex;
6350                 if (lastIndex > lastLastIndex) {
6351                   push$5(output, stringSlice$5(string, lastLastIndex, match.index));
6352                   if (match.length > 1 && match.index < string.length) apply$2($push, output, arraySlice$4(match, 1));
6353                   lastLength = match[0].length;
6354                   lastLastIndex = lastIndex;
6355                   if (output.length >= lim) break;
6356                 }
6357                 if (separatorCopy.lastIndex === match.index) separatorCopy.lastIndex++; // Avoid an infinite loop
6358               }
6359               if (lastLastIndex === string.length) {
6360                 if (lastLength || !exec$4(separatorCopy, '')) push$5(output, '');
6361               } else push$5(output, stringSlice$5(string, lastLastIndex));
6362               return output.length > lim ? arraySlice$4(output, 0, lim) : output;
6363             };
6364           // Chakra, V8
6365           } else if ('0'.split(undefined, 0).length) {
6366             internalSplit = function (separator, limit) {
6367               return separator === undefined && limit === 0 ? [] : call$6(nativeSplit, this, separator, limit);
6368             };
6369           } else internalSplit = nativeSplit;
6370
6371           return [
6372             // `String.prototype.split` method
6373             // https://tc39.es/ecma262/#sec-string.prototype.split
6374             function split(separator, limit) {
6375               var O = requireObjectCoercible$9(this);
6376               var splitter = separator == undefined ? undefined : getMethod$2(separator, SPLIT);
6377               return splitter
6378                 ? call$6(splitter, separator, O, limit)
6379                 : call$6(internalSplit, toString$e(O), separator, limit);
6380             },
6381             // `RegExp.prototype[@@split]` method
6382             // https://tc39.es/ecma262/#sec-regexp.prototype-@@split
6383             //
6384             // NOTE: This cannot be properly polyfilled in engines that don't support
6385             // the 'y' flag.
6386             function (string, limit) {
6387               var rx = anObject$5(this);
6388               var S = toString$e(string);
6389               var res = maybeCallNative(internalSplit, rx, S, limit, internalSplit !== nativeSplit);
6390
6391               if (res.done) return res.value;
6392
6393               var C = speciesConstructor$1(rx, RegExp);
6394
6395               var unicodeMatching = rx.unicode;
6396               var flags = (rx.ignoreCase ? 'i' : '') +
6397                           (rx.multiline ? 'm' : '') +
6398                           (rx.unicode ? 'u' : '') +
6399                           (UNSUPPORTED_Y$1 ? 'g' : 'y');
6400
6401               // ^(? + rx + ) is needed, in combination with some S slicing, to
6402               // simulate the 'y' flag.
6403               var splitter = new C(UNSUPPORTED_Y$1 ? '^(?:' + rx.source + ')' : rx, flags);
6404               var lim = limit === undefined ? MAX_UINT32 : limit >>> 0;
6405               if (lim === 0) return [];
6406               if (S.length === 0) return callRegExpExec(splitter, S) === null ? [S] : [];
6407               var p = 0;
6408               var q = 0;
6409               var A = [];
6410               while (q < S.length) {
6411                 splitter.lastIndex = UNSUPPORTED_Y$1 ? 0 : q;
6412                 var z = callRegExpExec(splitter, UNSUPPORTED_Y$1 ? stringSlice$5(S, q) : S);
6413                 var e;
6414                 if (
6415                   z === null ||
6416                   (e = min$4(toLength$4(splitter.lastIndex + (UNSUPPORTED_Y$1 ? q : 0)), S.length)) === p
6417                 ) {
6418                   q = advanceStringIndex$1(S, q, unicodeMatching);
6419                 } else {
6420                   push$5(A, stringSlice$5(S, p, q));
6421                   if (A.length === lim) return A;
6422                   for (var i = 1; i <= z.length - 1; i++) {
6423                     push$5(A, z[i]);
6424                     if (A.length === lim) return A;
6425                   }
6426                   q = p = e;
6427                 }
6428               }
6429               push$5(A, stringSlice$5(S, p));
6430               return A;
6431             }
6432           ];
6433         }, !SPLIT_WORKS_WITH_OVERWRITTEN_EXEC, UNSUPPORTED_Y$1);
6434
6435         // a string of all valid unicode whitespaces
6436         var whitespaces$4 = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' +
6437           '\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF';
6438
6439         var uncurryThis$o = functionUncurryThis;
6440         var requireObjectCoercible$8 = requireObjectCoercible$e;
6441         var toString$d = toString$k;
6442         var whitespaces$3 = whitespaces$4;
6443
6444         var replace$4 = uncurryThis$o(''.replace);
6445         var whitespace = '[' + whitespaces$3 + ']';
6446         var ltrim = RegExp('^' + whitespace + whitespace + '*');
6447         var rtrim$2 = RegExp(whitespace + whitespace + '*$');
6448
6449         // `String.prototype.{ trim, trimStart, trimEnd, trimLeft, trimRight }` methods implementation
6450         var createMethod$2 = function (TYPE) {
6451           return function ($this) {
6452             var string = toString$d(requireObjectCoercible$8($this));
6453             if (TYPE & 1) string = replace$4(string, ltrim, '');
6454             if (TYPE & 2) string = replace$4(string, rtrim$2, '');
6455             return string;
6456           };
6457         };
6458
6459         var stringTrim = {
6460           // `String.prototype.{ trimLeft, trimStart }` methods
6461           // https://tc39.es/ecma262/#sec-string.prototype.trimstart
6462           start: createMethod$2(1),
6463           // `String.prototype.{ trimRight, trimEnd }` methods
6464           // https://tc39.es/ecma262/#sec-string.prototype.trimend
6465           end: createMethod$2(2),
6466           // `String.prototype.trim` method
6467           // https://tc39.es/ecma262/#sec-string.prototype.trim
6468           trim: createMethod$2(3)
6469         };
6470
6471         var PROPER_FUNCTION_NAME = functionName.PROPER;
6472         var fails$o = fails$V;
6473         var whitespaces$2 = whitespaces$4;
6474
6475         var non = '\u200B\u0085\u180E';
6476
6477         // check that a method works with the correct list
6478         // of whitespaces and has a correct name
6479         var stringTrimForced = function (METHOD_NAME) {
6480           return fails$o(function () {
6481             return !!whitespaces$2[METHOD_NAME]()
6482               || non[METHOD_NAME]() !== non
6483               || (PROPER_FUNCTION_NAME && whitespaces$2[METHOD_NAME].name !== METHOD_NAME);
6484           });
6485         };
6486
6487         var $$W = _export;
6488         var $trim = stringTrim.trim;
6489         var forcedStringTrimMethod$2 = stringTrimForced;
6490
6491         // `String.prototype.trim` method
6492         // https://tc39.es/ecma262/#sec-string.prototype.trim
6493         $$W({ target: 'String', proto: true, forced: forcedStringTrimMethod$2('trim') }, {
6494           trim: function trim() {
6495             return $trim(this);
6496           }
6497         });
6498
6499         var DESCRIPTORS$b = descriptors;
6500         var FUNCTION_NAME_EXISTS = functionName.EXISTS;
6501         var uncurryThis$n = functionUncurryThis;
6502         var defineProperty$6 = objectDefineProperty.f;
6503
6504         var FunctionPrototype = Function.prototype;
6505         var functionToString = uncurryThis$n(FunctionPrototype.toString);
6506         var nameRE = /function\b(?:\s|\/\*[\S\s]*?\*\/|\/\/[^\n\r]*[\n\r]+)*([^\s(/]*)/;
6507         var regExpExec$2 = uncurryThis$n(nameRE.exec);
6508         var NAME = 'name';
6509
6510         // Function instances `.name` property
6511         // https://tc39.es/ecma262/#sec-function-instances-name
6512         if (DESCRIPTORS$b && !FUNCTION_NAME_EXISTS) {
6513           defineProperty$6(FunctionPrototype, NAME, {
6514             configurable: true,
6515             get: function () {
6516               try {
6517                 return regExpExec$2(nameRE, functionToString(this))[1];
6518               } catch (error) {
6519                 return '';
6520               }
6521             }
6522           });
6523         }
6524
6525         var $$V = _export;
6526         var DESCRIPTORS$a = descriptors;
6527         var create$5 = objectCreate;
6528
6529         // `Object.create` method
6530         // https://tc39.es/ecma262/#sec-object.create
6531         $$V({ target: 'Object', stat: true, sham: !DESCRIPTORS$a }, {
6532           create: create$5
6533         });
6534
6535         var $$U = _export;
6536         var global$l = global$1o;
6537         var apply$1 = functionApply;
6538         var isCallable$2 = isCallable$r;
6539         var userAgent$1 = engineUserAgent;
6540         var arraySlice$3 = arraySlice$b;
6541         var validateArgumentsLength$1 = validateArgumentsLength$4;
6542
6543         var MSIE = /MSIE .\./.test(userAgent$1); // <- dirty ie9- check
6544         var Function$2 = global$l.Function;
6545
6546         var wrap$1 = function (scheduler) {
6547           return function (handler, timeout /* , ...arguments */) {
6548             var boundArgs = validateArgumentsLength$1(arguments.length, 1) > 2;
6549             var fn = isCallable$2(handler) ? handler : Function$2(handler);
6550             var args = boundArgs ? arraySlice$3(arguments, 2) : undefined;
6551             return scheduler(boundArgs ? function () {
6552               apply$1(fn, this, args);
6553             } : fn, timeout);
6554           };
6555         };
6556
6557         // ie9- setTimeout & setInterval additional parameters fix
6558         // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#timers
6559         $$U({ global: true, bind: true, forced: MSIE }, {
6560           // `setTimeout` method
6561           // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-settimeout
6562           setTimeout: wrap$1(global$l.setTimeout),
6563           // `setInterval` method
6564           // https://html.spec.whatwg.org/multipage/timers-and-user-prompts.html#dom-setinterval
6565           setInterval: wrap$1(global$l.setInterval)
6566         });
6567
6568         var global$k = typeof globalThis !== 'undefined' && globalThis || typeof self !== 'undefined' && self || typeof global$k !== 'undefined' && global$k;
6569         var support = {
6570           searchParams: 'URLSearchParams' in global$k,
6571           iterable: 'Symbol' in global$k && 'iterator' in Symbol,
6572           blob: 'FileReader' in global$k && 'Blob' in global$k && function () {
6573             try {
6574               new Blob();
6575               return true;
6576             } catch (e) {
6577               return false;
6578             }
6579           }(),
6580           formData: 'FormData' in global$k,
6581           arrayBuffer: 'ArrayBuffer' in global$k
6582         };
6583
6584         function isDataView(obj) {
6585           return obj && DataView.prototype.isPrototypeOf(obj);
6586         }
6587
6588         if (support.arrayBuffer) {
6589           var viewClasses = ['[object Int8Array]', '[object Uint8Array]', '[object Uint8ClampedArray]', '[object Int16Array]', '[object Uint16Array]', '[object Int32Array]', '[object Uint32Array]', '[object Float32Array]', '[object Float64Array]'];
6590
6591           var isArrayBufferView = ArrayBuffer.isView || function (obj) {
6592             return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1;
6593           };
6594         }
6595
6596         function normalizeName(name) {
6597           if (typeof name !== 'string') {
6598             name = String(name);
6599           }
6600
6601           if (/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(name) || name === '') {
6602             throw new TypeError('Invalid character in header field name: "' + name + '"');
6603           }
6604
6605           return name.toLowerCase();
6606         }
6607
6608         function normalizeValue(value) {
6609           if (typeof value !== 'string') {
6610             value = String(value);
6611           }
6612
6613           return value;
6614         } // Build a destructive iterator for the value list
6615
6616
6617         function iteratorFor(items) {
6618           var iterator = {
6619             next: function next() {
6620               var value = items.shift();
6621               return {
6622                 done: value === undefined,
6623                 value: value
6624               };
6625             }
6626           };
6627
6628           if (support.iterable) {
6629             iterator[Symbol.iterator] = function () {
6630               return iterator;
6631             };
6632           }
6633
6634           return iterator;
6635         }
6636
6637         function Headers(headers) {
6638           this.map = {};
6639
6640           if (headers instanceof Headers) {
6641             headers.forEach(function (value, name) {
6642               this.append(name, value);
6643             }, this);
6644           } else if (Array.isArray(headers)) {
6645             headers.forEach(function (header) {
6646               this.append(header[0], header[1]);
6647             }, this);
6648           } else if (headers) {
6649             Object.getOwnPropertyNames(headers).forEach(function (name) {
6650               this.append(name, headers[name]);
6651             }, this);
6652           }
6653         }
6654
6655         Headers.prototype.append = function (name, value) {
6656           name = normalizeName(name);
6657           value = normalizeValue(value);
6658           var oldValue = this.map[name];
6659           this.map[name] = oldValue ? oldValue + ', ' + value : value;
6660         };
6661
6662         Headers.prototype['delete'] = function (name) {
6663           delete this.map[normalizeName(name)];
6664         };
6665
6666         Headers.prototype.get = function (name) {
6667           name = normalizeName(name);
6668           return this.has(name) ? this.map[name] : null;
6669         };
6670
6671         Headers.prototype.has = function (name) {
6672           return this.map.hasOwnProperty(normalizeName(name));
6673         };
6674
6675         Headers.prototype.set = function (name, value) {
6676           this.map[normalizeName(name)] = normalizeValue(value);
6677         };
6678
6679         Headers.prototype.forEach = function (callback, thisArg) {
6680           for (var name in this.map) {
6681             if (this.map.hasOwnProperty(name)) {
6682               callback.call(thisArg, this.map[name], name, this);
6683             }
6684           }
6685         };
6686
6687         Headers.prototype.keys = function () {
6688           var items = [];
6689           this.forEach(function (value, name) {
6690             items.push(name);
6691           });
6692           return iteratorFor(items);
6693         };
6694
6695         Headers.prototype.values = function () {
6696           var items = [];
6697           this.forEach(function (value) {
6698             items.push(value);
6699           });
6700           return iteratorFor(items);
6701         };
6702
6703         Headers.prototype.entries = function () {
6704           var items = [];
6705           this.forEach(function (value, name) {
6706             items.push([name, value]);
6707           });
6708           return iteratorFor(items);
6709         };
6710
6711         if (support.iterable) {
6712           Headers.prototype[Symbol.iterator] = Headers.prototype.entries;
6713         }
6714
6715         function consumed(body) {
6716           if (body.bodyUsed) {
6717             return Promise.reject(new TypeError('Already read'));
6718           }
6719
6720           body.bodyUsed = true;
6721         }
6722
6723         function fileReaderReady(reader) {
6724           return new Promise(function (resolve, reject) {
6725             reader.onload = function () {
6726               resolve(reader.result);
6727             };
6728
6729             reader.onerror = function () {
6730               reject(reader.error);
6731             };
6732           });
6733         }
6734
6735         function readBlobAsArrayBuffer(blob) {
6736           var reader = new FileReader();
6737           var promise = fileReaderReady(reader);
6738           reader.readAsArrayBuffer(blob);
6739           return promise;
6740         }
6741
6742         function readBlobAsText(blob) {
6743           var reader = new FileReader();
6744           var promise = fileReaderReady(reader);
6745           reader.readAsText(blob);
6746           return promise;
6747         }
6748
6749         function readArrayBufferAsText(buf) {
6750           var view = new Uint8Array(buf);
6751           var chars = new Array(view.length);
6752
6753           for (var i = 0; i < view.length; i++) {
6754             chars[i] = String.fromCharCode(view[i]);
6755           }
6756
6757           return chars.join('');
6758         }
6759
6760         function bufferClone(buf) {
6761           if (buf.slice) {
6762             return buf.slice(0);
6763           } else {
6764             var view = new Uint8Array(buf.byteLength);
6765             view.set(new Uint8Array(buf));
6766             return view.buffer;
6767           }
6768         }
6769
6770         function Body() {
6771           this.bodyUsed = false;
6772
6773           this._initBody = function (body) {
6774             /*
6775               fetch-mock wraps the Response object in an ES6 Proxy to
6776               provide useful test harness features such as flush. However, on
6777               ES5 browsers without fetch or Proxy support pollyfills must be used;
6778               the proxy-pollyfill is unable to proxy an attribute unless it exists
6779               on the object before the Proxy is created. This change ensures
6780               Response.bodyUsed exists on the instance, while maintaining the
6781               semantic of setting Request.bodyUsed in the constructor before
6782               _initBody is called.
6783             */
6784             this.bodyUsed = this.bodyUsed;
6785             this._bodyInit = body;
6786
6787             if (!body) {
6788               this._bodyText = '';
6789             } else if (typeof body === 'string') {
6790               this._bodyText = body;
6791             } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
6792               this._bodyBlob = body;
6793             } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
6794               this._bodyFormData = body;
6795             } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
6796               this._bodyText = body.toString();
6797             } else if (support.arrayBuffer && support.blob && isDataView(body)) {
6798               this._bodyArrayBuffer = bufferClone(body.buffer); // IE 10-11 can't handle a DataView body.
6799
6800               this._bodyInit = new Blob([this._bodyArrayBuffer]);
6801             } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
6802               this._bodyArrayBuffer = bufferClone(body);
6803             } else {
6804               this._bodyText = body = Object.prototype.toString.call(body);
6805             }
6806
6807             if (!this.headers.get('content-type')) {
6808               if (typeof body === 'string') {
6809                 this.headers.set('content-type', 'text/plain;charset=UTF-8');
6810               } else if (this._bodyBlob && this._bodyBlob.type) {
6811                 this.headers.set('content-type', this._bodyBlob.type);
6812               } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
6813                 this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
6814               }
6815             }
6816           };
6817
6818           if (support.blob) {
6819             this.blob = function () {
6820               var rejected = consumed(this);
6821
6822               if (rejected) {
6823                 return rejected;
6824               }
6825
6826               if (this._bodyBlob) {
6827                 return Promise.resolve(this._bodyBlob);
6828               } else if (this._bodyArrayBuffer) {
6829                 return Promise.resolve(new Blob([this._bodyArrayBuffer]));
6830               } else if (this._bodyFormData) {
6831                 throw new Error('could not read FormData body as blob');
6832               } else {
6833                 return Promise.resolve(new Blob([this._bodyText]));
6834               }
6835             };
6836
6837             this.arrayBuffer = function () {
6838               if (this._bodyArrayBuffer) {
6839                 var isConsumed = consumed(this);
6840
6841                 if (isConsumed) {
6842                   return isConsumed;
6843                 }
6844
6845                 if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
6846                   return Promise.resolve(this._bodyArrayBuffer.buffer.slice(this._bodyArrayBuffer.byteOffset, this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength));
6847                 } else {
6848                   return Promise.resolve(this._bodyArrayBuffer);
6849                 }
6850               } else {
6851                 return this.blob().then(readBlobAsArrayBuffer);
6852               }
6853             };
6854           }
6855
6856           this.text = function () {
6857             var rejected = consumed(this);
6858
6859             if (rejected) {
6860               return rejected;
6861             }
6862
6863             if (this._bodyBlob) {
6864               return readBlobAsText(this._bodyBlob);
6865             } else if (this._bodyArrayBuffer) {
6866               return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer));
6867             } else if (this._bodyFormData) {
6868               throw new Error('could not read FormData body as text');
6869             } else {
6870               return Promise.resolve(this._bodyText);
6871             }
6872           };
6873
6874           if (support.formData) {
6875             this.formData = function () {
6876               return this.text().then(decode);
6877             };
6878           }
6879
6880           this.json = function () {
6881             return this.text().then(JSON.parse);
6882           };
6883
6884           return this;
6885         } // HTTP methods whose capitalization should be normalized
6886
6887
6888         var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT'];
6889
6890         function normalizeMethod(method) {
6891           var upcased = method.toUpperCase();
6892           return methods.indexOf(upcased) > -1 ? upcased : method;
6893         }
6894
6895         function Request(input, options) {
6896           if (!(this instanceof Request)) {
6897             throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');
6898           }
6899
6900           options = options || {};
6901           var body = options.body;
6902
6903           if (input instanceof Request) {
6904             if (input.bodyUsed) {
6905               throw new TypeError('Already read');
6906             }
6907
6908             this.url = input.url;
6909             this.credentials = input.credentials;
6910
6911             if (!options.headers) {
6912               this.headers = new Headers(input.headers);
6913             }
6914
6915             this.method = input.method;
6916             this.mode = input.mode;
6917             this.signal = input.signal;
6918
6919             if (!body && input._bodyInit != null) {
6920               body = input._bodyInit;
6921               input.bodyUsed = true;
6922             }
6923           } else {
6924             this.url = String(input);
6925           }
6926
6927           this.credentials = options.credentials || this.credentials || 'same-origin';
6928
6929           if (options.headers || !this.headers) {
6930             this.headers = new Headers(options.headers);
6931           }
6932
6933           this.method = normalizeMethod(options.method || this.method || 'GET');
6934           this.mode = options.mode || this.mode || null;
6935           this.signal = options.signal || this.signal;
6936           this.referrer = null;
6937
6938           if ((this.method === 'GET' || this.method === 'HEAD') && body) {
6939             throw new TypeError('Body not allowed for GET or HEAD requests');
6940           }
6941
6942           this._initBody(body);
6943
6944           if (this.method === 'GET' || this.method === 'HEAD') {
6945             if (options.cache === 'no-store' || options.cache === 'no-cache') {
6946               // Search for a '_' parameter in the query string
6947               var reParamSearch = /([?&])_=[^&]*/;
6948
6949               if (reParamSearch.test(this.url)) {
6950                 // If it already exists then set the value with the current time
6951                 this.url = this.url.replace(reParamSearch, '$1_=' + new Date().getTime());
6952               } else {
6953                 // Otherwise add a new '_' parameter to the end with the current time
6954                 var reQueryString = /\?/;
6955                 this.url += (reQueryString.test(this.url) ? '&' : '?') + '_=' + new Date().getTime();
6956               }
6957             }
6958           }
6959         }
6960
6961         Request.prototype.clone = function () {
6962           return new Request(this, {
6963             body: this._bodyInit
6964           });
6965         };
6966
6967         function decode(body) {
6968           var form = new FormData();
6969           body.trim().split('&').forEach(function (bytes) {
6970             if (bytes) {
6971               var split = bytes.split('=');
6972               var name = split.shift().replace(/\+/g, ' ');
6973               var value = split.join('=').replace(/\+/g, ' ');
6974               form.append(decodeURIComponent(name), decodeURIComponent(value));
6975             }
6976           });
6977           return form;
6978         }
6979
6980         function parseHeaders(rawHeaders) {
6981           var headers = new Headers(); // Replace instances of \r\n and \n followed by at least one space or horizontal tab with a space
6982           // https://tools.ietf.org/html/rfc7230#section-3.2
6983
6984           var preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, ' '); // Avoiding split via regex to work around a common IE11 bug with the core-js 3.6.0 regex polyfill
6985           // https://github.com/github/fetch/issues/748
6986           // https://github.com/zloirock/core-js/issues/751
6987
6988           preProcessedHeaders.split('\r').map(function (header) {
6989             return header.indexOf('\n') === 0 ? header.substr(1, header.length) : header;
6990           }).forEach(function (line) {
6991             var parts = line.split(':');
6992             var key = parts.shift().trim();
6993
6994             if (key) {
6995               var value = parts.join(':').trim();
6996               headers.append(key, value);
6997             }
6998           });
6999           return headers;
7000         }
7001
7002         Body.call(Request.prototype);
7003         function Response(bodyInit, options) {
7004           if (!(this instanceof Response)) {
7005             throw new TypeError('Please use the "new" operator, this DOM object constructor cannot be called as a function.');
7006           }
7007
7008           if (!options) {
7009             options = {};
7010           }
7011
7012           this.type = 'default';
7013           this.status = options.status === undefined ? 200 : options.status;
7014           this.ok = this.status >= 200 && this.status < 300;
7015           this.statusText = options.statusText === undefined ? '' : '' + options.statusText;
7016           this.headers = new Headers(options.headers);
7017           this.url = options.url || '';
7018
7019           this._initBody(bodyInit);
7020         }
7021         Body.call(Response.prototype);
7022
7023         Response.prototype.clone = function () {
7024           return new Response(this._bodyInit, {
7025             status: this.status,
7026             statusText: this.statusText,
7027             headers: new Headers(this.headers),
7028             url: this.url
7029           });
7030         };
7031
7032         Response.error = function () {
7033           var response = new Response(null, {
7034             status: 0,
7035             statusText: ''
7036           });
7037           response.type = 'error';
7038           return response;
7039         };
7040
7041         var redirectStatuses = [301, 302, 303, 307, 308];
7042
7043         Response.redirect = function (url, status) {
7044           if (redirectStatuses.indexOf(status) === -1) {
7045             throw new RangeError('Invalid status code');
7046           }
7047
7048           return new Response(null, {
7049             status: status,
7050             headers: {
7051               location: url
7052             }
7053           });
7054         };
7055
7056         var DOMException$1 = global$k.DOMException;
7057
7058         try {
7059           new DOMException$1();
7060         } catch (err) {
7061           DOMException$1 = function DOMException(message, name) {
7062             this.message = message;
7063             this.name = name;
7064             var error = Error(message);
7065             this.stack = error.stack;
7066           };
7067
7068           DOMException$1.prototype = Object.create(Error.prototype);
7069           DOMException$1.prototype.constructor = DOMException$1;
7070         }
7071
7072         function fetch$1(input, init) {
7073           return new Promise(function (resolve, reject) {
7074             var request = new Request(input, init);
7075
7076             if (request.signal && request.signal.aborted) {
7077               return reject(new DOMException$1('Aborted', 'AbortError'));
7078             }
7079
7080             var xhr = new XMLHttpRequest();
7081
7082             function abortXhr() {
7083               xhr.abort();
7084             }
7085
7086             xhr.onload = function () {
7087               var options = {
7088                 status: xhr.status,
7089                 statusText: xhr.statusText,
7090                 headers: parseHeaders(xhr.getAllResponseHeaders() || '')
7091               };
7092               options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL');
7093               var body = 'response' in xhr ? xhr.response : xhr.responseText;
7094               setTimeout(function () {
7095                 resolve(new Response(body, options));
7096               }, 0);
7097             };
7098
7099             xhr.onerror = function () {
7100               setTimeout(function () {
7101                 reject(new TypeError('Network request failed'));
7102               }, 0);
7103             };
7104
7105             xhr.ontimeout = function () {
7106               setTimeout(function () {
7107                 reject(new TypeError('Network request failed'));
7108               }, 0);
7109             };
7110
7111             xhr.onabort = function () {
7112               setTimeout(function () {
7113                 reject(new DOMException$1('Aborted', 'AbortError'));
7114               }, 0);
7115             };
7116
7117             function fixUrl(url) {
7118               try {
7119                 return url === '' && global$k.location.href ? global$k.location.href : url;
7120               } catch (e) {
7121                 return url;
7122               }
7123             }
7124
7125             xhr.open(request.method, fixUrl(request.url), true);
7126
7127             if (request.credentials === 'include') {
7128               xhr.withCredentials = true;
7129             } else if (request.credentials === 'omit') {
7130               xhr.withCredentials = false;
7131             }
7132
7133             if ('responseType' in xhr) {
7134               if (support.blob) {
7135                 xhr.responseType = 'blob';
7136               } else if (support.arrayBuffer && request.headers.get('Content-Type') && request.headers.get('Content-Type').indexOf('application/octet-stream') !== -1) {
7137                 xhr.responseType = 'arraybuffer';
7138               }
7139             }
7140
7141             if (init && _typeof(init.headers) === 'object' && !(init.headers instanceof Headers)) {
7142               Object.getOwnPropertyNames(init.headers).forEach(function (name) {
7143                 xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
7144               });
7145             } else {
7146               request.headers.forEach(function (value, name) {
7147                 xhr.setRequestHeader(name, value);
7148               });
7149             }
7150
7151             if (request.signal) {
7152               request.signal.addEventListener('abort', abortXhr);
7153
7154               xhr.onreadystatechange = function () {
7155                 // DONE (success or failure)
7156                 if (xhr.readyState === 4) {
7157                   request.signal.removeEventListener('abort', abortXhr);
7158                 }
7159               };
7160             }
7161
7162             xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit);
7163           });
7164         }
7165         fetch$1.polyfill = true;
7166
7167         if (!global$k.fetch) {
7168           global$k.fetch = fetch$1;
7169           global$k.Headers = Headers;
7170           global$k.Request = Request;
7171           global$k.Response = Response;
7172         }
7173
7174         var $$T = _export;
7175         var DESCRIPTORS$9 = descriptors;
7176         var defineProperty$5 = objectDefineProperty.f;
7177
7178         // `Object.defineProperty` method
7179         // https://tc39.es/ecma262/#sec-object.defineproperty
7180         // eslint-disable-next-line es/no-object-defineproperty -- safe
7181         $$T({ target: 'Object', stat: true, forced: Object.defineProperty !== defineProperty$5, sham: !DESCRIPTORS$9 }, {
7182           defineProperty: defineProperty$5
7183         });
7184
7185         var $$S = _export;
7186         var setPrototypeOf = objectSetPrototypeOf;
7187
7188         // `Object.setPrototypeOf` method
7189         // https://tc39.es/ecma262/#sec-object.setprototypeof
7190         $$S({ target: 'Object', stat: true }, {
7191           setPrototypeOf: setPrototypeOf
7192         });
7193
7194         var $$R = _export;
7195         var fails$n = fails$V;
7196         var toObject$8 = toObject$i;
7197         var nativeGetPrototypeOf = objectGetPrototypeOf;
7198         var CORRECT_PROTOTYPE_GETTER = correctPrototypeGetter;
7199
7200         var FAILS_ON_PRIMITIVES$4 = fails$n(function () { nativeGetPrototypeOf(1); });
7201
7202         // `Object.getPrototypeOf` method
7203         // https://tc39.es/ecma262/#sec-object.getprototypeof
7204         $$R({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$4, sham: !CORRECT_PROTOTYPE_GETTER }, {
7205           getPrototypeOf: function getPrototypeOf(it) {
7206             return nativeGetPrototypeOf(toObject$8(it));
7207           }
7208         });
7209
7210         var global$j = global$1o;
7211         var uncurryThis$m = functionUncurryThis;
7212         var aCallable$2 = aCallable$a;
7213         var isObject$b = isObject$s;
7214         var hasOwn$5 = hasOwnProperty_1;
7215         var arraySlice$2 = arraySlice$b;
7216         var NATIVE_BIND = functionBindNative;
7217
7218         var Function$1 = global$j.Function;
7219         var concat$1 = uncurryThis$m([].concat);
7220         var join$3 = uncurryThis$m([].join);
7221         var factories = {};
7222
7223         var construct = function (C, argsLength, args) {
7224           if (!hasOwn$5(factories, argsLength)) {
7225             for (var list = [], i = 0; i < argsLength; i++) list[i] = 'a[' + i + ']';
7226             factories[argsLength] = Function$1('C,a', 'return new C(' + join$3(list, ',') + ')');
7227           } return factories[argsLength](C, args);
7228         };
7229
7230         // `Function.prototype.bind` method implementation
7231         // https://tc39.es/ecma262/#sec-function.prototype.bind
7232         var functionBind = NATIVE_BIND ? Function$1.bind : function bind(that /* , ...args */) {
7233           var F = aCallable$2(this);
7234           var Prototype = F.prototype;
7235           var partArgs = arraySlice$2(arguments, 1);
7236           var boundFunction = function bound(/* args... */) {
7237             var args = concat$1(partArgs, arraySlice$2(arguments));
7238             return this instanceof boundFunction ? construct(F, args.length, args) : F.apply(that, args);
7239           };
7240           if (isObject$b(Prototype)) boundFunction.prototype = Prototype;
7241           return boundFunction;
7242         };
7243
7244         var $$Q = _export;
7245         var getBuiltIn$1 = getBuiltIn$b;
7246         var apply = functionApply;
7247         var bind$7 = functionBind;
7248         var aConstructor = aConstructor$3;
7249         var anObject$4 = anObject$n;
7250         var isObject$a = isObject$s;
7251         var create$4 = objectCreate;
7252         var fails$m = fails$V;
7253
7254         var nativeConstruct = getBuiltIn$1('Reflect', 'construct');
7255         var ObjectPrototype = Object.prototype;
7256         var push$4 = [].push;
7257
7258         // `Reflect.construct` method
7259         // https://tc39.es/ecma262/#sec-reflect.construct
7260         // MS Edge supports only 2 arguments and argumentsList argument is optional
7261         // FF Nightly sets third argument as `new.target`, but does not create `this` from it
7262         var NEW_TARGET_BUG = fails$m(function () {
7263           function F() { /* empty */ }
7264           return !(nativeConstruct(function () { /* empty */ }, [], F) instanceof F);
7265         });
7266
7267         var ARGS_BUG = !fails$m(function () {
7268           nativeConstruct(function () { /* empty */ });
7269         });
7270
7271         var FORCED$c = NEW_TARGET_BUG || ARGS_BUG;
7272
7273         $$Q({ target: 'Reflect', stat: true, forced: FORCED$c, sham: FORCED$c }, {
7274           construct: function construct(Target, args /* , newTarget */) {
7275             aConstructor(Target);
7276             anObject$4(args);
7277             var newTarget = arguments.length < 3 ? Target : aConstructor(arguments[2]);
7278             if (ARGS_BUG && !NEW_TARGET_BUG) return nativeConstruct(Target, args, newTarget);
7279             if (Target == newTarget) {
7280               // w/o altered newTarget, optimization for 0-4 arguments
7281               switch (args.length) {
7282                 case 0: return new Target();
7283                 case 1: return new Target(args[0]);
7284                 case 2: return new Target(args[0], args[1]);
7285                 case 3: return new Target(args[0], args[1], args[2]);
7286                 case 4: return new Target(args[0], args[1], args[2], args[3]);
7287               }
7288               // w/o altered newTarget, lot of arguments case
7289               var $args = [null];
7290               apply(push$4, $args, args);
7291               return new (apply(bind$7, Target, $args))();
7292             }
7293             // with altered newTarget, not support built-in constructors
7294             var proto = newTarget.prototype;
7295             var instance = create$4(isObject$a(proto) ? proto : ObjectPrototype);
7296             var result = apply(Target, instance, args);
7297             return isObject$a(result) ? result : instance;
7298           }
7299         });
7300
7301         var hasOwn$4 = hasOwnProperty_1;
7302
7303         var isDataDescriptor$1 = function (descriptor) {
7304           return descriptor !== undefined && (hasOwn$4(descriptor, 'value') || hasOwn$4(descriptor, 'writable'));
7305         };
7306
7307         var $$P = _export;
7308         var call$5 = functionCall;
7309         var isObject$9 = isObject$s;
7310         var anObject$3 = anObject$n;
7311         var isDataDescriptor = isDataDescriptor$1;
7312         var getOwnPropertyDescriptorModule = objectGetOwnPropertyDescriptor;
7313         var getPrototypeOf = objectGetPrototypeOf;
7314
7315         // `Reflect.get` method
7316         // https://tc39.es/ecma262/#sec-reflect.get
7317         function get$3(target, propertyKey /* , receiver */) {
7318           var receiver = arguments.length < 3 ? target : arguments[2];
7319           var descriptor, prototype;
7320           if (anObject$3(target) === receiver) return target[propertyKey];
7321           descriptor = getOwnPropertyDescriptorModule.f(target, propertyKey);
7322           if (descriptor) return isDataDescriptor(descriptor)
7323             ? descriptor.value
7324             : descriptor.get === undefined ? undefined : call$5(descriptor.get, receiver);
7325           if (isObject$9(prototype = getPrototypeOf(target))) return get$3(prototype, propertyKey, receiver);
7326         }
7327
7328         $$P({ target: 'Reflect', stat: true }, {
7329           get: get$3
7330         });
7331
7332         var $$O = _export;
7333         var fails$l = fails$V;
7334         var toIndexedObject$1 = toIndexedObject$d;
7335         var nativeGetOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
7336         var DESCRIPTORS$8 = descriptors;
7337
7338         var FAILS_ON_PRIMITIVES$3 = fails$l(function () { nativeGetOwnPropertyDescriptor(1); });
7339         var FORCED$b = !DESCRIPTORS$8 || FAILS_ON_PRIMITIVES$3;
7340
7341         // `Object.getOwnPropertyDescriptor` method
7342         // https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
7343         $$O({ target: 'Object', stat: true, forced: FORCED$b, sham: !DESCRIPTORS$8 }, {
7344           getOwnPropertyDescriptor: function getOwnPropertyDescriptor(it, key) {
7345             return nativeGetOwnPropertyDescriptor(toIndexedObject$1(it), key);
7346           }
7347         });
7348
7349         var $$N = _export;
7350         var global$i = global$1o;
7351         var toAbsoluteIndex$1 = toAbsoluteIndex$9;
7352         var toIntegerOrInfinity$2 = toIntegerOrInfinity$b;
7353         var lengthOfArrayLike$5 = lengthOfArrayLike$i;
7354         var toObject$7 = toObject$i;
7355         var arraySpeciesCreate$2 = arraySpeciesCreate$4;
7356         var createProperty$2 = createProperty$5;
7357         var arrayMethodHasSpeciesSupport$2 = arrayMethodHasSpeciesSupport$5;
7358
7359         var HAS_SPECIES_SUPPORT$1 = arrayMethodHasSpeciesSupport$2('splice');
7360
7361         var TypeError$6 = global$i.TypeError;
7362         var max$1 = Math.max;
7363         var min$3 = Math.min;
7364         var MAX_SAFE_INTEGER$1 = 0x1FFFFFFFFFFFFF;
7365         var MAXIMUM_ALLOWED_LENGTH_EXCEEDED = 'Maximum allowed length exceeded';
7366
7367         // `Array.prototype.splice` method
7368         // https://tc39.es/ecma262/#sec-array.prototype.splice
7369         // with adding support of @@species
7370         $$N({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT$1 }, {
7371           splice: function splice(start, deleteCount /* , ...items */) {
7372             var O = toObject$7(this);
7373             var len = lengthOfArrayLike$5(O);
7374             var actualStart = toAbsoluteIndex$1(start, len);
7375             var argumentsLength = arguments.length;
7376             var insertCount, actualDeleteCount, A, k, from, to;
7377             if (argumentsLength === 0) {
7378               insertCount = actualDeleteCount = 0;
7379             } else if (argumentsLength === 1) {
7380               insertCount = 0;
7381               actualDeleteCount = len - actualStart;
7382             } else {
7383               insertCount = argumentsLength - 2;
7384               actualDeleteCount = min$3(max$1(toIntegerOrInfinity$2(deleteCount), 0), len - actualStart);
7385             }
7386             if (len + insertCount - actualDeleteCount > MAX_SAFE_INTEGER$1) {
7387               throw TypeError$6(MAXIMUM_ALLOWED_LENGTH_EXCEEDED);
7388             }
7389             A = arraySpeciesCreate$2(O, actualDeleteCount);
7390             for (k = 0; k < actualDeleteCount; k++) {
7391               from = actualStart + k;
7392               if (from in O) createProperty$2(A, k, O[from]);
7393             }
7394             A.length = actualDeleteCount;
7395             if (insertCount < actualDeleteCount) {
7396               for (k = actualStart; k < len - actualDeleteCount; k++) {
7397                 from = k + actualDeleteCount;
7398                 to = k + insertCount;
7399                 if (from in O) O[to] = O[from];
7400                 else delete O[to];
7401               }
7402               for (k = len; k > len - actualDeleteCount + insertCount; k--) delete O[k - 1];
7403             } else if (insertCount > actualDeleteCount) {
7404               for (k = len - actualDeleteCount; k > actualStart; k--) {
7405                 from = k + actualDeleteCount - 1;
7406                 to = k + insertCount - 1;
7407                 if (from in O) O[to] = O[from];
7408                 else delete O[to];
7409               }
7410             }
7411             for (k = 0; k < insertCount; k++) {
7412               O[k + actualStart] = arguments[k + 2];
7413             }
7414             O.length = len - actualDeleteCount + insertCount;
7415             return A;
7416           }
7417         });
7418
7419         var defineWellKnownSymbol$1 = defineWellKnownSymbol$4;
7420
7421         // `Symbol.toStringTag` well-known symbol
7422         // https://tc39.es/ecma262/#sec-symbol.tostringtag
7423         defineWellKnownSymbol$1('toStringTag');
7424
7425         var global$h = global$1o;
7426         var setToStringTag$3 = setToStringTag$a;
7427
7428         // JSON[@@toStringTag] property
7429         // https://tc39.es/ecma262/#sec-json-@@tostringtag
7430         setToStringTag$3(global$h.JSON, 'JSON', true);
7431
7432         var setToStringTag$2 = setToStringTag$a;
7433
7434         // Math[@@toStringTag] property
7435         // https://tc39.es/ecma262/#sec-math-@@tostringtag
7436         setToStringTag$2(Math, 'Math', true);
7437
7438         (function (factory) {
7439           factory();
7440         })(function () {
7441
7442           function _classCallCheck(instance, Constructor) {
7443             if (!(instance instanceof Constructor)) {
7444               throw new TypeError("Cannot call a class as a function");
7445             }
7446           }
7447
7448           function _defineProperties(target, props) {
7449             for (var i = 0; i < props.length; i++) {
7450               var descriptor = props[i];
7451               descriptor.enumerable = descriptor.enumerable || false;
7452               descriptor.configurable = true;
7453               if ("value" in descriptor) descriptor.writable = true;
7454               Object.defineProperty(target, descriptor.key, descriptor);
7455             }
7456           }
7457
7458           function _createClass(Constructor, protoProps, staticProps) {
7459             if (protoProps) _defineProperties(Constructor.prototype, protoProps);
7460             if (staticProps) _defineProperties(Constructor, staticProps);
7461             return Constructor;
7462           }
7463
7464           function _inherits(subClass, superClass) {
7465             if (typeof superClass !== "function" && superClass !== null) {
7466               throw new TypeError("Super expression must either be null or a function");
7467             }
7468
7469             subClass.prototype = Object.create(superClass && superClass.prototype, {
7470               constructor: {
7471                 value: subClass,
7472                 writable: true,
7473                 configurable: true
7474               }
7475             });
7476             if (superClass) _setPrototypeOf(subClass, superClass);
7477           }
7478
7479           function _getPrototypeOf(o) {
7480             _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
7481               return o.__proto__ || Object.getPrototypeOf(o);
7482             };
7483             return _getPrototypeOf(o);
7484           }
7485
7486           function _setPrototypeOf(o, p) {
7487             _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
7488               o.__proto__ = p;
7489               return o;
7490             };
7491
7492             return _setPrototypeOf(o, p);
7493           }
7494
7495           function _isNativeReflectConstruct() {
7496             if (typeof Reflect === "undefined" || !Reflect.construct) return false;
7497             if (Reflect.construct.sham) return false;
7498             if (typeof Proxy === "function") return true;
7499
7500             try {
7501               Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
7502               return true;
7503             } catch (e) {
7504               return false;
7505             }
7506           }
7507
7508           function _assertThisInitialized(self) {
7509             if (self === void 0) {
7510               throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
7511             }
7512
7513             return self;
7514           }
7515
7516           function _possibleConstructorReturn(self, call) {
7517             if (call && (_typeof(call) === "object" || typeof call === "function")) {
7518               return call;
7519             }
7520
7521             return _assertThisInitialized(self);
7522           }
7523
7524           function _createSuper(Derived) {
7525             var hasNativeReflectConstruct = _isNativeReflectConstruct();
7526
7527             return function _createSuperInternal() {
7528               var Super = _getPrototypeOf(Derived),
7529                   result;
7530
7531               if (hasNativeReflectConstruct) {
7532                 var NewTarget = _getPrototypeOf(this).constructor;
7533
7534                 result = Reflect.construct(Super, arguments, NewTarget);
7535               } else {
7536                 result = Super.apply(this, arguments);
7537               }
7538
7539               return _possibleConstructorReturn(this, result);
7540             };
7541           }
7542
7543           function _superPropBase(object, property) {
7544             while (!Object.prototype.hasOwnProperty.call(object, property)) {
7545               object = _getPrototypeOf(object);
7546               if (object === null) break;
7547             }
7548
7549             return object;
7550           }
7551
7552           function _get(target, property, receiver) {
7553             if (typeof Reflect !== "undefined" && Reflect.get) {
7554               _get = Reflect.get;
7555             } else {
7556               _get = function _get(target, property, receiver) {
7557                 var base = _superPropBase(target, property);
7558
7559                 if (!base) return;
7560                 var desc = Object.getOwnPropertyDescriptor(base, property);
7561
7562                 if (desc.get) {
7563                   return desc.get.call(receiver);
7564                 }
7565
7566                 return desc.value;
7567               };
7568             }
7569
7570             return _get(target, property, receiver || target);
7571           }
7572
7573           var Emitter = /*#__PURE__*/function () {
7574             function Emitter() {
7575               _classCallCheck(this, Emitter);
7576
7577               Object.defineProperty(this, 'listeners', {
7578                 value: {},
7579                 writable: true,
7580                 configurable: true
7581               });
7582             }
7583
7584             _createClass(Emitter, [{
7585               key: "addEventListener",
7586               value: function addEventListener(type, callback, options) {
7587                 if (!(type in this.listeners)) {
7588                   this.listeners[type] = [];
7589                 }
7590
7591                 this.listeners[type].push({
7592                   callback: callback,
7593                   options: options
7594                 });
7595               }
7596             }, {
7597               key: "removeEventListener",
7598               value: function removeEventListener(type, callback) {
7599                 if (!(type in this.listeners)) {
7600                   return;
7601                 }
7602
7603                 var stack = this.listeners[type];
7604
7605                 for (var i = 0, l = stack.length; i < l; i++) {
7606                   if (stack[i].callback === callback) {
7607                     stack.splice(i, 1);
7608                     return;
7609                   }
7610                 }
7611               }
7612             }, {
7613               key: "dispatchEvent",
7614               value: function dispatchEvent(event) {
7615                 if (!(event.type in this.listeners)) {
7616                   return;
7617                 }
7618
7619                 var stack = this.listeners[event.type];
7620                 var stackToCall = stack.slice();
7621
7622                 for (var i = 0, l = stackToCall.length; i < l; i++) {
7623                   var listener = stackToCall[i];
7624
7625                   try {
7626                     listener.callback.call(this, event);
7627                   } catch (e) {
7628                     Promise.resolve().then(function () {
7629                       throw e;
7630                     });
7631                   }
7632
7633                   if (listener.options && listener.options.once) {
7634                     this.removeEventListener(event.type, listener.callback);
7635                   }
7636                 }
7637
7638                 return !event.defaultPrevented;
7639               }
7640             }]);
7641
7642             return Emitter;
7643           }();
7644
7645           var AbortSignal = /*#__PURE__*/function (_Emitter) {
7646             _inherits(AbortSignal, _Emitter);
7647
7648             var _super = _createSuper(AbortSignal);
7649
7650             function AbortSignal() {
7651               var _this;
7652
7653               _classCallCheck(this, AbortSignal);
7654
7655               _this = _super.call(this); // Some versions of babel does not transpile super() correctly for IE <= 10, if the parent
7656               // constructor has failed to run, then "this.listeners" will still be undefined and then we call
7657               // the parent constructor directly instead as a workaround. For general details, see babel bug:
7658               // https://github.com/babel/babel/issues/3041
7659               // This hack was added as a fix for the issue described here:
7660               // https://github.com/Financial-Times/polyfill-library/pull/59#issuecomment-477558042
7661
7662               if (!_this.listeners) {
7663                 Emitter.call(_assertThisInitialized(_this));
7664               } // Compared to assignment, Object.defineProperty makes properties non-enumerable by default and
7665               // we want Object.keys(new AbortController().signal) to be [] for compat with the native impl
7666
7667
7668               Object.defineProperty(_assertThisInitialized(_this), 'aborted', {
7669                 value: false,
7670                 writable: true,
7671                 configurable: true
7672               });
7673               Object.defineProperty(_assertThisInitialized(_this), 'onabort', {
7674                 value: null,
7675                 writable: true,
7676                 configurable: true
7677               });
7678               return _this;
7679             }
7680
7681             _createClass(AbortSignal, [{
7682               key: "toString",
7683               value: function toString() {
7684                 return '[object AbortSignal]';
7685               }
7686             }, {
7687               key: "dispatchEvent",
7688               value: function dispatchEvent(event) {
7689                 if (event.type === 'abort') {
7690                   this.aborted = true;
7691
7692                   if (typeof this.onabort === 'function') {
7693                     this.onabort.call(this, event);
7694                   }
7695                 }
7696
7697                 _get(_getPrototypeOf(AbortSignal.prototype), "dispatchEvent", this).call(this, event);
7698               }
7699             }]);
7700
7701             return AbortSignal;
7702           }(Emitter);
7703
7704           var AbortController = /*#__PURE__*/function () {
7705             function AbortController() {
7706               _classCallCheck(this, AbortController); // Compared to assignment, Object.defineProperty makes properties non-enumerable by default and
7707               // we want Object.keys(new AbortController()) to be [] for compat with the native impl
7708
7709
7710               Object.defineProperty(this, 'signal', {
7711                 value: new AbortSignal(),
7712                 writable: true,
7713                 configurable: true
7714               });
7715             }
7716
7717             _createClass(AbortController, [{
7718               key: "abort",
7719               value: function abort() {
7720                 var event;
7721
7722                 try {
7723                   event = new Event('abort');
7724                 } catch (e) {
7725                   if (typeof document !== 'undefined') {
7726                     if (!document.createEvent) {
7727                       // For Internet Explorer 8:
7728                       event = document.createEventObject();
7729                       event.type = 'abort';
7730                     } else {
7731                       // For Internet Explorer 11:
7732                       event = document.createEvent('Event');
7733                       event.initEvent('abort', false, false);
7734                     }
7735                   } else {
7736                     // Fallback where document isn't available:
7737                     event = {
7738                       type: 'abort',
7739                       bubbles: false,
7740                       cancelable: false
7741                     };
7742                   }
7743                 }
7744
7745                 this.signal.dispatchEvent(event);
7746               }
7747             }, {
7748               key: "toString",
7749               value: function toString() {
7750                 return '[object AbortController]';
7751               }
7752             }]);
7753
7754             return AbortController;
7755           }();
7756
7757           if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
7758             // These are necessary to make sure that we get correct output for:
7759             // Object.prototype.toString.call(new AbortController())
7760             AbortController.prototype[Symbol.toStringTag] = 'AbortController';
7761             AbortSignal.prototype[Symbol.toStringTag] = 'AbortSignal';
7762           }
7763
7764           function polyfillNeeded(self) {
7765             if (self.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL) {
7766               console.log('__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL=true is set, will force install polyfill');
7767               return true;
7768             } // Note that the "unfetch" minimal fetch polyfill defines fetch() without
7769             // defining window.Request, and this polyfill need to work on top of unfetch
7770             // so the below feature detection needs the !self.AbortController part.
7771             // The Request.prototype check is also needed because Safari versions 11.1.2
7772             // up to and including 12.1.x has a window.AbortController present but still
7773             // does NOT correctly implement abortable fetch:
7774             // https://bugs.webkit.org/show_bug.cgi?id=174980#c2
7775
7776
7777             return typeof self.Request === 'function' && !self.Request.prototype.hasOwnProperty('signal') || !self.AbortController;
7778           }
7779           /**
7780            * Note: the "fetch.Request" default value is available for fetch imported from
7781            * the "node-fetch" package and not in browsers. This is OK since browsers
7782            * will be importing umd-polyfill.js from that path "self" is passed the
7783            * decorator so the default value will not be used (because browsers that define
7784            * fetch also has Request). One quirky setup where self.fetch exists but
7785            * self.Request does not is when the "unfetch" minimal fetch polyfill is used
7786            * on top of IE11; for this case the browser will try to use the fetch.Request
7787            * default value which in turn will be undefined but then then "if (Request)"
7788            * will ensure that you get a patched fetch but still no Request (as expected).
7789            * @param {fetch, Request = fetch.Request}
7790            * @returns {fetch: abortableFetch, Request: AbortableRequest}
7791            */
7792
7793
7794           function abortableFetchDecorator(patchTargets) {
7795             if ('function' === typeof patchTargets) {
7796               patchTargets = {
7797                 fetch: patchTargets
7798               };
7799             }
7800
7801             var _patchTargets = patchTargets,
7802                 fetch = _patchTargets.fetch,
7803                 _patchTargets$Request = _patchTargets.Request,
7804                 NativeRequest = _patchTargets$Request === void 0 ? fetch.Request : _patchTargets$Request,
7805                 NativeAbortController = _patchTargets.AbortController,
7806                 _patchTargets$__FORCE = _patchTargets.__FORCE_INSTALL_ABORTCONTROLLER_POLYFILL,
7807                 __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL = _patchTargets$__FORCE === void 0 ? false : _patchTargets$__FORCE;
7808
7809             if (!polyfillNeeded({
7810               fetch: fetch,
7811               Request: NativeRequest,
7812               AbortController: NativeAbortController,
7813               __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL: __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL
7814             })) {
7815               return {
7816                 fetch: fetch,
7817                 Request: Request
7818               };
7819             }
7820
7821             var Request = NativeRequest; // Note that the "unfetch" minimal fetch polyfill defines fetch() without
7822             // defining window.Request, and this polyfill need to work on top of unfetch
7823             // hence we only patch it if it's available. Also we don't patch it if signal
7824             // is already available on the Request prototype because in this case support
7825             // is present and the patching below can cause a crash since it assigns to
7826             // request.signal which is technically a read-only property. This latter error
7827             // happens when you run the main5.js node-fetch example in the repo
7828             // "abortcontroller-polyfill-examples". The exact error is:
7829             //   request.signal = init.signal;
7830             //   ^
7831             // TypeError: Cannot set property signal of #<Request> which has only a getter
7832
7833             if (Request && !Request.prototype.hasOwnProperty('signal') || __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL) {
7834               Request = function Request(input, init) {
7835                 var signal;
7836
7837                 if (init && init.signal) {
7838                   signal = init.signal; // Never pass init.signal to the native Request implementation when the polyfill has
7839                   // been installed because if we're running on top of a browser with a
7840                   // working native AbortController (i.e. the polyfill was installed due to
7841                   // __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL being set), then passing our
7842                   // fake AbortSignal to the native fetch will trigger:
7843                   // TypeError: Failed to construct 'Request': member signal is not of type AbortSignal.
7844
7845                   delete init.signal;
7846                 }
7847
7848                 var request = new NativeRequest(input, init);
7849
7850                 if (signal) {
7851                   Object.defineProperty(request, 'signal', {
7852                     writable: false,
7853                     enumerable: false,
7854                     configurable: true,
7855                     value: signal
7856                   });
7857                 }
7858
7859                 return request;
7860               };
7861
7862               Request.prototype = NativeRequest.prototype;
7863             }
7864
7865             var realFetch = fetch;
7866
7867             var abortableFetch = function abortableFetch(input, init) {
7868               var signal = Request && Request.prototype.isPrototypeOf(input) ? input.signal : init ? init.signal : undefined;
7869
7870               if (signal) {
7871                 var abortError;
7872
7873                 try {
7874                   abortError = new DOMException('Aborted', 'AbortError');
7875                 } catch (err) {
7876                   // IE 11 does not support calling the DOMException constructor, use a
7877                   // regular error object on it instead.
7878                   abortError = new Error('Aborted');
7879                   abortError.name = 'AbortError';
7880                 } // Return early if already aborted, thus avoiding making an HTTP request
7881
7882
7883                 if (signal.aborted) {
7884                   return Promise.reject(abortError);
7885                 } // Turn an event into a promise, reject it once `abort` is dispatched
7886
7887
7888                 var cancellation = new Promise(function (_, reject) {
7889                   signal.addEventListener('abort', function () {
7890                     return reject(abortError);
7891                   }, {
7892                     once: true
7893                   });
7894                 });
7895
7896                 if (init && init.signal) {
7897                   // Never pass .signal to the native implementation when the polyfill has
7898                   // been installed because if we're running on top of a browser with a
7899                   // working native AbortController (i.e. the polyfill was installed due to
7900                   // __FORCE_INSTALL_ABORTCONTROLLER_POLYFILL being set), then passing our
7901                   // fake AbortSignal to the native fetch will trigger:
7902                   // TypeError: Failed to execute 'fetch' on 'Window': member signal is not of type AbortSignal.
7903                   delete init.signal;
7904                 } // Return the fastest promise (don't need to wait for request to finish)
7905
7906
7907                 return Promise.race([cancellation, realFetch(input, init)]);
7908               }
7909
7910               return realFetch(input, init);
7911             };
7912
7913             return {
7914               fetch: abortableFetch,
7915               Request: Request
7916             };
7917           }
7918
7919           (function (self) {
7920             if (!polyfillNeeded(self)) {
7921               return;
7922             }
7923
7924             if (!self.fetch) {
7925               console.warn('fetch() is not available, cannot install abortcontroller-polyfill');
7926               return;
7927             }
7928
7929             var _abortableFetch = abortableFetchDecorator(self),
7930                 fetch = _abortableFetch.fetch,
7931                 Request = _abortableFetch.Request;
7932
7933             self.fetch = fetch;
7934             self.Request = Request;
7935             Object.defineProperty(self, 'AbortController', {
7936               writable: true,
7937               enumerable: false,
7938               configurable: true,
7939               value: AbortController
7940             });
7941             Object.defineProperty(self, 'AbortSignal', {
7942               writable: true,
7943               enumerable: false,
7944               configurable: true,
7945               value: AbortSignal
7946             });
7947           })(typeof self !== 'undefined' ? self : commonjsGlobal);
7948         });
7949
7950         function actionAddEntity(way) {
7951           return function (graph) {
7952             return graph.replace(way);
7953           };
7954         }
7955
7956         var $$M = _export;
7957         var global$g = global$1o;
7958         var fails$k = fails$V;
7959         var isArray$3 = isArray$8;
7960         var isObject$8 = isObject$s;
7961         var toObject$6 = toObject$i;
7962         var lengthOfArrayLike$4 = lengthOfArrayLike$i;
7963         var createProperty$1 = createProperty$5;
7964         var arraySpeciesCreate$1 = arraySpeciesCreate$4;
7965         var arrayMethodHasSpeciesSupport$1 = arrayMethodHasSpeciesSupport$5;
7966         var wellKnownSymbol$2 = wellKnownSymbol$t;
7967         var V8_VERSION = engineV8Version;
7968
7969         var IS_CONCAT_SPREADABLE = wellKnownSymbol$2('isConcatSpreadable');
7970         var MAX_SAFE_INTEGER = 0x1FFFFFFFFFFFFF;
7971         var MAXIMUM_ALLOWED_INDEX_EXCEEDED = 'Maximum allowed index exceeded';
7972         var TypeError$5 = global$g.TypeError;
7973
7974         // We can't use this feature detection in V8 since it causes
7975         // deoptimization and serious performance degradation
7976         // https://github.com/zloirock/core-js/issues/679
7977         var IS_CONCAT_SPREADABLE_SUPPORT = V8_VERSION >= 51 || !fails$k(function () {
7978           var array = [];
7979           array[IS_CONCAT_SPREADABLE] = false;
7980           return array.concat()[0] !== array;
7981         });
7982
7983         var SPECIES_SUPPORT = arrayMethodHasSpeciesSupport$1('concat');
7984
7985         var isConcatSpreadable = function (O) {
7986           if (!isObject$8(O)) return false;
7987           var spreadable = O[IS_CONCAT_SPREADABLE];
7988           return spreadable !== undefined ? !!spreadable : isArray$3(O);
7989         };
7990
7991         var FORCED$a = !IS_CONCAT_SPREADABLE_SUPPORT || !SPECIES_SUPPORT;
7992
7993         // `Array.prototype.concat` method
7994         // https://tc39.es/ecma262/#sec-array.prototype.concat
7995         // with adding support of @@isConcatSpreadable and @@species
7996         $$M({ target: 'Array', proto: true, forced: FORCED$a }, {
7997           // eslint-disable-next-line no-unused-vars -- required for `.length`
7998           concat: function concat(arg) {
7999             var O = toObject$6(this);
8000             var A = arraySpeciesCreate$1(O, 0);
8001             var n = 0;
8002             var i, k, length, len, E;
8003             for (i = -1, length = arguments.length; i < length; i++) {
8004               E = i === -1 ? O : arguments[i];
8005               if (isConcatSpreadable(E)) {
8006                 len = lengthOfArrayLike$4(E);
8007                 if (n + len > MAX_SAFE_INTEGER) throw TypeError$5(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
8008                 for (k = 0; k < len; k++, n++) if (k in E) createProperty$1(A, n, E[k]);
8009               } else {
8010                 if (n >= MAX_SAFE_INTEGER) throw TypeError$5(MAXIMUM_ALLOWED_INDEX_EXCEEDED);
8011                 createProperty$1(A, n++, E);
8012               }
8013             }
8014             A.length = n;
8015             return A;
8016           }
8017         });
8018
8019         var DESCRIPTORS$7 = descriptors;
8020         var uncurryThis$l = functionUncurryThis;
8021         var call$4 = functionCall;
8022         var fails$j = fails$V;
8023         var objectKeys$1 = objectKeys$4;
8024         var getOwnPropertySymbolsModule = objectGetOwnPropertySymbols;
8025         var propertyIsEnumerableModule = objectPropertyIsEnumerable;
8026         var toObject$5 = toObject$i;
8027         var IndexedObject = indexedObject;
8028
8029         // eslint-disable-next-line es/no-object-assign -- safe
8030         var $assign = Object.assign;
8031         // eslint-disable-next-line es/no-object-defineproperty -- required for testing
8032         var defineProperty$4 = Object.defineProperty;
8033         var concat = uncurryThis$l([].concat);
8034
8035         // `Object.assign` method
8036         // https://tc39.es/ecma262/#sec-object.assign
8037         var objectAssign = !$assign || fails$j(function () {
8038           // should have correct order of operations (Edge bug)
8039           if (DESCRIPTORS$7 && $assign({ b: 1 }, $assign(defineProperty$4({}, 'a', {
8040             enumerable: true,
8041             get: function () {
8042               defineProperty$4(this, 'b', {
8043                 value: 3,
8044                 enumerable: false
8045               });
8046             }
8047           }), { b: 2 })).b !== 1) return true;
8048           // should work with symbols and should have deterministic property order (V8 bug)
8049           var A = {};
8050           var B = {};
8051           // eslint-disable-next-line es/no-symbol -- safe
8052           var symbol = Symbol();
8053           var alphabet = 'abcdefghijklmnopqrst';
8054           A[symbol] = 7;
8055           alphabet.split('').forEach(function (chr) { B[chr] = chr; });
8056           return $assign({}, A)[symbol] != 7 || objectKeys$1($assign({}, B)).join('') != alphabet;
8057         }) ? function assign(target, source) { // eslint-disable-line no-unused-vars -- required for `.length`
8058           var T = toObject$5(target);
8059           var argumentsLength = arguments.length;
8060           var index = 1;
8061           var getOwnPropertySymbols = getOwnPropertySymbolsModule.f;
8062           var propertyIsEnumerable = propertyIsEnumerableModule.f;
8063           while (argumentsLength > index) {
8064             var S = IndexedObject(arguments[index++]);
8065             var keys = getOwnPropertySymbols ? concat(objectKeys$1(S), getOwnPropertySymbols(S)) : objectKeys$1(S);
8066             var length = keys.length;
8067             var j = 0;
8068             var key;
8069             while (length > j) {
8070               key = keys[j++];
8071               if (!DESCRIPTORS$7 || call$4(propertyIsEnumerable, S, key)) T[key] = S[key];
8072             }
8073           } return T;
8074         } : $assign;
8075
8076         var $$L = _export;
8077         var assign$2 = objectAssign;
8078
8079         // `Object.assign` method
8080         // https://tc39.es/ecma262/#sec-object.assign
8081         // eslint-disable-next-line es/no-object-assign -- required for testing
8082         $$L({ target: 'Object', stat: true, forced: Object.assign !== assign$2 }, {
8083           assign: assign$2
8084         });
8085
8086         var $$K = _export;
8087         var $filter = arrayIteration.filter;
8088         var arrayMethodHasSpeciesSupport = arrayMethodHasSpeciesSupport$5;
8089
8090         var HAS_SPECIES_SUPPORT = arrayMethodHasSpeciesSupport('filter');
8091
8092         // `Array.prototype.filter` method
8093         // https://tc39.es/ecma262/#sec-array.prototype.filter
8094         // with adding support of @@species
8095         $$K({ target: 'Array', proto: true, forced: !HAS_SPECIES_SUPPORT }, {
8096           filter: function filter(callbackfn /* , thisArg */) {
8097             return $filter(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
8098           }
8099         });
8100
8101         var $$J = _export;
8102         var toObject$4 = toObject$i;
8103         var nativeKeys = objectKeys$4;
8104         var fails$i = fails$V;
8105
8106         var FAILS_ON_PRIMITIVES$2 = fails$i(function () { nativeKeys(1); });
8107
8108         // `Object.keys` method
8109         // https://tc39.es/ecma262/#sec-object.keys
8110         $$J({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES$2 }, {
8111           keys: function keys(it) {
8112             return nativeKeys(toObject$4(it));
8113           }
8114         });
8115
8116         var $$I = _export;
8117         var uncurryThis$k = functionUncurryThis;
8118         var isArray$2 = isArray$8;
8119
8120         var un$Reverse = uncurryThis$k([].reverse);
8121         var test$1 = [1, 2];
8122
8123         // `Array.prototype.reverse` method
8124         // https://tc39.es/ecma262/#sec-array.prototype.reverse
8125         // fix for Safari 12.0 bug
8126         // https://bugs.webkit.org/show_bug.cgi?id=188794
8127         $$I({ target: 'Array', proto: true, forced: String(test$1) === String(test$1.reverse()) }, {
8128           reverse: function reverse() {
8129             // eslint-disable-next-line no-self-assign -- dirty hack
8130             if (isArray$2(this)) this.length = this.length;
8131             return un$Reverse(this);
8132           }
8133         });
8134
8135         var global$f = global$1o;
8136         var fails$h = fails$V;
8137         var uncurryThis$j = functionUncurryThis;
8138         var toString$c = toString$k;
8139         var trim$4 = stringTrim.trim;
8140         var whitespaces$1 = whitespaces$4;
8141
8142         var charAt$2 = uncurryThis$j(''.charAt);
8143         var n$ParseFloat = global$f.parseFloat;
8144         var Symbol$2 = global$f.Symbol;
8145         var ITERATOR$1 = Symbol$2 && Symbol$2.iterator;
8146         var FORCED$9 = 1 / n$ParseFloat(whitespaces$1 + '-0') !== -Infinity
8147           // MS Edge 18- broken with boxed symbols
8148           || (ITERATOR$1 && !fails$h(function () { n$ParseFloat(Object(ITERATOR$1)); }));
8149
8150         // `parseFloat` method
8151         // https://tc39.es/ecma262/#sec-parsefloat-string
8152         var numberParseFloat = FORCED$9 ? function parseFloat(string) {
8153           var trimmedString = trim$4(toString$c(string));
8154           var result = n$ParseFloat(trimmedString);
8155           return result === 0 && charAt$2(trimmedString, 0) == '-' ? -0 : result;
8156         } : n$ParseFloat;
8157
8158         var $$H = _export;
8159         var $parseFloat = numberParseFloat;
8160
8161         // `parseFloat` method
8162         // https://tc39.es/ecma262/#sec-parsefloat-string
8163         $$H({ global: true, forced: parseFloat != $parseFloat }, {
8164           parseFloat: $parseFloat
8165         });
8166
8167         /*
8168         Order the nodes of a way in reverse order and reverse any direction dependent tags
8169         other than `oneway`. (We assume that correcting a backwards oneway is the primary
8170         reason for reversing a way.)
8171
8172         In addition, numeric-valued `incline` tags are negated.
8173
8174         The JOSM implementation was used as a guide, but transformations that were of unclear benefit
8175         or adjusted tags that don't seem to be used in practice were omitted.
8176
8177         References:
8178             http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
8179             http://wiki.openstreetmap.org/wiki/Key:direction#Steps
8180             http://wiki.openstreetmap.org/wiki/Key:incline
8181             http://wiki.openstreetmap.org/wiki/Route#Members
8182             http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
8183             http://wiki.openstreetmap.org/wiki/Tag:highway%3Dstop
8184             http://wiki.openstreetmap.org/wiki/Key:traffic_sign#On_a_way_or_area
8185         */
8186         function actionReverse(entityID, options) {
8187           var ignoreKey = /^.*(_|:)?(description|name|note|website|ref|source|comment|watch|attribution)(_|:)?/;
8188           var numeric = /^([+\-]?)(?=[\d.])/;
8189           var directionKey = /direction$/;
8190           var turn_lanes = /^turn:lanes:?/;
8191           var keyReplacements = [[/:right$/, ':left'], [/:left$/, ':right'], [/:forward$/, ':backward'], [/:backward$/, ':forward'], [/:right:/, ':left:'], [/:left:/, ':right:'], [/:forward:/, ':backward:'], [/:backward:/, ':forward:']];
8192           var valueReplacements = {
8193             left: 'right',
8194             right: 'left',
8195             up: 'down',
8196             down: 'up',
8197             forward: 'backward',
8198             backward: 'forward',
8199             forwards: 'backward',
8200             backwards: 'forward'
8201           };
8202           var roleReplacements = {
8203             forward: 'backward',
8204             backward: 'forward',
8205             forwards: 'backward',
8206             backwards: 'forward'
8207           };
8208           var onewayReplacements = {
8209             yes: '-1',
8210             '1': '-1',
8211             '-1': 'yes'
8212           };
8213           var compassReplacements = {
8214             N: 'S',
8215             NNE: 'SSW',
8216             NE: 'SW',
8217             ENE: 'WSW',
8218             E: 'W',
8219             ESE: 'WNW',
8220             SE: 'NW',
8221             SSE: 'NNW',
8222             S: 'N',
8223             SSW: 'NNE',
8224             SW: 'NE',
8225             WSW: 'ENE',
8226             W: 'E',
8227             WNW: 'ESE',
8228             NW: 'SE',
8229             NNW: 'SSE'
8230           };
8231
8232           function reverseKey(key) {
8233             for (var i = 0; i < keyReplacements.length; ++i) {
8234               var replacement = keyReplacements[i];
8235
8236               if (replacement[0].test(key)) {
8237                 return key.replace(replacement[0], replacement[1]);
8238               }
8239             }
8240
8241             return key;
8242           }
8243
8244           function reverseValue(key, value, includeAbsolute) {
8245             if (ignoreKey.test(key)) return value; // Turn lanes are left/right to key (not way) direction - #5674
8246
8247             if (turn_lanes.test(key)) {
8248               return value;
8249             } else if (key === 'incline' && numeric.test(value)) {
8250               return value.replace(numeric, function (_, sign) {
8251                 return sign === '-' ? '' : '-';
8252               });
8253             } else if (options && options.reverseOneway && key === 'oneway') {
8254               return onewayReplacements[value] || value;
8255             } else if (includeAbsolute && directionKey.test(key)) {
8256               if (compassReplacements[value]) return compassReplacements[value];
8257               var degrees = parseFloat(value);
8258
8259               if (typeof degrees === 'number' && !isNaN(degrees)) {
8260                 if (degrees < 180) {
8261                   degrees += 180;
8262                 } else {
8263                   degrees -= 180;
8264                 }
8265
8266                 return degrees.toString();
8267               }
8268             }
8269
8270             return valueReplacements[value] || value;
8271           } // Reverse the direction of tags attached to the nodes - #3076
8272
8273
8274           function reverseNodeTags(graph, nodeIDs) {
8275             for (var i = 0; i < nodeIDs.length; i++) {
8276               var node = graph.hasEntity(nodeIDs[i]);
8277               if (!node || !Object.keys(node.tags).length) continue;
8278               var tags = {};
8279
8280               for (var key in node.tags) {
8281                 tags[reverseKey(key)] = reverseValue(key, node.tags[key], node.id === entityID);
8282               }
8283
8284               graph = graph.replace(node.update({
8285                 tags: tags
8286               }));
8287             }
8288
8289             return graph;
8290           }
8291
8292           function reverseWay(graph, way) {
8293             var nodes = way.nodes.slice().reverse();
8294             var tags = {};
8295             var role;
8296
8297             for (var key in way.tags) {
8298               tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
8299             }
8300
8301             graph.parentRelations(way).forEach(function (relation) {
8302               relation.members.forEach(function (member, index) {
8303                 if (member.id === way.id && (role = roleReplacements[member.role])) {
8304                   relation = relation.updateMember({
8305                     role: role
8306                   }, index);
8307                   graph = graph.replace(relation);
8308                 }
8309               });
8310             }); // Reverse any associated directions on nodes on the way and then replace
8311             // the way itself with the reversed node ids and updated way tags
8312
8313             return reverseNodeTags(graph, nodes).replace(way.update({
8314               nodes: nodes,
8315               tags: tags
8316             }));
8317           }
8318
8319           var action = function action(graph) {
8320             var entity = graph.entity(entityID);
8321
8322             if (entity.type === 'way') {
8323               return reverseWay(graph, entity);
8324             }
8325
8326             return reverseNodeTags(graph, [entityID]);
8327           };
8328
8329           action.disabled = function (graph) {
8330             var entity = graph.hasEntity(entityID);
8331             if (!entity || entity.type === 'way') return false;
8332
8333             for (var key in entity.tags) {
8334               var value = entity.tags[key];
8335
8336               if (reverseKey(key) !== key || reverseValue(key, value, true) !== value) {
8337                 return false;
8338               }
8339             }
8340
8341             return 'nondirectional_node';
8342           };
8343
8344           action.entityID = function () {
8345             return entityID;
8346           };
8347
8348           return action;
8349         }
8350
8351         function osmIsInterestingTag(key) {
8352           return key !== 'attribution' && key !== 'created_by' && key !== 'source' && key !== 'odbl' && key.indexOf('source:') !== 0 && key.indexOf('source_ref') !== 0 && // purposely exclude colon
8353           key.indexOf('tiger:') !== 0;
8354         }
8355         var osmAreaKeys = {};
8356         function osmSetAreaKeys(value) {
8357           osmAreaKeys = value;
8358         } // returns an object with the tag from `tags` that implies an area geometry, if any
8359
8360         function osmTagSuggestingArea(tags) {
8361           if (tags.area === 'yes') return {
8362             area: 'yes'
8363           };
8364           if (tags.area === 'no') return null; // `highway` and `railway` are typically linear features, but there
8365           // are a few exceptions that should be treated as areas, even in the
8366           // absence of a proper `area=yes` or `areaKeys` tag.. see #4194
8367
8368           var lineKeys = {
8369             highway: {
8370               rest_area: true,
8371               services: true
8372             },
8373             railway: {
8374               roundhouse: true,
8375               station: true,
8376               traverser: true,
8377               turntable: true,
8378               wash: true
8379             }
8380           };
8381           var returnTags = {};
8382
8383           for (var key in tags) {
8384             if (key in osmAreaKeys && !(tags[key] in osmAreaKeys[key])) {
8385               returnTags[key] = tags[key];
8386               return returnTags;
8387             }
8388
8389             if (key in lineKeys && tags[key] in lineKeys[key]) {
8390               returnTags[key] = tags[key];
8391               return returnTags;
8392             }
8393           }
8394
8395           return null;
8396         } // Tags that indicate a node can be a standalone point
8397         // e.g. { amenity: { bar: true, parking: true, ... } ... }
8398
8399         var osmPointTags = {};
8400         function osmSetPointTags(value) {
8401           osmPointTags = value;
8402         } // Tags that indicate a node can be part of a way
8403         // e.g. { amenity: { parking: true, ... }, highway: { stop: true ... } ... }
8404
8405         var osmVertexTags = {};
8406         function osmSetVertexTags(value) {
8407           osmVertexTags = value;
8408         }
8409         function osmNodeGeometriesForTags(nodeTags) {
8410           var geometries = {};
8411
8412           for (var key in nodeTags) {
8413             if (osmPointTags[key] && (osmPointTags[key]['*'] || osmPointTags[key][nodeTags[key]])) {
8414               geometries.point = true;
8415             }
8416
8417             if (osmVertexTags[key] && (osmVertexTags[key]['*'] || osmVertexTags[key][nodeTags[key]])) {
8418               geometries.vertex = true;
8419             } // break early if both are already supported
8420
8421
8422             if (geometries.point && geometries.vertex) break;
8423           }
8424
8425           return geometries;
8426         }
8427         var osmOneWayTags = {
8428           'aerialway': {
8429             'chair_lift': true,
8430             'drag_lift': true,
8431             'j-bar': true,
8432             'magic_carpet': true,
8433             'mixed_lift': true,
8434             'platter': true,
8435             'rope_tow': true,
8436             't-bar': true,
8437             'zip_line': true
8438           },
8439           'highway': {
8440             'motorway': true
8441           },
8442           'junction': {
8443             'circular': true,
8444             'roundabout': true
8445           },
8446           'man_made': {
8447             'goods_conveyor': true,
8448             'piste:halfpipe': true
8449           },
8450           'piste:type': {
8451             'downhill': true,
8452             'sled': true,
8453             'yes': true
8454           },
8455           'seamark:type': {
8456             'separation_lane': true,
8457             'separation_roundabout': true
8458           },
8459           'waterway': {
8460             'canal': true,
8461             'ditch': true,
8462             'drain': true,
8463             'fish_pass': true,
8464             'river': true,
8465             'stream': true,
8466             'tidal_channel': true
8467           }
8468         }; // solid and smooth surfaces akin to the assumed default road surface in OSM
8469
8470         var osmPavedTags = {
8471           'surface': {
8472             'paved': true,
8473             'asphalt': true,
8474             'concrete': true,
8475             'concrete:lanes': true,
8476             'concrete:plates': true
8477           },
8478           'tracktype': {
8479             'grade1': true
8480           }
8481         }; // solid, if somewhat uncommon surfaces with a high range of smoothness
8482
8483         var osmSemipavedTags = {
8484           'surface': {
8485             'cobblestone': true,
8486             'cobblestone:flattened': true,
8487             'unhewn_cobblestone': true,
8488             'sett': true,
8489             'paving_stones': true,
8490             'metal': true,
8491             'wood': true
8492           }
8493         };
8494         var osmRightSideIsInsideTags = {
8495           'natural': {
8496             'cliff': true,
8497             'coastline': 'coastline'
8498           },
8499           'barrier': {
8500             'retaining_wall': true,
8501             'kerb': true,
8502             'guard_rail': true,
8503             'city_wall': true
8504           },
8505           'man_made': {
8506             'embankment': true
8507           },
8508           'waterway': {
8509             'weir': true
8510           }
8511         }; // "highway" tag values for pedestrian or vehicle right-of-ways that make up the routable network
8512         // (does not include `raceway`)
8513
8514         var osmRoutableHighwayTagValues = {
8515           motorway: true,
8516           trunk: true,
8517           primary: true,
8518           secondary: true,
8519           tertiary: true,
8520           residential: true,
8521           motorway_link: true,
8522           trunk_link: true,
8523           primary_link: true,
8524           secondary_link: true,
8525           tertiary_link: true,
8526           unclassified: true,
8527           road: true,
8528           service: true,
8529           track: true,
8530           living_street: true,
8531           bus_guideway: true,
8532           path: true,
8533           footway: true,
8534           cycleway: true,
8535           bridleway: true,
8536           pedestrian: true,
8537           corridor: true,
8538           steps: true
8539         }; // "highway" tag values that generally do not allow motor vehicles
8540
8541         var osmPathHighwayTagValues = {
8542           path: true,
8543           footway: true,
8544           cycleway: true,
8545           bridleway: true,
8546           pedestrian: true,
8547           corridor: true,
8548           steps: true
8549         }; // "railway" tag values representing existing railroad tracks (purposely does not include 'abandoned')
8550
8551         var osmRailwayTrackTagValues = {
8552           rail: true,
8553           light_rail: true,
8554           tram: true,
8555           subway: true,
8556           monorail: true,
8557           funicular: true,
8558           miniature: true,
8559           narrow_gauge: true,
8560           disused: true,
8561           preserved: true
8562         }; // "waterway" tag values for line features representing water flow
8563
8564         var osmFlowingWaterwayTagValues = {
8565           canal: true,
8566           ditch: true,
8567           drain: true,
8568           fish_pass: true,
8569           river: true,
8570           stream: true,
8571           tidal_channel: true
8572         };
8573
8574         var global$e = global$1o;
8575         var fails$g = fails$V;
8576         var uncurryThis$i = functionUncurryThis;
8577         var toString$b = toString$k;
8578         var trim$3 = stringTrim.trim;
8579         var whitespaces = whitespaces$4;
8580
8581         var $parseInt$1 = global$e.parseInt;
8582         var Symbol$1 = global$e.Symbol;
8583         var ITERATOR = Symbol$1 && Symbol$1.iterator;
8584         var hex$2 = /^[+-]?0x/i;
8585         var exec$3 = uncurryThis$i(hex$2.exec);
8586         var FORCED$8 = $parseInt$1(whitespaces + '08') !== 8 || $parseInt$1(whitespaces + '0x16') !== 22
8587           // MS Edge 18- broken with boxed symbols
8588           || (ITERATOR && !fails$g(function () { $parseInt$1(Object(ITERATOR)); }));
8589
8590         // `parseInt` method
8591         // https://tc39.es/ecma262/#sec-parseint-string-radix
8592         var numberParseInt = FORCED$8 ? function parseInt(string, radix) {
8593           var S = trim$3(toString$b(string));
8594           return $parseInt$1(S, (radix >>> 0) || (exec$3(hex$2, S) ? 16 : 10));
8595         } : $parseInt$1;
8596
8597         var $$G = _export;
8598         var $parseInt = numberParseInt;
8599
8600         // `parseInt` method
8601         // https://tc39.es/ecma262/#sec-parseint-string-radix
8602         $$G({ global: true, forced: parseInt != $parseInt }, {
8603           parseInt: $parseInt
8604         });
8605
8606         var internalMetadata = {exports: {}};
8607
8608         // FF26- bug: ArrayBuffers are non-extensible, but Object.isExtensible does not report it
8609         var fails$f = fails$V;
8610
8611         var arrayBufferNonExtensible = fails$f(function () {
8612           if (typeof ArrayBuffer == 'function') {
8613             var buffer = new ArrayBuffer(8);
8614             // eslint-disable-next-line es/no-object-isextensible, es/no-object-defineproperty -- safe
8615             if (Object.isExtensible(buffer)) Object.defineProperty(buffer, 'a', { value: 8 });
8616           }
8617         });
8618
8619         var fails$e = fails$V;
8620         var isObject$7 = isObject$s;
8621         var classof = classofRaw$1;
8622         var ARRAY_BUFFER_NON_EXTENSIBLE = arrayBufferNonExtensible;
8623
8624         // eslint-disable-next-line es/no-object-isextensible -- safe
8625         var $isExtensible = Object.isExtensible;
8626         var FAILS_ON_PRIMITIVES$1 = fails$e(function () { $isExtensible(1); });
8627
8628         // `Object.isExtensible` method
8629         // https://tc39.es/ecma262/#sec-object.isextensible
8630         var objectIsExtensible = (FAILS_ON_PRIMITIVES$1 || ARRAY_BUFFER_NON_EXTENSIBLE) ? function isExtensible(it) {
8631           if (!isObject$7(it)) return false;
8632           if (ARRAY_BUFFER_NON_EXTENSIBLE && classof(it) == 'ArrayBuffer') return false;
8633           return $isExtensible ? $isExtensible(it) : true;
8634         } : $isExtensible;
8635
8636         var fails$d = fails$V;
8637
8638         var freezing = !fails$d(function () {
8639           // eslint-disable-next-line es/no-object-isextensible, es/no-object-preventextensions -- required for testing
8640           return Object.isExtensible(Object.preventExtensions({}));
8641         });
8642
8643         var $$F = _export;
8644         var uncurryThis$h = functionUncurryThis;
8645         var hiddenKeys = hiddenKeys$6;
8646         var isObject$6 = isObject$s;
8647         var hasOwn$3 = hasOwnProperty_1;
8648         var defineProperty$3 = objectDefineProperty.f;
8649         var getOwnPropertyNamesModule = objectGetOwnPropertyNames;
8650         var getOwnPropertyNamesExternalModule = objectGetOwnPropertyNamesExternal;
8651         var isExtensible = objectIsExtensible;
8652         var uid = uid$5;
8653         var FREEZING$1 = freezing;
8654
8655         var REQUIRED = false;
8656         var METADATA = uid('meta');
8657         var id$1 = 0;
8658
8659         var setMetadata = function (it) {
8660           defineProperty$3(it, METADATA, { value: {
8661             objectID: 'O' + id$1++, // object ID
8662             weakData: {}          // weak collections IDs
8663           } });
8664         };
8665
8666         var fastKey$1 = function (it, create) {
8667           // return a primitive with prefix
8668           if (!isObject$6(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
8669           if (!hasOwn$3(it, METADATA)) {
8670             // can't set metadata to uncaught frozen object
8671             if (!isExtensible(it)) return 'F';
8672             // not necessary to add metadata
8673             if (!create) return 'E';
8674             // add missing metadata
8675             setMetadata(it);
8676           // return object ID
8677           } return it[METADATA].objectID;
8678         };
8679
8680         var getWeakData = function (it, create) {
8681           if (!hasOwn$3(it, METADATA)) {
8682             // can't set metadata to uncaught frozen object
8683             if (!isExtensible(it)) return true;
8684             // not necessary to add metadata
8685             if (!create) return false;
8686             // add missing metadata
8687             setMetadata(it);
8688           // return the store of weak collections IDs
8689           } return it[METADATA].weakData;
8690         };
8691
8692         // add metadata on freeze-family methods calling
8693         var onFreeze$1 = function (it) {
8694           if (FREEZING$1 && REQUIRED && isExtensible(it) && !hasOwn$3(it, METADATA)) setMetadata(it);
8695           return it;
8696         };
8697
8698         var enable = function () {
8699           meta.enable = function () { /* empty */ };
8700           REQUIRED = true;
8701           var getOwnPropertyNames = getOwnPropertyNamesModule.f;
8702           var splice = uncurryThis$h([].splice);
8703           var test = {};
8704           test[METADATA] = 1;
8705
8706           // prevent exposing of metadata key
8707           if (getOwnPropertyNames(test).length) {
8708             getOwnPropertyNamesModule.f = function (it) {
8709               var result = getOwnPropertyNames(it);
8710               for (var i = 0, length = result.length; i < length; i++) {
8711                 if (result[i] === METADATA) {
8712                   splice(result, i, 1);
8713                   break;
8714                 }
8715               } return result;
8716             };
8717
8718             $$F({ target: 'Object', stat: true, forced: true }, {
8719               getOwnPropertyNames: getOwnPropertyNamesExternalModule.f
8720             });
8721           }
8722         };
8723
8724         var meta = internalMetadata.exports = {
8725           enable: enable,
8726           fastKey: fastKey$1,
8727           getWeakData: getWeakData,
8728           onFreeze: onFreeze$1
8729         };
8730
8731         hiddenKeys[METADATA] = true;
8732
8733         var $$E = _export;
8734         var global$d = global$1o;
8735         var uncurryThis$g = functionUncurryThis;
8736         var isForced$2 = isForced_1;
8737         var redefine$4 = redefine$h.exports;
8738         var InternalMetadataModule = internalMetadata.exports;
8739         var iterate$1 = iterate$3;
8740         var anInstance$2 = anInstance$7;
8741         var isCallable$1 = isCallable$r;
8742         var isObject$5 = isObject$s;
8743         var fails$c = fails$V;
8744         var checkCorrectnessOfIteration$1 = checkCorrectnessOfIteration$4;
8745         var setToStringTag$1 = setToStringTag$a;
8746         var inheritIfRequired$2 = inheritIfRequired$4;
8747
8748         var collection$2 = function (CONSTRUCTOR_NAME, wrapper, common) {
8749           var IS_MAP = CONSTRUCTOR_NAME.indexOf('Map') !== -1;
8750           var IS_WEAK = CONSTRUCTOR_NAME.indexOf('Weak') !== -1;
8751           var ADDER = IS_MAP ? 'set' : 'add';
8752           var NativeConstructor = global$d[CONSTRUCTOR_NAME];
8753           var NativePrototype = NativeConstructor && NativeConstructor.prototype;
8754           var Constructor = NativeConstructor;
8755           var exported = {};
8756
8757           var fixMethod = function (KEY) {
8758             var uncurriedNativeMethod = uncurryThis$g(NativePrototype[KEY]);
8759             redefine$4(NativePrototype, KEY,
8760               KEY == 'add' ? function add(value) {
8761                 uncurriedNativeMethod(this, value === 0 ? 0 : value);
8762                 return this;
8763               } : KEY == 'delete' ? function (key) {
8764                 return IS_WEAK && !isObject$5(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
8765               } : KEY == 'get' ? function get(key) {
8766                 return IS_WEAK && !isObject$5(key) ? undefined : uncurriedNativeMethod(this, key === 0 ? 0 : key);
8767               } : KEY == 'has' ? function has(key) {
8768                 return IS_WEAK && !isObject$5(key) ? false : uncurriedNativeMethod(this, key === 0 ? 0 : key);
8769               } : function set(key, value) {
8770                 uncurriedNativeMethod(this, key === 0 ? 0 : key, value);
8771                 return this;
8772               }
8773             );
8774           };
8775
8776           var REPLACE = isForced$2(
8777             CONSTRUCTOR_NAME,
8778             !isCallable$1(NativeConstructor) || !(IS_WEAK || NativePrototype.forEach && !fails$c(function () {
8779               new NativeConstructor().entries().next();
8780             }))
8781           );
8782
8783           if (REPLACE) {
8784             // create collection constructor
8785             Constructor = common.getConstructor(wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER);
8786             InternalMetadataModule.enable();
8787           } else if (isForced$2(CONSTRUCTOR_NAME, true)) {
8788             var instance = new Constructor();
8789             // early implementations not supports chaining
8790             var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
8791             // V8 ~ Chromium 40- weak-collections throws on primitives, but should return false
8792             var THROWS_ON_PRIMITIVES = fails$c(function () { instance.has(1); });
8793             // most early implementations doesn't supports iterables, most modern - not close it correctly
8794             // eslint-disable-next-line no-new -- required for testing
8795             var ACCEPT_ITERABLES = checkCorrectnessOfIteration$1(function (iterable) { new NativeConstructor(iterable); });
8796             // for early implementations -0 and +0 not the same
8797             var BUGGY_ZERO = !IS_WEAK && fails$c(function () {
8798               // V8 ~ Chromium 42- fails only with 5+ elements
8799               var $instance = new NativeConstructor();
8800               var index = 5;
8801               while (index--) $instance[ADDER](index, index);
8802               return !$instance.has(-0);
8803             });
8804
8805             if (!ACCEPT_ITERABLES) {
8806               Constructor = wrapper(function (dummy, iterable) {
8807                 anInstance$2(dummy, NativePrototype);
8808                 var that = inheritIfRequired$2(new NativeConstructor(), dummy, Constructor);
8809                 if (iterable != undefined) iterate$1(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
8810                 return that;
8811               });
8812               Constructor.prototype = NativePrototype;
8813               NativePrototype.constructor = Constructor;
8814             }
8815
8816             if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
8817               fixMethod('delete');
8818               fixMethod('has');
8819               IS_MAP && fixMethod('get');
8820             }
8821
8822             if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
8823
8824             // weak collections should not contains .clear method
8825             if (IS_WEAK && NativePrototype.clear) delete NativePrototype.clear;
8826           }
8827
8828           exported[CONSTRUCTOR_NAME] = Constructor;
8829           $$E({ global: true, forced: Constructor != NativeConstructor }, exported);
8830
8831           setToStringTag$1(Constructor, CONSTRUCTOR_NAME);
8832
8833           if (!IS_WEAK) common.setStrong(Constructor, CONSTRUCTOR_NAME, IS_MAP);
8834
8835           return Constructor;
8836         };
8837
8838         var defineProperty$2 = objectDefineProperty.f;
8839         var create$3 = objectCreate;
8840         var redefineAll = redefineAll$4;
8841         var bind$6 = functionBindContext;
8842         var anInstance$1 = anInstance$7;
8843         var iterate = iterate$3;
8844         var defineIterator = defineIterator$3;
8845         var setSpecies$1 = setSpecies$5;
8846         var DESCRIPTORS$6 = descriptors;
8847         var fastKey = internalMetadata.exports.fastKey;
8848         var InternalStateModule$1 = internalState;
8849
8850         var setInternalState$1 = InternalStateModule$1.set;
8851         var internalStateGetterFor = InternalStateModule$1.getterFor;
8852
8853         var collectionStrong$2 = {
8854           getConstructor: function (wrapper, CONSTRUCTOR_NAME, IS_MAP, ADDER) {
8855             var Constructor = wrapper(function (that, iterable) {
8856               anInstance$1(that, Prototype);
8857               setInternalState$1(that, {
8858                 type: CONSTRUCTOR_NAME,
8859                 index: create$3(null),
8860                 first: undefined,
8861                 last: undefined,
8862                 size: 0
8863               });
8864               if (!DESCRIPTORS$6) that.size = 0;
8865               if (iterable != undefined) iterate(iterable, that[ADDER], { that: that, AS_ENTRIES: IS_MAP });
8866             });
8867
8868             var Prototype = Constructor.prototype;
8869
8870             var getInternalState = internalStateGetterFor(CONSTRUCTOR_NAME);
8871
8872             var define = function (that, key, value) {
8873               var state = getInternalState(that);
8874               var entry = getEntry(that, key);
8875               var previous, index;
8876               // change existing entry
8877               if (entry) {
8878                 entry.value = value;
8879               // create new entry
8880               } else {
8881                 state.last = entry = {
8882                   index: index = fastKey(key, true),
8883                   key: key,
8884                   value: value,
8885                   previous: previous = state.last,
8886                   next: undefined,
8887                   removed: false
8888                 };
8889                 if (!state.first) state.first = entry;
8890                 if (previous) previous.next = entry;
8891                 if (DESCRIPTORS$6) state.size++;
8892                 else that.size++;
8893                 // add to index
8894                 if (index !== 'F') state.index[index] = entry;
8895               } return that;
8896             };
8897
8898             var getEntry = function (that, key) {
8899               var state = getInternalState(that);
8900               // fast case
8901               var index = fastKey(key);
8902               var entry;
8903               if (index !== 'F') return state.index[index];
8904               // frozen object case
8905               for (entry = state.first; entry; entry = entry.next) {
8906                 if (entry.key == key) return entry;
8907               }
8908             };
8909
8910             redefineAll(Prototype, {
8911               // `{ Map, Set }.prototype.clear()` methods
8912               // https://tc39.es/ecma262/#sec-map.prototype.clear
8913               // https://tc39.es/ecma262/#sec-set.prototype.clear
8914               clear: function clear() {
8915                 var that = this;
8916                 var state = getInternalState(that);
8917                 var data = state.index;
8918                 var entry = state.first;
8919                 while (entry) {
8920                   entry.removed = true;
8921                   if (entry.previous) entry.previous = entry.previous.next = undefined;
8922                   delete data[entry.index];
8923                   entry = entry.next;
8924                 }
8925                 state.first = state.last = undefined;
8926                 if (DESCRIPTORS$6) state.size = 0;
8927                 else that.size = 0;
8928               },
8929               // `{ Map, Set }.prototype.delete(key)` methods
8930               // https://tc39.es/ecma262/#sec-map.prototype.delete
8931               // https://tc39.es/ecma262/#sec-set.prototype.delete
8932               'delete': function (key) {
8933                 var that = this;
8934                 var state = getInternalState(that);
8935                 var entry = getEntry(that, key);
8936                 if (entry) {
8937                   var next = entry.next;
8938                   var prev = entry.previous;
8939                   delete state.index[entry.index];
8940                   entry.removed = true;
8941                   if (prev) prev.next = next;
8942                   if (next) next.previous = prev;
8943                   if (state.first == entry) state.first = next;
8944                   if (state.last == entry) state.last = prev;
8945                   if (DESCRIPTORS$6) state.size--;
8946                   else that.size--;
8947                 } return !!entry;
8948               },
8949               // `{ Map, Set }.prototype.forEach(callbackfn, thisArg = undefined)` methods
8950               // https://tc39.es/ecma262/#sec-map.prototype.foreach
8951               // https://tc39.es/ecma262/#sec-set.prototype.foreach
8952               forEach: function forEach(callbackfn /* , that = undefined */) {
8953                 var state = getInternalState(this);
8954                 var boundFunction = bind$6(callbackfn, arguments.length > 1 ? arguments[1] : undefined);
8955                 var entry;
8956                 while (entry = entry ? entry.next : state.first) {
8957                   boundFunction(entry.value, entry.key, this);
8958                   // revert to the last existing entry
8959                   while (entry && entry.removed) entry = entry.previous;
8960                 }
8961               },
8962               // `{ Map, Set}.prototype.has(key)` methods
8963               // https://tc39.es/ecma262/#sec-map.prototype.has
8964               // https://tc39.es/ecma262/#sec-set.prototype.has
8965               has: function has(key) {
8966                 return !!getEntry(this, key);
8967               }
8968             });
8969
8970             redefineAll(Prototype, IS_MAP ? {
8971               // `Map.prototype.get(key)` method
8972               // https://tc39.es/ecma262/#sec-map.prototype.get
8973               get: function get(key) {
8974                 var entry = getEntry(this, key);
8975                 return entry && entry.value;
8976               },
8977               // `Map.prototype.set(key, value)` method
8978               // https://tc39.es/ecma262/#sec-map.prototype.set
8979               set: function set(key, value) {
8980                 return define(this, key === 0 ? 0 : key, value);
8981               }
8982             } : {
8983               // `Set.prototype.add(value)` method
8984               // https://tc39.es/ecma262/#sec-set.prototype.add
8985               add: function add(value) {
8986                 return define(this, value = value === 0 ? 0 : value, value);
8987               }
8988             });
8989             if (DESCRIPTORS$6) defineProperty$2(Prototype, 'size', {
8990               get: function () {
8991                 return getInternalState(this).size;
8992               }
8993             });
8994             return Constructor;
8995           },
8996           setStrong: function (Constructor, CONSTRUCTOR_NAME, IS_MAP) {
8997             var ITERATOR_NAME = CONSTRUCTOR_NAME + ' Iterator';
8998             var getInternalCollectionState = internalStateGetterFor(CONSTRUCTOR_NAME);
8999             var getInternalIteratorState = internalStateGetterFor(ITERATOR_NAME);
9000             // `{ Map, Set }.prototype.{ keys, values, entries, @@iterator }()` methods
9001             // https://tc39.es/ecma262/#sec-map.prototype.entries
9002             // https://tc39.es/ecma262/#sec-map.prototype.keys
9003             // https://tc39.es/ecma262/#sec-map.prototype.values
9004             // https://tc39.es/ecma262/#sec-map.prototype-@@iterator
9005             // https://tc39.es/ecma262/#sec-set.prototype.entries
9006             // https://tc39.es/ecma262/#sec-set.prototype.keys
9007             // https://tc39.es/ecma262/#sec-set.prototype.values
9008             // https://tc39.es/ecma262/#sec-set.prototype-@@iterator
9009             defineIterator(Constructor, CONSTRUCTOR_NAME, function (iterated, kind) {
9010               setInternalState$1(this, {
9011                 type: ITERATOR_NAME,
9012                 target: iterated,
9013                 state: getInternalCollectionState(iterated),
9014                 kind: kind,
9015                 last: undefined
9016               });
9017             }, function () {
9018               var state = getInternalIteratorState(this);
9019               var kind = state.kind;
9020               var entry = state.last;
9021               // revert to the last existing entry
9022               while (entry && entry.removed) entry = entry.previous;
9023               // get next entry
9024               if (!state.target || !(state.last = entry = entry ? entry.next : state.state.first)) {
9025                 // or finish the iteration
9026                 state.target = undefined;
9027                 return { value: undefined, done: true };
9028               }
9029               // return step by kind
9030               if (kind == 'keys') return { value: entry.key, done: false };
9031               if (kind == 'values') return { value: entry.value, done: false };
9032               return { value: [entry.key, entry.value], done: false };
9033             }, IS_MAP ? 'entries' : 'values', !IS_MAP, true);
9034
9035             // `{ Map, Set }.prototype[@@species]` accessors
9036             // https://tc39.es/ecma262/#sec-get-map-@@species
9037             // https://tc39.es/ecma262/#sec-get-set-@@species
9038             setSpecies$1(CONSTRUCTOR_NAME);
9039           }
9040         };
9041
9042         var collection$1 = collection$2;
9043         var collectionStrong$1 = collectionStrong$2;
9044
9045         // `Set` constructor
9046         // https://tc39.es/ecma262/#sec-set-objects
9047         collection$1('Set', function (init) {
9048           return function Set() { return init(this, arguments.length ? arguments[0] : undefined); };
9049         }, collectionStrong$1);
9050
9051         function d3_ascending (a, b) {
9052           return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
9053         }
9054
9055         function d3_bisector (f) {
9056           var delta = f;
9057           var compare = f;
9058
9059           if (f.length === 1) {
9060             delta = function delta(d, x) {
9061               return f(d) - x;
9062             };
9063
9064             compare = ascendingComparator(f);
9065           }
9066
9067           function left(a, x, lo, hi) {
9068             if (lo == null) lo = 0;
9069             if (hi == null) hi = a.length;
9070
9071             while (lo < hi) {
9072               var mid = lo + hi >>> 1;
9073               if (compare(a[mid], x) < 0) lo = mid + 1;else hi = mid;
9074             }
9075
9076             return lo;
9077           }
9078
9079           function right(a, x, lo, hi) {
9080             if (lo == null) lo = 0;
9081             if (hi == null) hi = a.length;
9082
9083             while (lo < hi) {
9084               var mid = lo + hi >>> 1;
9085               if (compare(a[mid], x) > 0) hi = mid;else lo = mid + 1;
9086             }
9087
9088             return lo;
9089           }
9090
9091           function center(a, x, lo, hi) {
9092             if (lo == null) lo = 0;
9093             if (hi == null) hi = a.length;
9094             var i = left(a, x, lo, hi - 1);
9095             return i > lo && delta(a[i - 1], x) > -delta(a[i], x) ? i - 1 : i;
9096           }
9097
9098           return {
9099             left: left,
9100             center: center,
9101             right: right
9102           };
9103         }
9104
9105         function ascendingComparator(f) {
9106           return function (d, x) {
9107             return d3_ascending(f(d), x);
9108           };
9109         }
9110
9111         var defineWellKnownSymbol = defineWellKnownSymbol$4;
9112
9113         // `Symbol.asyncIterator` well-known symbol
9114         // https://tc39.es/ecma262/#sec-symbol.asynciterator
9115         defineWellKnownSymbol('asyncIterator');
9116
9117         var runtime = {exports: {}};
9118
9119         (function (module) {
9120           var runtime = function (exports) {
9121
9122             var Op = Object.prototype;
9123             var hasOwn = Op.hasOwnProperty;
9124             var undefined$1; // More compressible than void 0.
9125
9126             var $Symbol = typeof Symbol === "function" ? Symbol : {};
9127             var iteratorSymbol = $Symbol.iterator || "@@iterator";
9128             var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
9129             var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
9130
9131             function define(obj, key, value) {
9132               Object.defineProperty(obj, key, {
9133                 value: value,
9134                 enumerable: true,
9135                 configurable: true,
9136                 writable: true
9137               });
9138               return obj[key];
9139             }
9140
9141             try {
9142               // IE 8 has a broken Object.defineProperty that only works on DOM objects.
9143               define({}, "");
9144             } catch (err) {
9145               define = function define(obj, key, value) {
9146                 return obj[key] = value;
9147               };
9148             }
9149
9150             function wrap(innerFn, outerFn, self, tryLocsList) {
9151               // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator.
9152               var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
9153               var generator = Object.create(protoGenerator.prototype);
9154               var context = new Context(tryLocsList || []); // The ._invoke method unifies the implementations of the .next,
9155               // .throw, and .return methods.
9156
9157               generator._invoke = makeInvokeMethod(innerFn, self, context);
9158               return generator;
9159             }
9160
9161             exports.wrap = wrap; // Try/catch helper to minimize deoptimizations. Returns a completion
9162             // record like context.tryEntries[i].completion. This interface could
9163             // have been (and was previously) designed to take a closure to be
9164             // invoked without arguments, but in all the cases we care about we
9165             // already have an existing method we want to call, so there's no need
9166             // to create a new function object. We can even get away with assuming
9167             // the method takes exactly one argument, since that happens to be true
9168             // in every case, so we don't have to touch the arguments object. The
9169             // only additional allocation required is the completion record, which
9170             // has a stable shape and so hopefully should be cheap to allocate.
9171
9172             function tryCatch(fn, obj, arg) {
9173               try {
9174                 return {
9175                   type: "normal",
9176                   arg: fn.call(obj, arg)
9177                 };
9178               } catch (err) {
9179                 return {
9180                   type: "throw",
9181                   arg: err
9182                 };
9183               }
9184             }
9185
9186             var GenStateSuspendedStart = "suspendedStart";
9187             var GenStateSuspendedYield = "suspendedYield";
9188             var GenStateExecuting = "executing";
9189             var GenStateCompleted = "completed"; // Returning this object from the innerFn has the same effect as
9190             // breaking out of the dispatch switch statement.
9191
9192             var ContinueSentinel = {}; // Dummy constructor functions that we use as the .constructor and
9193             // .constructor.prototype properties for functions that return Generator
9194             // objects. For full spec compliance, you may wish to configure your
9195             // minifier not to mangle the names of these two functions.
9196
9197             function Generator() {}
9198
9199             function GeneratorFunction() {}
9200
9201             function GeneratorFunctionPrototype() {} // This is a polyfill for %IteratorPrototype% for environments that
9202             // don't natively support it.
9203
9204
9205             var IteratorPrototype = {};
9206             define(IteratorPrototype, iteratorSymbol, function () {
9207               return this;
9208             });
9209             var getProto = Object.getPrototypeOf;
9210             var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
9211
9212             if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
9213               // This environment has a native %IteratorPrototype%; use it instead
9214               // of the polyfill.
9215               IteratorPrototype = NativeIteratorPrototype;
9216             }
9217
9218             var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
9219             GeneratorFunction.prototype = GeneratorFunctionPrototype;
9220             define(Gp, "constructor", GeneratorFunctionPrototype);
9221             define(GeneratorFunctionPrototype, "constructor", GeneratorFunction);
9222             GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"); // Helper for defining the .next, .throw, and .return methods of the
9223             // Iterator interface in terms of a single ._invoke method.
9224
9225             function defineIteratorMethods(prototype) {
9226               ["next", "throw", "return"].forEach(function (method) {
9227                 define(prototype, method, function (arg) {
9228                   return this._invoke(method, arg);
9229                 });
9230               });
9231             }
9232
9233             exports.isGeneratorFunction = function (genFun) {
9234               var ctor = typeof genFun === "function" && genFun.constructor;
9235               return ctor ? ctor === GeneratorFunction || // For the native GeneratorFunction constructor, the best we can
9236               // do is to check its .name property.
9237               (ctor.displayName || ctor.name) === "GeneratorFunction" : false;
9238             };
9239
9240             exports.mark = function (genFun) {
9241               if (Object.setPrototypeOf) {
9242                 Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
9243               } else {
9244                 genFun.__proto__ = GeneratorFunctionPrototype;
9245                 define(genFun, toStringTagSymbol, "GeneratorFunction");
9246               }
9247
9248               genFun.prototype = Object.create(Gp);
9249               return genFun;
9250             }; // Within the body of any async function, `await x` is transformed to
9251             // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test
9252             // `hasOwn.call(value, "__await")` to determine if the yielded value is
9253             // meant to be awaited.
9254
9255
9256             exports.awrap = function (arg) {
9257               return {
9258                 __await: arg
9259               };
9260             };
9261
9262             function AsyncIterator(generator, PromiseImpl) {
9263               function invoke(method, arg, resolve, reject) {
9264                 var record = tryCatch(generator[method], generator, arg);
9265
9266                 if (record.type === "throw") {
9267                   reject(record.arg);
9268                 } else {
9269                   var result = record.arg;
9270                   var value = result.value;
9271
9272                   if (value && _typeof(value) === "object" && hasOwn.call(value, "__await")) {
9273                     return PromiseImpl.resolve(value.__await).then(function (value) {
9274                       invoke("next", value, resolve, reject);
9275                     }, function (err) {
9276                       invoke("throw", err, resolve, reject);
9277                     });
9278                   }
9279
9280                   return PromiseImpl.resolve(value).then(function (unwrapped) {
9281                     // When a yielded Promise is resolved, its final value becomes
9282                     // the .value of the Promise<{value,done}> result for the
9283                     // current iteration.
9284                     result.value = unwrapped;
9285                     resolve(result);
9286                   }, function (error) {
9287                     // If a rejected Promise was yielded, throw the rejection back
9288                     // into the async generator function so it can be handled there.
9289                     return invoke("throw", error, resolve, reject);
9290                   });
9291                 }
9292               }
9293
9294               var previousPromise;
9295
9296               function enqueue(method, arg) {
9297                 function callInvokeWithMethodAndArg() {
9298                   return new PromiseImpl(function (resolve, reject) {
9299                     invoke(method, arg, resolve, reject);
9300                   });
9301                 }
9302
9303                 return previousPromise = // If enqueue has been called before, then we want to wait until
9304                 // all previous Promises have been resolved before calling invoke,
9305                 // so that results are always delivered in the correct order. If
9306                 // enqueue has not been called before, then it is important to
9307                 // call invoke immediately, without waiting on a callback to fire,
9308                 // so that the async generator function has the opportunity to do
9309                 // any necessary setup in a predictable way. This predictability
9310                 // is why the Promise constructor synchronously invokes its
9311                 // executor callback, and why async functions synchronously
9312                 // execute code before the first await. Since we implement simple
9313                 // async functions in terms of async generators, it is especially
9314                 // important to get this right, even though it requires care.
9315                 previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, // Avoid propagating failures to Promises returned by later
9316                 // invocations of the iterator.
9317                 callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
9318               } // Define the unified helper method that is used to implement .next,
9319               // .throw, and .return (see defineIteratorMethods).
9320
9321
9322               this._invoke = enqueue;
9323             }
9324
9325             defineIteratorMethods(AsyncIterator.prototype);
9326             define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
9327               return this;
9328             });
9329             exports.AsyncIterator = AsyncIterator; // Note that simple async functions are implemented on top of
9330             // AsyncIterator objects; they just return a Promise for the value of
9331             // the final result produced by the iterator.
9332
9333             exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
9334               if (PromiseImpl === void 0) PromiseImpl = Promise;
9335               var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
9336               return exports.isGeneratorFunction(outerFn) ? iter // If outerFn is a generator, return the full iterator.
9337               : iter.next().then(function (result) {
9338                 return result.done ? result.value : iter.next();
9339               });
9340             };
9341
9342             function makeInvokeMethod(innerFn, self, context) {
9343               var state = GenStateSuspendedStart;
9344               return function invoke(method, arg) {
9345                 if (state === GenStateExecuting) {
9346                   throw new Error("Generator is already running");
9347                 }
9348
9349                 if (state === GenStateCompleted) {
9350                   if (method === "throw") {
9351                     throw arg;
9352                   } // Be forgiving, per 25.3.3.3.3 of the spec:
9353                   // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
9354
9355
9356                   return doneResult();
9357                 }
9358
9359                 context.method = method;
9360                 context.arg = arg;
9361
9362                 while (true) {
9363                   var delegate = context.delegate;
9364
9365                   if (delegate) {
9366                     var delegateResult = maybeInvokeDelegate(delegate, context);
9367
9368                     if (delegateResult) {
9369                       if (delegateResult === ContinueSentinel) continue;
9370                       return delegateResult;
9371                     }
9372                   }
9373
9374                   if (context.method === "next") {
9375                     // Setting context._sent for legacy support of Babel's
9376                     // function.sent implementation.
9377                     context.sent = context._sent = context.arg;
9378                   } else if (context.method === "throw") {
9379                     if (state === GenStateSuspendedStart) {
9380                       state = GenStateCompleted;
9381                       throw context.arg;
9382                     }
9383
9384                     context.dispatchException(context.arg);
9385                   } else if (context.method === "return") {
9386                     context.abrupt("return", context.arg);
9387                   }
9388
9389                   state = GenStateExecuting;
9390                   var record = tryCatch(innerFn, self, context);
9391
9392                   if (record.type === "normal") {
9393                     // If an exception is thrown from innerFn, we leave state ===
9394                     // GenStateExecuting and loop back for another invocation.
9395                     state = context.done ? GenStateCompleted : GenStateSuspendedYield;
9396
9397                     if (record.arg === ContinueSentinel) {
9398                       continue;
9399                     }
9400
9401                     return {
9402                       value: record.arg,
9403                       done: context.done
9404                     };
9405                   } else if (record.type === "throw") {
9406                     state = GenStateCompleted; // Dispatch the exception by looping back around to the
9407                     // context.dispatchException(context.arg) call above.
9408
9409                     context.method = "throw";
9410                     context.arg = record.arg;
9411                   }
9412                 }
9413               };
9414             } // Call delegate.iterator[context.method](context.arg) and handle the
9415             // result, either by returning a { value, done } result from the
9416             // delegate iterator, or by modifying context.method and context.arg,
9417             // setting context.delegate to null, and returning the ContinueSentinel.
9418
9419
9420             function maybeInvokeDelegate(delegate, context) {
9421               var method = delegate.iterator[context.method];
9422
9423               if (method === undefined$1) {
9424                 // A .throw or .return when the delegate iterator has no .throw
9425                 // method always terminates the yield* loop.
9426                 context.delegate = null;
9427
9428                 if (context.method === "throw") {
9429                   // Note: ["return"] must be used for ES3 parsing compatibility.
9430                   if (delegate.iterator["return"]) {
9431                     // If the delegate iterator has a return method, give it a
9432                     // chance to clean up.
9433                     context.method = "return";
9434                     context.arg = undefined$1;
9435                     maybeInvokeDelegate(delegate, context);
9436
9437                     if (context.method === "throw") {
9438                       // If maybeInvokeDelegate(context) changed context.method from
9439                       // "return" to "throw", let that override the TypeError below.
9440                       return ContinueSentinel;
9441                     }
9442                   }
9443
9444                   context.method = "throw";
9445                   context.arg = new TypeError("The iterator does not provide a 'throw' method");
9446                 }
9447
9448                 return ContinueSentinel;
9449               }
9450
9451               var record = tryCatch(method, delegate.iterator, context.arg);
9452
9453               if (record.type === "throw") {
9454                 context.method = "throw";
9455                 context.arg = record.arg;
9456                 context.delegate = null;
9457                 return ContinueSentinel;
9458               }
9459
9460               var info = record.arg;
9461
9462               if (!info) {
9463                 context.method = "throw";
9464                 context.arg = new TypeError("iterator result is not an object");
9465                 context.delegate = null;
9466                 return ContinueSentinel;
9467               }
9468
9469               if (info.done) {
9470                 // Assign the result of the finished delegate to the temporary
9471                 // variable specified by delegate.resultName (see delegateYield).
9472                 context[delegate.resultName] = info.value; // Resume execution at the desired location (see delegateYield).
9473
9474                 context.next = delegate.nextLoc; // If context.method was "throw" but the delegate handled the
9475                 // exception, let the outer generator proceed normally. If
9476                 // context.method was "next", forget context.arg since it has been
9477                 // "consumed" by the delegate iterator. If context.method was
9478                 // "return", allow the original .return call to continue in the
9479                 // outer generator.
9480
9481                 if (context.method !== "return") {
9482                   context.method = "next";
9483                   context.arg = undefined$1;
9484                 }
9485               } else {
9486                 // Re-yield the result returned by the delegate method.
9487                 return info;
9488               } // The delegate iterator is finished, so forget it and continue with
9489               // the outer generator.
9490
9491
9492               context.delegate = null;
9493               return ContinueSentinel;
9494             } // Define Generator.prototype.{next,throw,return} in terms of the
9495             // unified ._invoke helper method.
9496
9497
9498             defineIteratorMethods(Gp);
9499             define(Gp, toStringTagSymbol, "Generator"); // A Generator should always return itself as the iterator object when the
9500             // @@iterator function is called on it. Some browsers' implementations of the
9501             // iterator prototype chain incorrectly implement this, causing the Generator
9502             // object to not be returned from this call. This ensures that doesn't happen.
9503             // See https://github.com/facebook/regenerator/issues/274 for more details.
9504
9505             define(Gp, iteratorSymbol, function () {
9506               return this;
9507             });
9508             define(Gp, "toString", function () {
9509               return "[object Generator]";
9510             });
9511
9512             function pushTryEntry(locs) {
9513               var entry = {
9514                 tryLoc: locs[0]
9515               };
9516
9517               if (1 in locs) {
9518                 entry.catchLoc = locs[1];
9519               }
9520
9521               if (2 in locs) {
9522                 entry.finallyLoc = locs[2];
9523                 entry.afterLoc = locs[3];
9524               }
9525
9526               this.tryEntries.push(entry);
9527             }
9528
9529             function resetTryEntry(entry) {
9530               var record = entry.completion || {};
9531               record.type = "normal";
9532               delete record.arg;
9533               entry.completion = record;
9534             }
9535
9536             function Context(tryLocsList) {
9537               // The root entry object (effectively a try statement without a catch
9538               // or a finally block) gives us a place to store values thrown from
9539               // locations where there is no enclosing try statement.
9540               this.tryEntries = [{
9541                 tryLoc: "root"
9542               }];
9543               tryLocsList.forEach(pushTryEntry, this);
9544               this.reset(true);
9545             }
9546
9547             exports.keys = function (object) {
9548               var keys = [];
9549
9550               for (var key in object) {
9551                 keys.push(key);
9552               }
9553
9554               keys.reverse(); // Rather than returning an object with a next method, we keep
9555               // things simple and return the next function itself.
9556
9557               return function next() {
9558                 while (keys.length) {
9559                   var key = keys.pop();
9560
9561                   if (key in object) {
9562                     next.value = key;
9563                     next.done = false;
9564                     return next;
9565                   }
9566                 } // To avoid creating an additional object, we just hang the .value
9567                 // and .done properties off the next function object itself. This
9568                 // also ensures that the minifier will not anonymize the function.
9569
9570
9571                 next.done = true;
9572                 return next;
9573               };
9574             };
9575
9576             function values(iterable) {
9577               if (iterable) {
9578                 var iteratorMethod = iterable[iteratorSymbol];
9579
9580                 if (iteratorMethod) {
9581                   return iteratorMethod.call(iterable);
9582                 }
9583
9584                 if (typeof iterable.next === "function") {
9585                   return iterable;
9586                 }
9587
9588                 if (!isNaN(iterable.length)) {
9589                   var i = -1,
9590                       next = function next() {
9591                     while (++i < iterable.length) {
9592                       if (hasOwn.call(iterable, i)) {
9593                         next.value = iterable[i];
9594                         next.done = false;
9595                         return next;
9596                       }
9597                     }
9598
9599                     next.value = undefined$1;
9600                     next.done = true;
9601                     return next;
9602                   };
9603
9604                   return next.next = next;
9605                 }
9606               } // Return an iterator with no values.
9607
9608
9609               return {
9610                 next: doneResult
9611               };
9612             }
9613
9614             exports.values = values;
9615
9616             function doneResult() {
9617               return {
9618                 value: undefined$1,
9619                 done: true
9620               };
9621             }
9622
9623             Context.prototype = {
9624               constructor: Context,
9625               reset: function reset(skipTempReset) {
9626                 this.prev = 0;
9627                 this.next = 0; // Resetting context._sent for legacy support of Babel's
9628                 // function.sent implementation.
9629
9630                 this.sent = this._sent = undefined$1;
9631                 this.done = false;
9632                 this.delegate = null;
9633                 this.method = "next";
9634                 this.arg = undefined$1;
9635                 this.tryEntries.forEach(resetTryEntry);
9636
9637                 if (!skipTempReset) {
9638                   for (var name in this) {
9639                     // Not sure about the optimal order of these conditions:
9640                     if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
9641                       this[name] = undefined$1;
9642                     }
9643                   }
9644                 }
9645               },
9646               stop: function stop() {
9647                 this.done = true;
9648                 var rootEntry = this.tryEntries[0];
9649                 var rootRecord = rootEntry.completion;
9650
9651                 if (rootRecord.type === "throw") {
9652                   throw rootRecord.arg;
9653                 }
9654
9655                 return this.rval;
9656               },
9657               dispatchException: function dispatchException(exception) {
9658                 if (this.done) {
9659                   throw exception;
9660                 }
9661
9662                 var context = this;
9663
9664                 function handle(loc, caught) {
9665                   record.type = "throw";
9666                   record.arg = exception;
9667                   context.next = loc;
9668
9669                   if (caught) {
9670                     // If the dispatched exception was caught by a catch block,
9671                     // then let that catch block handle the exception normally.
9672                     context.method = "next";
9673                     context.arg = undefined$1;
9674                   }
9675
9676                   return !!caught;
9677                 }
9678
9679                 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9680                   var entry = this.tryEntries[i];
9681                   var record = entry.completion;
9682
9683                   if (entry.tryLoc === "root") {
9684                     // Exception thrown outside of any try block that could handle
9685                     // it, so set the completion value of the entire function to
9686                     // throw the exception.
9687                     return handle("end");
9688                   }
9689
9690                   if (entry.tryLoc <= this.prev) {
9691                     var hasCatch = hasOwn.call(entry, "catchLoc");
9692                     var hasFinally = hasOwn.call(entry, "finallyLoc");
9693
9694                     if (hasCatch && hasFinally) {
9695                       if (this.prev < entry.catchLoc) {
9696                         return handle(entry.catchLoc, true);
9697                       } else if (this.prev < entry.finallyLoc) {
9698                         return handle(entry.finallyLoc);
9699                       }
9700                     } else if (hasCatch) {
9701                       if (this.prev < entry.catchLoc) {
9702                         return handle(entry.catchLoc, true);
9703                       }
9704                     } else if (hasFinally) {
9705                       if (this.prev < entry.finallyLoc) {
9706                         return handle(entry.finallyLoc);
9707                       }
9708                     } else {
9709                       throw new Error("try statement without catch or finally");
9710                     }
9711                   }
9712                 }
9713               },
9714               abrupt: function abrupt(type, arg) {
9715                 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9716                   var entry = this.tryEntries[i];
9717
9718                   if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
9719                     var finallyEntry = entry;
9720                     break;
9721                   }
9722                 }
9723
9724                 if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
9725                   // Ignore the finally entry if control is not jumping to a
9726                   // location outside the try/catch block.
9727                   finallyEntry = null;
9728                 }
9729
9730                 var record = finallyEntry ? finallyEntry.completion : {};
9731                 record.type = type;
9732                 record.arg = arg;
9733
9734                 if (finallyEntry) {
9735                   this.method = "next";
9736                   this.next = finallyEntry.finallyLoc;
9737                   return ContinueSentinel;
9738                 }
9739
9740                 return this.complete(record);
9741               },
9742               complete: function complete(record, afterLoc) {
9743                 if (record.type === "throw") {
9744                   throw record.arg;
9745                 }
9746
9747                 if (record.type === "break" || record.type === "continue") {
9748                   this.next = record.arg;
9749                 } else if (record.type === "return") {
9750                   this.rval = this.arg = record.arg;
9751                   this.method = "return";
9752                   this.next = "end";
9753                 } else if (record.type === "normal" && afterLoc) {
9754                   this.next = afterLoc;
9755                 }
9756
9757                 return ContinueSentinel;
9758               },
9759               finish: function finish(finallyLoc) {
9760                 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9761                   var entry = this.tryEntries[i];
9762
9763                   if (entry.finallyLoc === finallyLoc) {
9764                     this.complete(entry.completion, entry.afterLoc);
9765                     resetTryEntry(entry);
9766                     return ContinueSentinel;
9767                   }
9768                 }
9769               },
9770               "catch": function _catch(tryLoc) {
9771                 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
9772                   var entry = this.tryEntries[i];
9773
9774                   if (entry.tryLoc === tryLoc) {
9775                     var record = entry.completion;
9776
9777                     if (record.type === "throw") {
9778                       var thrown = record.arg;
9779                       resetTryEntry(entry);
9780                     }
9781
9782                     return thrown;
9783                   }
9784                 } // The context.catch method must only be called with a location
9785                 // argument that corresponds to a known catch block.
9786
9787
9788                 throw new Error("illegal catch attempt");
9789               },
9790               delegateYield: function delegateYield(iterable, resultName, nextLoc) {
9791                 this.delegate = {
9792                   iterator: values(iterable),
9793                   resultName: resultName,
9794                   nextLoc: nextLoc
9795                 };
9796
9797                 if (this.method === "next") {
9798                   // Deliberately forget the last sent value so that we don't
9799                   // accidentally pass it on to the delegate.
9800                   this.arg = undefined$1;
9801                 }
9802
9803                 return ContinueSentinel;
9804               }
9805             }; // Regardless of whether this script is executing as a CommonJS module
9806             // or not, return the runtime object so that we can declare the variable
9807             // regeneratorRuntime in the outer scope, which allows this module to be
9808             // injected easily by `bin/regenerator --include-runtime script.js`.
9809
9810             return exports;
9811           }( // If this script is executing as a CommonJS module, use module.exports
9812           // as the regeneratorRuntime namespace. Otherwise create a new empty
9813           // object. Either way, the resulting object will be used to initialize
9814           // the regeneratorRuntime variable at the top of this file.
9815           module.exports );
9816
9817           try {
9818             regeneratorRuntime = runtime;
9819           } catch (accidentalStrictMode) {
9820             // This module should not be running in strict mode, so the above
9821             // assignment should always work unless something is misconfigured. Just
9822             // in case runtime.js accidentally runs in strict mode, in modern engines
9823             // we can explicitly access globalThis. In older engines we can escape
9824             // strict mode using a global Function call. This could conceivably fail
9825             // if a Content Security Policy forbids using Function, but in that case
9826             // the proper solution is to fix the accidental strict mode problem. If
9827             // you've misconfigured your bundler to force strict mode and applied a
9828             // CSP to forbid Function, and you're not willing to fix either of those
9829             // problems, please detail your unique predicament in a GitHub issue.
9830             if ((typeof globalThis === "undefined" ? "undefined" : _typeof(globalThis)) === "object") {
9831               globalThis.regeneratorRuntime = runtime;
9832             } else {
9833               Function("r", "regeneratorRuntime = r")(runtime);
9834             }
9835           }
9836         })(runtime);
9837
9838         var _marked$3 = /*#__PURE__*/regeneratorRuntime.mark(numbers);
9839
9840         function number$1 (x) {
9841           return x === null ? NaN : +x;
9842         }
9843         function numbers(values, valueof) {
9844           var _iterator, _step, value, index, _iterator2, _step2, _value;
9845
9846           return regeneratorRuntime.wrap(function numbers$(_context) {
9847             while (1) {
9848               switch (_context.prev = _context.next) {
9849                 case 0:
9850                   if (!(valueof === undefined)) {
9851                     _context.next = 21;
9852                     break;
9853                   }
9854
9855                   _iterator = _createForOfIteratorHelper(values);
9856                   _context.prev = 2;
9857
9858                   _iterator.s();
9859
9860                 case 4:
9861                   if ((_step = _iterator.n()).done) {
9862                     _context.next = 11;
9863                     break;
9864                   }
9865
9866                   value = _step.value;
9867
9868                   if (!(value != null && (value = +value) >= value)) {
9869                     _context.next = 9;
9870                     break;
9871                   }
9872
9873                   _context.next = 9;
9874                   return value;
9875
9876                 case 9:
9877                   _context.next = 4;
9878                   break;
9879
9880                 case 11:
9881                   _context.next = 16;
9882                   break;
9883
9884                 case 13:
9885                   _context.prev = 13;
9886                   _context.t0 = _context["catch"](2);
9887
9888                   _iterator.e(_context.t0);
9889
9890                 case 16:
9891                   _context.prev = 16;
9892
9893                   _iterator.f();
9894
9895                   return _context.finish(16);
9896
9897                 case 19:
9898                   _context.next = 40;
9899                   break;
9900
9901                 case 21:
9902                   index = -1;
9903                   _iterator2 = _createForOfIteratorHelper(values);
9904                   _context.prev = 23;
9905
9906                   _iterator2.s();
9907
9908                 case 25:
9909                   if ((_step2 = _iterator2.n()).done) {
9910                     _context.next = 32;
9911                     break;
9912                   }
9913
9914                   _value = _step2.value;
9915
9916                   if (!((_value = valueof(_value, ++index, values)) != null && (_value = +_value) >= _value)) {
9917                     _context.next = 30;
9918                     break;
9919                   }
9920
9921                   _context.next = 30;
9922                   return _value;
9923
9924                 case 30:
9925                   _context.next = 25;
9926                   break;
9927
9928                 case 32:
9929                   _context.next = 37;
9930                   break;
9931
9932                 case 34:
9933                   _context.prev = 34;
9934                   _context.t1 = _context["catch"](23);
9935
9936                   _iterator2.e(_context.t1);
9937
9938                 case 37:
9939                   _context.prev = 37;
9940
9941                   _iterator2.f();
9942
9943                   return _context.finish(37);
9944
9945                 case 40:
9946                 case "end":
9947                   return _context.stop();
9948               }
9949             }
9950           }, _marked$3, null, [[2, 13, 16, 19], [23, 34, 37, 40]]);
9951         }
9952
9953         var ascendingBisect = d3_bisector(d3_ascending);
9954         var bisectRight = ascendingBisect.right;
9955         d3_bisector(number$1).center;
9956
9957         var anObject$2 = anObject$n;
9958         var iteratorClose = iteratorClose$2;
9959
9960         // call something on iterator step with safe closing on error
9961         var callWithSafeIterationClosing$1 = function (iterator, fn, value, ENTRIES) {
9962           try {
9963             return ENTRIES ? fn(anObject$2(value)[0], value[1]) : fn(value);
9964           } catch (error) {
9965             iteratorClose(iterator, 'throw', error);
9966           }
9967         };
9968
9969         var global$c = global$1o;
9970         var bind$5 = functionBindContext;
9971         var call$3 = functionCall;
9972         var toObject$3 = toObject$i;
9973         var callWithSafeIterationClosing = callWithSafeIterationClosing$1;
9974         var isArrayIteratorMethod = isArrayIteratorMethod$3;
9975         var isConstructor = isConstructor$4;
9976         var lengthOfArrayLike$3 = lengthOfArrayLike$i;
9977         var createProperty = createProperty$5;
9978         var getIterator = getIterator$4;
9979         var getIteratorMethod = getIteratorMethod$5;
9980
9981         var Array$1 = global$c.Array;
9982
9983         // `Array.from` method implementation
9984         // https://tc39.es/ecma262/#sec-array.from
9985         var arrayFrom$1 = function from(arrayLike /* , mapfn = undefined, thisArg = undefined */) {
9986           var O = toObject$3(arrayLike);
9987           var IS_CONSTRUCTOR = isConstructor(this);
9988           var argumentsLength = arguments.length;
9989           var mapfn = argumentsLength > 1 ? arguments[1] : undefined;
9990           var mapping = mapfn !== undefined;
9991           if (mapping) mapfn = bind$5(mapfn, argumentsLength > 2 ? arguments[2] : undefined);
9992           var iteratorMethod = getIteratorMethod(O);
9993           var index = 0;
9994           var length, result, step, iterator, next, value;
9995           // if the target is not iterable or it's an array with the default iterator - use a simple case
9996           if (iteratorMethod && !(this == Array$1 && isArrayIteratorMethod(iteratorMethod))) {
9997             iterator = getIterator(O, iteratorMethod);
9998             next = iterator.next;
9999             result = IS_CONSTRUCTOR ? new this() : [];
10000             for (;!(step = call$3(next, iterator)).done; index++) {
10001               value = mapping ? callWithSafeIterationClosing(iterator, mapfn, [step.value, index], true) : step.value;
10002               createProperty(result, index, value);
10003             }
10004           } else {
10005             length = lengthOfArrayLike$3(O);
10006             result = IS_CONSTRUCTOR ? new this(length) : Array$1(length);
10007             for (;length > index; index++) {
10008               value = mapping ? mapfn(O[index], index) : O[index];
10009               createProperty(result, index, value);
10010             }
10011           }
10012           result.length = index;
10013           return result;
10014         };
10015
10016         var $$D = _export;
10017         var from = arrayFrom$1;
10018         var checkCorrectnessOfIteration = checkCorrectnessOfIteration$4;
10019
10020         var INCORRECT_ITERATION = !checkCorrectnessOfIteration(function (iterable) {
10021           // eslint-disable-next-line es/no-array-from -- required for testing
10022           Array.from(iterable);
10023         });
10024
10025         // `Array.from` method
10026         // https://tc39.es/ecma262/#sec-array.from
10027         $$D({ target: 'Array', stat: true, forced: INCORRECT_ITERATION }, {
10028           from: from
10029         });
10030
10031         var $$C = _export;
10032         var fill = arrayFill$1;
10033         var addToUnscopables$4 = addToUnscopables$6;
10034
10035         // `Array.prototype.fill` method
10036         // https://tc39.es/ecma262/#sec-array.prototype.fill
10037         $$C({ target: 'Array', proto: true }, {
10038           fill: fill
10039         });
10040
10041         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
10042         addToUnscopables$4('fill');
10043
10044         var $$B = _export;
10045         var $some = arrayIteration.some;
10046         var arrayMethodIsStrict$4 = arrayMethodIsStrict$9;
10047
10048         var STRICT_METHOD$4 = arrayMethodIsStrict$4('some');
10049
10050         // `Array.prototype.some` method
10051         // https://tc39.es/ecma262/#sec-array.prototype.some
10052         $$B({ target: 'Array', proto: true, forced: !STRICT_METHOD$4 }, {
10053           some: function some(callbackfn /* , thisArg */) {
10054             return $some(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
10055           }
10056         });
10057
10058         var TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS = typedArrayConstructorsRequireWrappers;
10059         var exportTypedArrayStaticMethod = arrayBufferViewCore.exportTypedArrayStaticMethod;
10060         var typedArrayFrom = typedArrayFrom$2;
10061
10062         // `%TypedArray%.from` method
10063         // https://tc39.es/ecma262/#sec-%typedarray%.from
10064         exportTypedArrayStaticMethod('from', typedArrayFrom, TYPED_ARRAYS_CONSTRUCTORS_REQUIRES_WRAPPERS);
10065
10066         var createTypedArrayConstructor = typedArrayConstructor.exports;
10067
10068         // `Float64Array` constructor
10069         // https://tc39.es/ecma262/#sec-typedarray-objects
10070         createTypedArrayConstructor('Float64', function (init) {
10071           return function Float64Array(data, byteOffset, length) {
10072             return init(this, data, byteOffset, length);
10073           };
10074         });
10075
10076         function d3_descending (a, b) {
10077           return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
10078         }
10079
10080         // https://github.com/python/cpython/blob/a74eea238f5baba15797e2e8b570d153bc8690a7/Modules/mathmodule.c#L1423
10081         var Adder = /*#__PURE__*/function () {
10082           function Adder() {
10083             _classCallCheck$1(this, Adder);
10084
10085             this._partials = new Float64Array(32);
10086             this._n = 0;
10087           }
10088
10089           _createClass$1(Adder, [{
10090             key: "add",
10091             value: function add(x) {
10092               var p = this._partials;
10093               var i = 0;
10094
10095               for (var j = 0; j < this._n && j < 32; j++) {
10096                 var y = p[j],
10097                     hi = x + y,
10098                     lo = Math.abs(x) < Math.abs(y) ? x - (hi - y) : y - (hi - x);
10099                 if (lo) p[i++] = lo;
10100                 x = hi;
10101               }
10102
10103               p[i] = x;
10104               this._n = i + 1;
10105               return this;
10106             }
10107           }, {
10108             key: "valueOf",
10109             value: function valueOf() {
10110               var p = this._partials;
10111               var n = this._n,
10112                   x,
10113                   y,
10114                   lo,
10115                   hi = 0;
10116
10117               if (n > 0) {
10118                 hi = p[--n];
10119
10120                 while (n > 0) {
10121                   x = hi;
10122                   y = p[--n];
10123                   hi = x + y;
10124                   lo = y - (hi - x);
10125                   if (lo) break;
10126                 }
10127
10128                 if (n > 0 && (lo < 0 && p[n - 1] < 0 || lo > 0 && p[n - 1] > 0)) {
10129                   y = lo * 2;
10130                   x = hi + y;
10131                   if (y == x - hi) hi = x;
10132                 }
10133               }
10134
10135               return hi;
10136             }
10137           }]);
10138
10139           return Adder;
10140         }();
10141
10142         var $$A = _export;
10143         var DESCRIPTORS$5 = descriptors;
10144         var defineProperties$1 = objectDefineProperties.f;
10145
10146         // `Object.defineProperties` method
10147         // https://tc39.es/ecma262/#sec-object.defineproperties
10148         // eslint-disable-next-line es/no-object-defineproperties -- safe
10149         $$A({ target: 'Object', stat: true, forced: Object.defineProperties !== defineProperties$1, sham: !DESCRIPTORS$5 }, {
10150           defineProperties: defineProperties$1
10151         });
10152
10153         var collection = collection$2;
10154         var collectionStrong = collectionStrong$2;
10155
10156         // `Map` constructor
10157         // https://tc39.es/ecma262/#sec-map-objects
10158         collection('Map', function (init) {
10159           return function Map() { return init(this, arguments.length ? arguments[0] : undefined); };
10160         }, collectionStrong);
10161
10162         var $$z = _export;
10163         var uncurryThis$f = functionUncurryThis;
10164         var aCallable$1 = aCallable$a;
10165         var toObject$2 = toObject$i;
10166         var lengthOfArrayLike$2 = lengthOfArrayLike$i;
10167         var toString$a = toString$k;
10168         var fails$b = fails$V;
10169         var internalSort = arraySort$1;
10170         var arrayMethodIsStrict$3 = arrayMethodIsStrict$9;
10171         var FF = engineFfVersion;
10172         var IE_OR_EDGE = engineIsIeOrEdge;
10173         var V8 = engineV8Version;
10174         var WEBKIT = engineWebkitVersion;
10175
10176         var test = [];
10177         var un$Sort = uncurryThis$f(test.sort);
10178         var push$3 = uncurryThis$f(test.push);
10179
10180         // IE8-
10181         var FAILS_ON_UNDEFINED = fails$b(function () {
10182           test.sort(undefined);
10183         });
10184         // V8 bug
10185         var FAILS_ON_NULL = fails$b(function () {
10186           test.sort(null);
10187         });
10188         // Old WebKit
10189         var STRICT_METHOD$3 = arrayMethodIsStrict$3('sort');
10190
10191         var STABLE_SORT = !fails$b(function () {
10192           // feature detection can be too slow, so check engines versions
10193           if (V8) return V8 < 70;
10194           if (FF && FF > 3) return;
10195           if (IE_OR_EDGE) return true;
10196           if (WEBKIT) return WEBKIT < 603;
10197
10198           var result = '';
10199           var code, chr, value, index;
10200
10201           // generate an array with more 512 elements (Chakra and old V8 fails only in this case)
10202           for (code = 65; code < 76; code++) {
10203             chr = String.fromCharCode(code);
10204
10205             switch (code) {
10206               case 66: case 69: case 70: case 72: value = 3; break;
10207               case 68: case 71: value = 4; break;
10208               default: value = 2;
10209             }
10210
10211             for (index = 0; index < 47; index++) {
10212               test.push({ k: chr + index, v: value });
10213             }
10214           }
10215
10216           test.sort(function (a, b) { return b.v - a.v; });
10217
10218           for (index = 0; index < test.length; index++) {
10219             chr = test[index].k.charAt(0);
10220             if (result.charAt(result.length - 1) !== chr) result += chr;
10221           }
10222
10223           return result !== 'DGBEFHACIJK';
10224         });
10225
10226         var FORCED$7 = FAILS_ON_UNDEFINED || !FAILS_ON_NULL || !STRICT_METHOD$3 || !STABLE_SORT;
10227
10228         var getSortCompare = function (comparefn) {
10229           return function (x, y) {
10230             if (y === undefined) return -1;
10231             if (x === undefined) return 1;
10232             if (comparefn !== undefined) return +comparefn(x, y) || 0;
10233             return toString$a(x) > toString$a(y) ? 1 : -1;
10234           };
10235         };
10236
10237         // `Array.prototype.sort` method
10238         // https://tc39.es/ecma262/#sec-array.prototype.sort
10239         $$z({ target: 'Array', proto: true, forced: FORCED$7 }, {
10240           sort: function sort(comparefn) {
10241             if (comparefn !== undefined) aCallable$1(comparefn);
10242
10243             var array = toObject$2(this);
10244
10245             if (STABLE_SORT) return comparefn === undefined ? un$Sort(array) : un$Sort(array, comparefn);
10246
10247             var items = [];
10248             var arrayLength = lengthOfArrayLike$2(array);
10249             var itemsLength, index;
10250
10251             for (index = 0; index < arrayLength; index++) {
10252               if (index in array) push$3(items, array[index]);
10253             }
10254
10255             internalSort(items, getSortCompare(comparefn));
10256
10257             itemsLength = items.length;
10258             index = 0;
10259
10260             while (index < itemsLength) array[index] = items[index++];
10261             while (index < arrayLength) delete array[index++];
10262
10263             return array;
10264           }
10265         });
10266
10267         var e10 = Math.sqrt(50),
10268             e5 = Math.sqrt(10),
10269             e2 = Math.sqrt(2);
10270         function ticks (start, stop, count) {
10271           var reverse,
10272               i = -1,
10273               n,
10274               ticks,
10275               step;
10276           stop = +stop, start = +start, count = +count;
10277           if (start === stop && count > 0) return [start];
10278           if (reverse = stop < start) n = start, start = stop, stop = n;
10279           if ((step = tickIncrement(start, stop, count)) === 0 || !isFinite(step)) return [];
10280
10281           if (step > 0) {
10282             var r0 = Math.round(start / step),
10283                 r1 = Math.round(stop / step);
10284             if (r0 * step < start) ++r0;
10285             if (r1 * step > stop) --r1;
10286             ticks = new Array(n = r1 - r0 + 1);
10287
10288             while (++i < n) {
10289               ticks[i] = (r0 + i) * step;
10290             }
10291           } else {
10292             step = -step;
10293
10294             var _r = Math.round(start * step),
10295                 _r2 = Math.round(stop * step);
10296
10297             if (_r / step < start) ++_r;
10298             if (_r2 / step > stop) --_r2;
10299             ticks = new Array(n = _r2 - _r + 1);
10300
10301             while (++i < n) {
10302               ticks[i] = (_r + i) / step;
10303             }
10304           }
10305
10306           if (reverse) ticks.reverse();
10307           return ticks;
10308         }
10309         function tickIncrement(start, stop, count) {
10310           var step = (stop - start) / Math.max(0, count),
10311               power = Math.floor(Math.log(step) / Math.LN10),
10312               error = step / Math.pow(10, power);
10313           return power >= 0 ? (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1) * Math.pow(10, power) : -Math.pow(10, -power) / (error >= e10 ? 10 : error >= e5 ? 5 : error >= e2 ? 2 : 1);
10314         }
10315         function tickStep(start, stop, count) {
10316           var step0 = Math.abs(stop - start) / Math.max(0, count),
10317               step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
10318               error = step0 / step1;
10319           if (error >= e10) step1 *= 10;else if (error >= e5) step1 *= 5;else if (error >= e2) step1 *= 2;
10320           return stop < start ? -step1 : step1;
10321         }
10322
10323         function max(values, valueof) {
10324           var max;
10325
10326           if (valueof === undefined) {
10327             var _iterator = _createForOfIteratorHelper(values),
10328                 _step;
10329
10330             try {
10331               for (_iterator.s(); !(_step = _iterator.n()).done;) {
10332                 var value = _step.value;
10333
10334                 if (value != null && (max < value || max === undefined && value >= value)) {
10335                   max = value;
10336                 }
10337               }
10338             } catch (err) {
10339               _iterator.e(err);
10340             } finally {
10341               _iterator.f();
10342             }
10343           } else {
10344             var index = -1;
10345
10346             var _iterator2 = _createForOfIteratorHelper(values),
10347                 _step2;
10348
10349             try {
10350               for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
10351                 var _value = _step2.value;
10352
10353                 if ((_value = valueof(_value, ++index, values)) != null && (max < _value || max === undefined && _value >= _value)) {
10354                   max = _value;
10355                 }
10356               }
10357             } catch (err) {
10358               _iterator2.e(err);
10359             } finally {
10360               _iterator2.f();
10361             }
10362           }
10363
10364           return max;
10365         }
10366
10367         function min$2(values, valueof) {
10368           var min;
10369
10370           if (valueof === undefined) {
10371             var _iterator = _createForOfIteratorHelper(values),
10372                 _step;
10373
10374             try {
10375               for (_iterator.s(); !(_step = _iterator.n()).done;) {
10376                 var value = _step.value;
10377
10378                 if (value != null && (min > value || min === undefined && value >= value)) {
10379                   min = value;
10380                 }
10381               }
10382             } catch (err) {
10383               _iterator.e(err);
10384             } finally {
10385               _iterator.f();
10386             }
10387           } else {
10388             var index = -1;
10389
10390             var _iterator2 = _createForOfIteratorHelper(values),
10391                 _step2;
10392
10393             try {
10394               for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
10395                 var _value = _step2.value;
10396
10397                 if ((_value = valueof(_value, ++index, values)) != null && (min > _value || min === undefined && _value >= _value)) {
10398                   min = _value;
10399                 }
10400               }
10401             } catch (err) {
10402               _iterator2.e(err);
10403             } finally {
10404               _iterator2.f();
10405             }
10406           }
10407
10408           return min;
10409         }
10410
10411         // ISC license, Copyright 2018 Vladimir Agafonkin.
10412
10413         function quickselect$3(array, k) {
10414           var left = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
10415           var right = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : array.length - 1;
10416           var compare = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : d3_ascending;
10417
10418           while (right > left) {
10419             if (right - left > 600) {
10420               var n = right - left + 1;
10421               var m = k - left + 1;
10422               var z = Math.log(n);
10423               var s = 0.5 * Math.exp(2 * z / 3);
10424               var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
10425               var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
10426               var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
10427               quickselect$3(array, k, newLeft, newRight, compare);
10428             }
10429
10430             var t = array[k];
10431             var i = left;
10432             var j = right;
10433             swap$1(array, left, k);
10434             if (compare(array[right], t) > 0) swap$1(array, left, right);
10435
10436             while (i < j) {
10437               swap$1(array, i, j), ++i, --j;
10438
10439               while (compare(array[i], t) < 0) {
10440                 ++i;
10441               }
10442
10443               while (compare(array[j], t) > 0) {
10444                 --j;
10445               }
10446             }
10447
10448             if (compare(array[left], t) === 0) swap$1(array, left, j);else ++j, swap$1(array, j, right);
10449             if (j <= k) left = j + 1;
10450             if (k <= j) right = j - 1;
10451           }
10452
10453           return array;
10454         }
10455
10456         function swap$1(array, i, j) {
10457           var t = array[i];
10458           array[i] = array[j];
10459           array[j] = t;
10460         }
10461
10462         function quantile(values, p, valueof) {
10463           values = Float64Array.from(numbers(values, valueof));
10464           if (!(n = values.length)) return;
10465           if ((p = +p) <= 0 || n < 2) return min$2(values);
10466           if (p >= 1) return max(values);
10467           var n,
10468               i = (n - 1) * p,
10469               i0 = Math.floor(i),
10470               value0 = max(quickselect$3(values, i0).subarray(0, i0 + 1)),
10471               value1 = min$2(values.subarray(i0 + 1));
10472           return value0 + (value1 - value0) * (i - i0);
10473         }
10474
10475         function d3_median (values, valueof) {
10476           return quantile(values, 0.5, valueof);
10477         }
10478
10479         var _marked$2 = /*#__PURE__*/regeneratorRuntime.mark(flatten);
10480
10481         function flatten(arrays) {
10482           var _iterator, _step, array;
10483
10484           return regeneratorRuntime.wrap(function flatten$(_context) {
10485             while (1) {
10486               switch (_context.prev = _context.next) {
10487                 case 0:
10488                   _iterator = _createForOfIteratorHelper(arrays);
10489                   _context.prev = 1;
10490
10491                   _iterator.s();
10492
10493                 case 3:
10494                   if ((_step = _iterator.n()).done) {
10495                     _context.next = 8;
10496                     break;
10497                   }
10498
10499                   array = _step.value;
10500                   return _context.delegateYield(array, "t0", 6);
10501
10502                 case 6:
10503                   _context.next = 3;
10504                   break;
10505
10506                 case 8:
10507                   _context.next = 13;
10508                   break;
10509
10510                 case 10:
10511                   _context.prev = 10;
10512                   _context.t1 = _context["catch"](1);
10513
10514                   _iterator.e(_context.t1);
10515
10516                 case 13:
10517                   _context.prev = 13;
10518
10519                   _iterator.f();
10520
10521                   return _context.finish(13);
10522
10523                 case 16:
10524                 case "end":
10525                   return _context.stop();
10526               }
10527             }
10528           }, _marked$2, null, [[1, 10, 13, 16]]);
10529         }
10530
10531         function merge$4(arrays) {
10532           return Array.from(flatten(arrays));
10533         }
10534
10535         function range$1 (start, stop, step) {
10536           start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
10537           var i = -1,
10538               n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
10539               range = new Array(n);
10540
10541           while (++i < n) {
10542             range[i] = start + i * step;
10543           }
10544
10545           return range;
10546         }
10547
10548         // `SameValue` abstract operation
10549         // https://tc39.es/ecma262/#sec-samevalue
10550         // eslint-disable-next-line es/no-object-is -- safe
10551         var sameValue$1 = Object.is || function is(x, y) {
10552           // eslint-disable-next-line no-self-compare -- NaN check
10553           return x === y ? x !== 0 || 1 / x === 1 / y : x != x && y != y;
10554         };
10555
10556         var $$y = _export;
10557
10558         // eslint-disable-next-line es/no-math-hypot -- required for testing
10559         var $hypot = Math.hypot;
10560         var abs$3 = Math.abs;
10561         var sqrt$1 = Math.sqrt;
10562
10563         // Chrome 77 bug
10564         // https://bugs.chromium.org/p/v8/issues/detail?id=9546
10565         var BUGGY = !!$hypot && $hypot(Infinity, NaN) !== Infinity;
10566
10567         // `Math.hypot` method
10568         // https://tc39.es/ecma262/#sec-math.hypot
10569         $$y({ target: 'Math', stat: true, forced: BUGGY }, {
10570           // eslint-disable-next-line no-unused-vars -- required for `.length`
10571           hypot: function hypot(value1, value2) {
10572             var sum = 0;
10573             var i = 0;
10574             var aLen = arguments.length;
10575             var larg = 0;
10576             var arg, div;
10577             while (i < aLen) {
10578               arg = abs$3(arguments[i++]);
10579               if (larg < arg) {
10580                 div = larg / arg;
10581                 sum = sum * div * div + 1;
10582                 larg = arg;
10583               } else if (arg > 0) {
10584                 div = arg / larg;
10585                 sum += div * div;
10586               } else sum += arg;
10587             }
10588             return larg === Infinity ? Infinity : larg * sqrt$1(sum);
10589           }
10590         });
10591
10592         // `Math.sign` method implementation
10593         // https://tc39.es/ecma262/#sec-math.sign
10594         // eslint-disable-next-line es/no-math-sign -- safe
10595         var mathSign = Math.sign || function sign(x) {
10596           // eslint-disable-next-line no-self-compare -- NaN check
10597           return (x = +x) == 0 || x != x ? x : x < 0 ? -1 : 1;
10598         };
10599
10600         var $$x = _export;
10601         var sign$1 = mathSign;
10602
10603         // `Math.sign` method
10604         // https://tc39.es/ecma262/#sec-math.sign
10605         $$x({ target: 'Math', stat: true }, {
10606           sign: sign$1
10607         });
10608
10609         var epsilon$1 = 1e-6;
10610         var epsilon2$1 = 1e-12;
10611         var pi = Math.PI;
10612         var halfPi = pi / 2;
10613         var quarterPi = pi / 4;
10614         var tau = pi * 2;
10615         var degrees$1 = 180 / pi;
10616         var radians = pi / 180;
10617         var abs$2 = Math.abs;
10618         var atan = Math.atan;
10619         var atan2 = Math.atan2;
10620         var cos = Math.cos;
10621         var exp$2 = Math.exp;
10622         var log$1 = Math.log;
10623         var sin = Math.sin;
10624         var sign = Math.sign || function (x) {
10625           return x > 0 ? 1 : x < 0 ? -1 : 0;
10626         };
10627         var sqrt = Math.sqrt;
10628         var tan = Math.tan;
10629         function acos(x) {
10630           return x > 1 ? 0 : x < -1 ? pi : Math.acos(x);
10631         }
10632         function asin(x) {
10633           return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x);
10634         }
10635
10636         function noop$1() {}
10637
10638         function streamGeometry(geometry, stream) {
10639           if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
10640             streamGeometryType[geometry.type](geometry, stream);
10641           }
10642         }
10643
10644         var streamObjectType = {
10645           Feature: function Feature(object, stream) {
10646             streamGeometry(object.geometry, stream);
10647           },
10648           FeatureCollection: function FeatureCollection(object, stream) {
10649             var features = object.features,
10650                 i = -1,
10651                 n = features.length;
10652
10653             while (++i < n) {
10654               streamGeometry(features[i].geometry, stream);
10655             }
10656           }
10657         };
10658         var streamGeometryType = {
10659           Sphere: function Sphere(object, stream) {
10660             stream.sphere();
10661           },
10662           Point: function Point(object, stream) {
10663             object = object.coordinates;
10664             stream.point(object[0], object[1], object[2]);
10665           },
10666           MultiPoint: function MultiPoint(object, stream) {
10667             var coordinates = object.coordinates,
10668                 i = -1,
10669                 n = coordinates.length;
10670
10671             while (++i < n) {
10672               object = coordinates[i], stream.point(object[0], object[1], object[2]);
10673             }
10674           },
10675           LineString: function LineString(object, stream) {
10676             streamLine(object.coordinates, stream, 0);
10677           },
10678           MultiLineString: function MultiLineString(object, stream) {
10679             var coordinates = object.coordinates,
10680                 i = -1,
10681                 n = coordinates.length;
10682
10683             while (++i < n) {
10684               streamLine(coordinates[i], stream, 0);
10685             }
10686           },
10687           Polygon: function Polygon(object, stream) {
10688             streamPolygon(object.coordinates, stream);
10689           },
10690           MultiPolygon: function MultiPolygon(object, stream) {
10691             var coordinates = object.coordinates,
10692                 i = -1,
10693                 n = coordinates.length;
10694
10695             while (++i < n) {
10696               streamPolygon(coordinates[i], stream);
10697             }
10698           },
10699           GeometryCollection: function GeometryCollection(object, stream) {
10700             var geometries = object.geometries,
10701                 i = -1,
10702                 n = geometries.length;
10703
10704             while (++i < n) {
10705               streamGeometry(geometries[i], stream);
10706             }
10707           }
10708         };
10709
10710         function streamLine(coordinates, stream, closed) {
10711           var i = -1,
10712               n = coordinates.length - closed,
10713               coordinate;
10714           stream.lineStart();
10715
10716           while (++i < n) {
10717             coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
10718           }
10719
10720           stream.lineEnd();
10721         }
10722
10723         function streamPolygon(coordinates, stream) {
10724           var i = -1,
10725               n = coordinates.length;
10726           stream.polygonStart();
10727
10728           while (++i < n) {
10729             streamLine(coordinates[i], stream, 1);
10730           }
10731
10732           stream.polygonEnd();
10733         }
10734
10735         function d3_geoStream (object, stream) {
10736           if (object && streamObjectType.hasOwnProperty(object.type)) {
10737             streamObjectType[object.type](object, stream);
10738           } else {
10739             streamGeometry(object, stream);
10740           }
10741         }
10742
10743         var areaRingSum$1 = new Adder(); // hello?
10744
10745         var areaSum$1 = new Adder(),
10746             lambda00$1,
10747             phi00$1,
10748             lambda0$2,
10749             cosPhi0$1,
10750             sinPhi0$1;
10751         var areaStream$1 = {
10752           point: noop$1,
10753           lineStart: noop$1,
10754           lineEnd: noop$1,
10755           polygonStart: function polygonStart() {
10756             areaRingSum$1 = new Adder();
10757             areaStream$1.lineStart = areaRingStart$1;
10758             areaStream$1.lineEnd = areaRingEnd$1;
10759           },
10760           polygonEnd: function polygonEnd() {
10761             var areaRing = +areaRingSum$1;
10762             areaSum$1.add(areaRing < 0 ? tau + areaRing : areaRing);
10763             this.lineStart = this.lineEnd = this.point = noop$1;
10764           },
10765           sphere: function sphere() {
10766             areaSum$1.add(tau);
10767           }
10768         };
10769
10770         function areaRingStart$1() {
10771           areaStream$1.point = areaPointFirst$1;
10772         }
10773
10774         function areaRingEnd$1() {
10775           areaPoint$1(lambda00$1, phi00$1);
10776         }
10777
10778         function areaPointFirst$1(lambda, phi) {
10779           areaStream$1.point = areaPoint$1;
10780           lambda00$1 = lambda, phi00$1 = phi;
10781           lambda *= radians, phi *= radians;
10782           lambda0$2 = lambda, cosPhi0$1 = cos(phi = phi / 2 + quarterPi), sinPhi0$1 = sin(phi);
10783         }
10784
10785         function areaPoint$1(lambda, phi) {
10786           lambda *= radians, phi *= radians;
10787           phi = phi / 2 + quarterPi; // half the angular distance from south pole
10788           // Spherical excess E for a spherical triangle with vertices: south pole,
10789           // previous point, current point.  Uses a formula derived from Cagnoli’s
10790           // theorem.  See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
10791
10792           var dLambda = lambda - lambda0$2,
10793               sdLambda = dLambda >= 0 ? 1 : -1,
10794               adLambda = sdLambda * dLambda,
10795               cosPhi = cos(phi),
10796               sinPhi = sin(phi),
10797               k = sinPhi0$1 * sinPhi,
10798               u = cosPhi0$1 * cosPhi + k * cos(adLambda),
10799               v = k * sdLambda * sin(adLambda);
10800           areaRingSum$1.add(atan2(v, u)); // Advance the previous points.
10801
10802           lambda0$2 = lambda, cosPhi0$1 = cosPhi, sinPhi0$1 = sinPhi;
10803         }
10804
10805         function d3_geoArea (object) {
10806           areaSum$1 = new Adder();
10807           d3_geoStream(object, areaStream$1);
10808           return areaSum$1 * 2;
10809         }
10810
10811         function spherical(cartesian) {
10812           return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])];
10813         }
10814         function cartesian(spherical) {
10815           var lambda = spherical[0],
10816               phi = spherical[1],
10817               cosPhi = cos(phi);
10818           return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)];
10819         }
10820         function cartesianDot(a, b) {
10821           return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
10822         }
10823         function cartesianCross(a, b) {
10824           return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
10825         } // TODO return a
10826
10827         function cartesianAddInPlace(a, b) {
10828           a[0] += b[0], a[1] += b[1], a[2] += b[2];
10829         }
10830         function cartesianScale(vector, k) {
10831           return [vector[0] * k, vector[1] * k, vector[2] * k];
10832         } // TODO return d
10833
10834         function cartesianNormalizeInPlace(d) {
10835           var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
10836           d[0] /= l, d[1] /= l, d[2] /= l;
10837         }
10838
10839         var lambda0$1, phi0, lambda1, phi1, // bounds
10840         lambda2, // previous lambda-coordinate
10841         lambda00, phi00, // first point
10842         p0, // previous 3D point
10843         deltaSum, ranges, range;
10844         var boundsStream$1 = {
10845           point: boundsPoint$1,
10846           lineStart: boundsLineStart,
10847           lineEnd: boundsLineEnd,
10848           polygonStart: function polygonStart() {
10849             boundsStream$1.point = boundsRingPoint;
10850             boundsStream$1.lineStart = boundsRingStart;
10851             boundsStream$1.lineEnd = boundsRingEnd;
10852             deltaSum = new Adder();
10853             areaStream$1.polygonStart();
10854           },
10855           polygonEnd: function polygonEnd() {
10856             areaStream$1.polygonEnd();
10857             boundsStream$1.point = boundsPoint$1;
10858             boundsStream$1.lineStart = boundsLineStart;
10859             boundsStream$1.lineEnd = boundsLineEnd;
10860             if (areaRingSum$1 < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);else if (deltaSum > epsilon$1) phi1 = 90;else if (deltaSum < -epsilon$1) phi0 = -90;
10861             range[0] = lambda0$1, range[1] = lambda1;
10862           },
10863           sphere: function sphere() {
10864             lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
10865           }
10866         };
10867
10868         function boundsPoint$1(lambda, phi) {
10869           ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
10870           if (phi < phi0) phi0 = phi;
10871           if (phi > phi1) phi1 = phi;
10872         }
10873
10874         function linePoint(lambda, phi) {
10875           var p = cartesian([lambda * radians, phi * radians]);
10876
10877           if (p0) {
10878             var normal = cartesianCross(p0, p),
10879                 equatorial = [normal[1], -normal[0], 0],
10880                 inflection = cartesianCross(equatorial, normal);
10881             cartesianNormalizeInPlace(inflection);
10882             inflection = spherical(inflection);
10883             var delta = lambda - lambda2,
10884                 sign = delta > 0 ? 1 : -1,
10885                 lambdai = inflection[0] * degrees$1 * sign,
10886                 phii,
10887                 antimeridian = abs$2(delta) > 180;
10888
10889             if (antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
10890               phii = inflection[1] * degrees$1;
10891               if (phii > phi1) phi1 = phii;
10892             } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) {
10893               phii = -inflection[1] * degrees$1;
10894               if (phii < phi0) phi0 = phii;
10895             } else {
10896               if (phi < phi0) phi0 = phi;
10897               if (phi > phi1) phi1 = phi;
10898             }
10899
10900             if (antimeridian) {
10901               if (lambda < lambda2) {
10902                 if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
10903               } else {
10904                 if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
10905               }
10906             } else {
10907               if (lambda1 >= lambda0$1) {
10908                 if (lambda < lambda0$1) lambda0$1 = lambda;
10909                 if (lambda > lambda1) lambda1 = lambda;
10910               } else {
10911                 if (lambda > lambda2) {
10912                   if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
10913                 } else {
10914                   if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
10915                 }
10916               }
10917             }
10918           } else {
10919             ranges.push(range = [lambda0$1 = lambda, lambda1 = lambda]);
10920           }
10921
10922           if (phi < phi0) phi0 = phi;
10923           if (phi > phi1) phi1 = phi;
10924           p0 = p, lambda2 = lambda;
10925         }
10926
10927         function boundsLineStart() {
10928           boundsStream$1.point = linePoint;
10929         }
10930
10931         function boundsLineEnd() {
10932           range[0] = lambda0$1, range[1] = lambda1;
10933           boundsStream$1.point = boundsPoint$1;
10934           p0 = null;
10935         }
10936
10937         function boundsRingPoint(lambda, phi) {
10938           if (p0) {
10939             var delta = lambda - lambda2;
10940             deltaSum.add(abs$2(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
10941           } else {
10942             lambda00 = lambda, phi00 = phi;
10943           }
10944
10945           areaStream$1.point(lambda, phi);
10946           linePoint(lambda, phi);
10947         }
10948
10949         function boundsRingStart() {
10950           areaStream$1.lineStart();
10951         }
10952
10953         function boundsRingEnd() {
10954           boundsRingPoint(lambda00, phi00);
10955           areaStream$1.lineEnd();
10956           if (abs$2(deltaSum) > epsilon$1) lambda0$1 = -(lambda1 = 180);
10957           range[0] = lambda0$1, range[1] = lambda1;
10958           p0 = null;
10959         } // Finds the left-right distance between two longitudes.
10960         // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
10961         // the distance between ±180° to be 360°.
10962
10963
10964         function angle(lambda0, lambda1) {
10965           return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
10966         }
10967
10968         function rangeCompare(a, b) {
10969           return a[0] - b[0];
10970         }
10971
10972         function rangeContains(range, x) {
10973           return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
10974         }
10975
10976         function d3_geoBounds (feature) {
10977           var i, n, a, b, merged, deltaMax, delta;
10978           phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity);
10979           ranges = [];
10980           d3_geoStream(feature, boundsStream$1); // First, sort ranges by their minimum longitudes.
10981
10982           if (n = ranges.length) {
10983             ranges.sort(rangeCompare); // Then, merge any ranges that overlap.
10984
10985             for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
10986               b = ranges[i];
10987
10988               if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
10989                 if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
10990                 if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
10991               } else {
10992                 merged.push(a = b);
10993               }
10994             } // Finally, find the largest gap between the merged ranges.
10995             // The final bounding box will be the inverse of this gap.
10996
10997
10998             for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
10999               b = merged[i];
11000               if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1];
11001             }
11002           }
11003
11004           ranges = range = null;
11005           return lambda0$1 === Infinity || phi0 === Infinity ? [[NaN, NaN], [NaN, NaN]] : [[lambda0$1, phi0], [lambda1, phi1]];
11006         }
11007
11008         function compose (a, b) {
11009           function compose(x, y) {
11010             return x = a(x, y), b(x[0], x[1]);
11011           }
11012
11013           if (a.invert && b.invert) compose.invert = function (x, y) {
11014             return x = b.invert(x, y), x && a.invert(x[0], x[1]);
11015           };
11016           return compose;
11017         }
11018
11019         function rotationIdentity(lambda, phi) {
11020           return [abs$2(lambda) > pi ? lambda + Math.round(-lambda / tau) * tau : lambda, phi];
11021         }
11022
11023         rotationIdentity.invert = rotationIdentity;
11024         function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
11025           return (deltaLambda %= tau) ? deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) : rotationLambda(deltaLambda) : deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) : rotationIdentity;
11026         }
11027
11028         function forwardRotationLambda(deltaLambda) {
11029           return function (lambda, phi) {
11030             return lambda += deltaLambda, [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi];
11031           };
11032         }
11033
11034         function rotationLambda(deltaLambda) {
11035           var rotation = forwardRotationLambda(deltaLambda);
11036           rotation.invert = forwardRotationLambda(-deltaLambda);
11037           return rotation;
11038         }
11039
11040         function rotationPhiGamma(deltaPhi, deltaGamma) {
11041           var cosDeltaPhi = cos(deltaPhi),
11042               sinDeltaPhi = sin(deltaPhi),
11043               cosDeltaGamma = cos(deltaGamma),
11044               sinDeltaGamma = sin(deltaGamma);
11045
11046           function rotation(lambda, phi) {
11047             var cosPhi = cos(phi),
11048                 x = cos(lambda) * cosPhi,
11049                 y = sin(lambda) * cosPhi,
11050                 z = sin(phi),
11051                 k = z * cosDeltaPhi + x * sinDeltaPhi;
11052             return [atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), asin(k * cosDeltaGamma + y * sinDeltaGamma)];
11053           }
11054
11055           rotation.invert = function (lambda, phi) {
11056             var cosPhi = cos(phi),
11057                 x = cos(lambda) * cosPhi,
11058                 y = sin(lambda) * cosPhi,
11059                 z = sin(phi),
11060                 k = z * cosDeltaGamma - y * sinDeltaGamma;
11061             return [atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), asin(k * cosDeltaPhi - x * sinDeltaPhi)];
11062           };
11063
11064           return rotation;
11065         }
11066
11067         function rotation (rotate) {
11068           rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
11069
11070           function forward(coordinates) {
11071             coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
11072             return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
11073           }
11074
11075           forward.invert = function (coordinates) {
11076             coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
11077             return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
11078           };
11079
11080           return forward;
11081         }
11082
11083         function circleStream(stream, radius, delta, direction, t0, t1) {
11084           if (!delta) return;
11085           var cosRadius = cos(radius),
11086               sinRadius = sin(radius),
11087               step = direction * delta;
11088
11089           if (t0 == null) {
11090             t0 = radius + direction * tau;
11091             t1 = radius - step / 2;
11092           } else {
11093             t0 = circleRadius(cosRadius, t0);
11094             t1 = circleRadius(cosRadius, t1);
11095             if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau;
11096           }
11097
11098           for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
11099             point = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(t)]);
11100             stream.point(point[0], point[1]);
11101           }
11102         } // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
11103
11104         function circleRadius(cosRadius, point) {
11105           point = cartesian(point), point[0] -= cosRadius;
11106           cartesianNormalizeInPlace(point);
11107           var radius = acos(-point[1]);
11108           return ((-point[2] < 0 ? -radius : radius) + tau - epsilon$1) % tau;
11109         }
11110
11111         function clipBuffer () {
11112           var lines = [],
11113               line;
11114           return {
11115             point: function point(x, y, m) {
11116               line.push([x, y, m]);
11117             },
11118             lineStart: function lineStart() {
11119               lines.push(line = []);
11120             },
11121             lineEnd: noop$1,
11122             rejoin: function rejoin() {
11123               if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
11124             },
11125             result: function result() {
11126               var result = lines;
11127               lines = [];
11128               line = null;
11129               return result;
11130             }
11131           };
11132         }
11133
11134         function pointEqual (a, b) {
11135           return abs$2(a[0] - b[0]) < epsilon$1 && abs$2(a[1] - b[1]) < epsilon$1;
11136         }
11137
11138         function Intersection(point, points, other, entry) {
11139           this.x = point;
11140           this.z = points;
11141           this.o = other; // another intersection
11142
11143           this.e = entry; // is an entry?
11144
11145           this.v = false; // visited
11146
11147           this.n = this.p = null; // next & previous
11148         } // A generalized polygon clipping algorithm: given a polygon that has been cut
11149         // into its visible line segments, and rejoins the segments by interpolating
11150         // along the clip edge.
11151
11152
11153         function clipRejoin (segments, compareIntersection, startInside, interpolate, stream) {
11154           var subject = [],
11155               clip = [],
11156               i,
11157               n;
11158           segments.forEach(function (segment) {
11159             if ((n = segment.length - 1) <= 0) return;
11160             var n,
11161                 p0 = segment[0],
11162                 p1 = segment[n],
11163                 x;
11164
11165             if (pointEqual(p0, p1)) {
11166               if (!p0[2] && !p1[2]) {
11167                 stream.lineStart();
11168
11169                 for (i = 0; i < n; ++i) {
11170                   stream.point((p0 = segment[i])[0], p0[1]);
11171                 }
11172
11173                 stream.lineEnd();
11174                 return;
11175               } // handle degenerate cases by moving the point
11176
11177
11178               p1[0] += 2 * epsilon$1;
11179             }
11180
11181             subject.push(x = new Intersection(p0, segment, null, true));
11182             clip.push(x.o = new Intersection(p0, null, x, false));
11183             subject.push(x = new Intersection(p1, segment, null, false));
11184             clip.push(x.o = new Intersection(p1, null, x, true));
11185           });
11186           if (!subject.length) return;
11187           clip.sort(compareIntersection);
11188           link(subject);
11189           link(clip);
11190
11191           for (i = 0, n = clip.length; i < n; ++i) {
11192             clip[i].e = startInside = !startInside;
11193           }
11194
11195           var start = subject[0],
11196               points,
11197               point;
11198
11199           while (1) {
11200             // Find first unvisited intersection.
11201             var current = start,
11202                 isSubject = true;
11203
11204             while (current.v) {
11205               if ((current = current.n) === start) return;
11206             }
11207
11208             points = current.z;
11209             stream.lineStart();
11210
11211             do {
11212               current.v = current.o.v = true;
11213
11214               if (current.e) {
11215                 if (isSubject) {
11216                   for (i = 0, n = points.length; i < n; ++i) {
11217                     stream.point((point = points[i])[0], point[1]);
11218                   }
11219                 } else {
11220                   interpolate(current.x, current.n.x, 1, stream);
11221                 }
11222
11223                 current = current.n;
11224               } else {
11225                 if (isSubject) {
11226                   points = current.p.z;
11227
11228                   for (i = points.length - 1; i >= 0; --i) {
11229                     stream.point((point = points[i])[0], point[1]);
11230                   }
11231                 } else {
11232                   interpolate(current.x, current.p.x, -1, stream);
11233                 }
11234
11235                 current = current.p;
11236               }
11237
11238               current = current.o;
11239               points = current.z;
11240               isSubject = !isSubject;
11241             } while (!current.v);
11242
11243             stream.lineEnd();
11244           }
11245         }
11246
11247         function link(array) {
11248           if (!(n = array.length)) return;
11249           var n,
11250               i = 0,
11251               a = array[0],
11252               b;
11253
11254           while (++i < n) {
11255             a.n = b = array[i];
11256             b.p = a;
11257             a = b;
11258           }
11259
11260           a.n = b = array[0];
11261           b.p = a;
11262         }
11263
11264         function longitude(point) {
11265           if (abs$2(point[0]) <= pi) return point[0];else return sign(point[0]) * ((abs$2(point[0]) + pi) % tau - pi);
11266         }
11267
11268         function polygonContains (polygon, point) {
11269           var lambda = longitude(point),
11270               phi = point[1],
11271               sinPhi = sin(phi),
11272               normal = [sin(lambda), -cos(lambda), 0],
11273               angle = 0,
11274               winding = 0;
11275           var sum = new Adder();
11276           if (sinPhi === 1) phi = halfPi + epsilon$1;else if (sinPhi === -1) phi = -halfPi - epsilon$1;
11277
11278           for (var i = 0, n = polygon.length; i < n; ++i) {
11279             if (!(m = (ring = polygon[i]).length)) continue;
11280             var ring,
11281                 m,
11282                 point0 = ring[m - 1],
11283                 lambda0 = longitude(point0),
11284                 phi0 = point0[1] / 2 + quarterPi,
11285                 sinPhi0 = sin(phi0),
11286                 cosPhi0 = cos(phi0);
11287
11288             for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
11289               var point1 = ring[j],
11290                   lambda1 = longitude(point1),
11291                   phi1 = point1[1] / 2 + quarterPi,
11292                   sinPhi1 = sin(phi1),
11293                   cosPhi1 = cos(phi1),
11294                   delta = lambda1 - lambda0,
11295                   sign = delta >= 0 ? 1 : -1,
11296                   absDelta = sign * delta,
11297                   antimeridian = absDelta > pi,
11298                   k = sinPhi0 * sinPhi1;
11299               sum.add(atan2(k * sign * sin(absDelta), cosPhi0 * cosPhi1 + k * cos(absDelta)));
11300               angle += antimeridian ? delta + sign * tau : delta; // Are the longitudes either side of the point’s meridian (lambda),
11301               // and are the latitudes smaller than the parallel (phi)?
11302
11303               if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
11304                 var arc = cartesianCross(cartesian(point0), cartesian(point1));
11305                 cartesianNormalizeInPlace(arc);
11306                 var intersection = cartesianCross(normal, arc);
11307                 cartesianNormalizeInPlace(intersection);
11308                 var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);
11309
11310                 if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
11311                   winding += antimeridian ^ delta >= 0 ? 1 : -1;
11312                 }
11313               }
11314             }
11315           } // First, determine whether the South pole is inside or outside:
11316           //
11317           // It is inside if:
11318           // * the polygon winds around it in a clockwise direction.
11319           // * the polygon does not (cumulatively) wind around it, but has a negative
11320           //   (counter-clockwise) area.
11321           //
11322           // Second, count the (signed) number of times a segment crosses a lambda
11323           // from the point to the South pole.  If it is zero, then the point is the
11324           // same side as the South pole.
11325
11326
11327           return (angle < -epsilon$1 || angle < epsilon$1 && sum < -epsilon2$1) ^ winding & 1;
11328         }
11329
11330         function clip (pointVisible, clipLine, interpolate, start) {
11331           return function (sink) {
11332             var line = clipLine(sink),
11333                 ringBuffer = clipBuffer(),
11334                 ringSink = clipLine(ringBuffer),
11335                 polygonStarted = false,
11336                 polygon,
11337                 segments,
11338                 ring;
11339             var clip = {
11340               point: point,
11341               lineStart: lineStart,
11342               lineEnd: lineEnd,
11343               polygonStart: function polygonStart() {
11344                 clip.point = pointRing;
11345                 clip.lineStart = ringStart;
11346                 clip.lineEnd = ringEnd;
11347                 segments = [];
11348                 polygon = [];
11349               },
11350               polygonEnd: function polygonEnd() {
11351                 clip.point = point;
11352                 clip.lineStart = lineStart;
11353                 clip.lineEnd = lineEnd;
11354                 segments = merge$4(segments);
11355                 var startInside = polygonContains(polygon, start);
11356
11357                 if (segments.length) {
11358                   if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
11359                   clipRejoin(segments, compareIntersection, startInside, interpolate, sink);
11360                 } else if (startInside) {
11361                   if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
11362                   sink.lineStart();
11363                   interpolate(null, null, 1, sink);
11364                   sink.lineEnd();
11365                 }
11366
11367                 if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
11368                 segments = polygon = null;
11369               },
11370               sphere: function sphere() {
11371                 sink.polygonStart();
11372                 sink.lineStart();
11373                 interpolate(null, null, 1, sink);
11374                 sink.lineEnd();
11375                 sink.polygonEnd();
11376               }
11377             };
11378
11379             function point(lambda, phi) {
11380               if (pointVisible(lambda, phi)) sink.point(lambda, phi);
11381             }
11382
11383             function pointLine(lambda, phi) {
11384               line.point(lambda, phi);
11385             }
11386
11387             function lineStart() {
11388               clip.point = pointLine;
11389               line.lineStart();
11390             }
11391
11392             function lineEnd() {
11393               clip.point = point;
11394               line.lineEnd();
11395             }
11396
11397             function pointRing(lambda, phi) {
11398               ring.push([lambda, phi]);
11399               ringSink.point(lambda, phi);
11400             }
11401
11402             function ringStart() {
11403               ringSink.lineStart();
11404               ring = [];
11405             }
11406
11407             function ringEnd() {
11408               pointRing(ring[0][0], ring[0][1]);
11409               ringSink.lineEnd();
11410               var clean = ringSink.clean(),
11411                   ringSegments = ringBuffer.result(),
11412                   i,
11413                   n = ringSegments.length,
11414                   m,
11415                   segment,
11416                   point;
11417               ring.pop();
11418               polygon.push(ring);
11419               ring = null;
11420               if (!n) return; // No intersections.
11421
11422               if (clean & 1) {
11423                 segment = ringSegments[0];
11424
11425                 if ((m = segment.length - 1) > 0) {
11426                   if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
11427                   sink.lineStart();
11428
11429                   for (i = 0; i < m; ++i) {
11430                     sink.point((point = segment[i])[0], point[1]);
11431                   }
11432
11433                   sink.lineEnd();
11434                 }
11435
11436                 return;
11437               } // Rejoin connected segments.
11438               // TODO reuse ringBuffer.rejoin()?
11439
11440
11441               if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
11442               segments.push(ringSegments.filter(validSegment));
11443             }
11444
11445             return clip;
11446           };
11447         }
11448
11449         function validSegment(segment) {
11450           return segment.length > 1;
11451         } // Intersections are sorted along the clip edge. For both antimeridian cutting
11452         // and circle clipping, the same comparison is used.
11453
11454
11455         function compareIntersection(a, b) {
11456           return ((a = a.x)[0] < 0 ? a[1] - halfPi - epsilon$1 : halfPi - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon$1 : halfPi - b[1]);
11457         }
11458
11459         var clipAntimeridian = clip(function () {
11460           return true;
11461         }, clipAntimeridianLine, clipAntimeridianInterpolate, [-pi, -halfPi]); // Takes a line and cuts into visible segments. Return values: 0 - there were
11462         // intersections or the line was empty; 1 - no intersections; 2 - there were
11463         // intersections, and the first and last segments should be rejoined.
11464
11465         function clipAntimeridianLine(stream) {
11466           var lambda0 = NaN,
11467               phi0 = NaN,
11468               sign0 = NaN,
11469               _clean; // no intersections
11470
11471
11472           return {
11473             lineStart: function lineStart() {
11474               stream.lineStart();
11475               _clean = 1;
11476             },
11477             point: function point(lambda1, phi1) {
11478               var sign1 = lambda1 > 0 ? pi : -pi,
11479                   delta = abs$2(lambda1 - lambda0);
11480
11481               if (abs$2(delta - pi) < epsilon$1) {
11482                 // line crosses a pole
11483                 stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi);
11484                 stream.point(sign0, phi0);
11485                 stream.lineEnd();
11486                 stream.lineStart();
11487                 stream.point(sign1, phi0);
11488                 stream.point(lambda1, phi0);
11489                 _clean = 0;
11490               } else if (sign0 !== sign1 && delta >= pi) {
11491                 // line crosses antimeridian
11492                 if (abs$2(lambda0 - sign0) < epsilon$1) lambda0 -= sign0 * epsilon$1; // handle degeneracies
11493
11494                 if (abs$2(lambda1 - sign1) < epsilon$1) lambda1 -= sign1 * epsilon$1;
11495                 phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
11496                 stream.point(sign0, phi0);
11497                 stream.lineEnd();
11498                 stream.lineStart();
11499                 stream.point(sign1, phi0);
11500                 _clean = 0;
11501               }
11502
11503               stream.point(lambda0 = lambda1, phi0 = phi1);
11504               sign0 = sign1;
11505             },
11506             lineEnd: function lineEnd() {
11507               stream.lineEnd();
11508               lambda0 = phi0 = NaN;
11509             },
11510             clean: function clean() {
11511               return 2 - _clean; // if intersections, rejoin first and last segments
11512             }
11513           };
11514         }
11515
11516         function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
11517           var cosPhi0,
11518               cosPhi1,
11519               sinLambda0Lambda1 = sin(lambda0 - lambda1);
11520           return abs$2(sinLambda0Lambda1) > epsilon$1 ? atan((sin(phi0) * (cosPhi1 = cos(phi1)) * sin(lambda1) - sin(phi1) * (cosPhi0 = cos(phi0)) * sin(lambda0)) / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) : (phi0 + phi1) / 2;
11521         }
11522
11523         function clipAntimeridianInterpolate(from, to, direction, stream) {
11524           var phi;
11525
11526           if (from == null) {
11527             phi = direction * halfPi;
11528             stream.point(-pi, phi);
11529             stream.point(0, phi);
11530             stream.point(pi, phi);
11531             stream.point(pi, 0);
11532             stream.point(pi, -phi);
11533             stream.point(0, -phi);
11534             stream.point(-pi, -phi);
11535             stream.point(-pi, 0);
11536             stream.point(-pi, phi);
11537           } else if (abs$2(from[0] - to[0]) > epsilon$1) {
11538             var lambda = from[0] < to[0] ? pi : -pi;
11539             phi = direction * lambda / 2;
11540             stream.point(-lambda, phi);
11541             stream.point(0, phi);
11542             stream.point(lambda, phi);
11543           } else {
11544             stream.point(to[0], to[1]);
11545           }
11546         }
11547
11548         function clipCircle (radius) {
11549           var cr = cos(radius),
11550               delta = 6 * radians,
11551               smallRadius = cr > 0,
11552               notHemisphere = abs$2(cr) > epsilon$1; // TODO optimise for this common case
11553
11554           function interpolate(from, to, direction, stream) {
11555             circleStream(stream, radius, delta, direction, from, to);
11556           }
11557
11558           function visible(lambda, phi) {
11559             return cos(lambda) * cos(phi) > cr;
11560           } // Takes a line and cuts into visible segments. Return values used for polygon
11561           // clipping: 0 - there were intersections or the line was empty; 1 - no
11562           // intersections 2 - there were intersections, and the first and last segments
11563           // should be rejoined.
11564
11565
11566           function clipLine(stream) {
11567             var point0, // previous point
11568             c0, // code for previous point
11569             v0, // visibility of previous point
11570             v00, // visibility of first point
11571             _clean; // no intersections
11572
11573
11574             return {
11575               lineStart: function lineStart() {
11576                 v00 = v0 = false;
11577                 _clean = 1;
11578               },
11579               point: function point(lambda, phi) {
11580                 var point1 = [lambda, phi],
11581                     point2,
11582                     v = visible(lambda, phi),
11583                     c = smallRadius ? v ? 0 : code(lambda, phi) : v ? code(lambda + (lambda < 0 ? pi : -pi), phi) : 0;
11584                 if (!point0 && (v00 = v0 = v)) stream.lineStart();
11585
11586                 if (v !== v0) {
11587                   point2 = intersect(point0, point1);
11588                   if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2)) point1[2] = 1;
11589                 }
11590
11591                 if (v !== v0) {
11592                   _clean = 0;
11593
11594                   if (v) {
11595                     // outside going in
11596                     stream.lineStart();
11597                     point2 = intersect(point1, point0);
11598                     stream.point(point2[0], point2[1]);
11599                   } else {
11600                     // inside going out
11601                     point2 = intersect(point0, point1);
11602                     stream.point(point2[0], point2[1], 2);
11603                     stream.lineEnd();
11604                   }
11605
11606                   point0 = point2;
11607                 } else if (notHemisphere && point0 && smallRadius ^ v) {
11608                   var t; // If the codes for two points are different, or are both zero,
11609                   // and there this segment intersects with the small circle.
11610
11611                   if (!(c & c0) && (t = intersect(point1, point0, true))) {
11612                     _clean = 0;
11613
11614                     if (smallRadius) {
11615                       stream.lineStart();
11616                       stream.point(t[0][0], t[0][1]);
11617                       stream.point(t[1][0], t[1][1]);
11618                       stream.lineEnd();
11619                     } else {
11620                       stream.point(t[1][0], t[1][1]);
11621                       stream.lineEnd();
11622                       stream.lineStart();
11623                       stream.point(t[0][0], t[0][1], 3);
11624                     }
11625                   }
11626                 }
11627
11628                 if (v && (!point0 || !pointEqual(point0, point1))) {
11629                   stream.point(point1[0], point1[1]);
11630                 }
11631
11632                 point0 = point1, v0 = v, c0 = c;
11633               },
11634               lineEnd: function lineEnd() {
11635                 if (v0) stream.lineEnd();
11636                 point0 = null;
11637               },
11638               // Rejoin first and last segments if there were intersections and the first
11639               // and last points were visible.
11640               clean: function clean() {
11641                 return _clean | (v00 && v0) << 1;
11642               }
11643             };
11644           } // Intersects the great circle between a and b with the clip circle.
11645
11646
11647           function intersect(a, b, two) {
11648             var pa = cartesian(a),
11649                 pb = cartesian(b); // We have two planes, n1.p = d1 and n2.p = d2.
11650             // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
11651
11652             var n1 = [1, 0, 0],
11653                 // normal
11654             n2 = cartesianCross(pa, pb),
11655                 n2n2 = cartesianDot(n2, n2),
11656                 n1n2 = n2[0],
11657                 // cartesianDot(n1, n2),
11658             determinant = n2n2 - n1n2 * n1n2; // Two polar points.
11659
11660             if (!determinant) return !two && a;
11661             var c1 = cr * n2n2 / determinant,
11662                 c2 = -cr * n1n2 / determinant,
11663                 n1xn2 = cartesianCross(n1, n2),
11664                 A = cartesianScale(n1, c1),
11665                 B = cartesianScale(n2, c2);
11666             cartesianAddInPlace(A, B); // Solve |p(t)|^2 = 1.
11667
11668             var u = n1xn2,
11669                 w = cartesianDot(A, u),
11670                 uu = cartesianDot(u, u),
11671                 t2 = w * w - uu * (cartesianDot(A, A) - 1);
11672             if (t2 < 0) return;
11673             var t = sqrt(t2),
11674                 q = cartesianScale(u, (-w - t) / uu);
11675             cartesianAddInPlace(q, A);
11676             q = spherical(q);
11677             if (!two) return q; // Two intersection points.
11678
11679             var lambda0 = a[0],
11680                 lambda1 = b[0],
11681                 phi0 = a[1],
11682                 phi1 = b[1],
11683                 z;
11684             if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
11685             var delta = lambda1 - lambda0,
11686                 polar = abs$2(delta - pi) < epsilon$1,
11687                 meridian = polar || delta < epsilon$1;
11688             if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z; // Check that the first point is between a and b.
11689
11690             if (meridian ? polar ? phi0 + phi1 > 0 ^ q[1] < (abs$2(q[0] - lambda0) < epsilon$1 ? phi0 : phi1) : phi0 <= q[1] && q[1] <= phi1 : delta > pi ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
11691               var q1 = cartesianScale(u, (-w + t) / uu);
11692               cartesianAddInPlace(q1, A);
11693               return [q, spherical(q1)];
11694             }
11695           } // Generates a 4-bit vector representing the location of a point relative to
11696           // the small circle's bounding box.
11697
11698
11699           function code(lambda, phi) {
11700             var r = smallRadius ? radius : pi - radius,
11701                 code = 0;
11702             if (lambda < -r) code |= 1; // left
11703             else if (lambda > r) code |= 2; // right
11704
11705             if (phi < -r) code |= 4; // below
11706             else if (phi > r) code |= 8; // above
11707
11708             return code;
11709           }
11710
11711           return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi, radius - pi]);
11712         }
11713
11714         function clipLine (a, b, x0, y0, x1, y1) {
11715           var ax = a[0],
11716               ay = a[1],
11717               bx = b[0],
11718               by = b[1],
11719               t0 = 0,
11720               t1 = 1,
11721               dx = bx - ax,
11722               dy = by - ay,
11723               r;
11724           r = x0 - ax;
11725           if (!dx && r > 0) return;
11726           r /= dx;
11727
11728           if (dx < 0) {
11729             if (r < t0) return;
11730             if (r < t1) t1 = r;
11731           } else if (dx > 0) {
11732             if (r > t1) return;
11733             if (r > t0) t0 = r;
11734           }
11735
11736           r = x1 - ax;
11737           if (!dx && r < 0) return;
11738           r /= dx;
11739
11740           if (dx < 0) {
11741             if (r > t1) return;
11742             if (r > t0) t0 = r;
11743           } else if (dx > 0) {
11744             if (r < t0) return;
11745             if (r < t1) t1 = r;
11746           }
11747
11748           r = y0 - ay;
11749           if (!dy && r > 0) return;
11750           r /= dy;
11751
11752           if (dy < 0) {
11753             if (r < t0) return;
11754             if (r < t1) t1 = r;
11755           } else if (dy > 0) {
11756             if (r > t1) return;
11757             if (r > t0) t0 = r;
11758           }
11759
11760           r = y1 - ay;
11761           if (!dy && r < 0) return;
11762           r /= dy;
11763
11764           if (dy < 0) {
11765             if (r > t1) return;
11766             if (r > t0) t0 = r;
11767           } else if (dy > 0) {
11768             if (r < t0) return;
11769             if (r < t1) t1 = r;
11770           }
11771
11772           if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
11773           if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
11774           return true;
11775         }
11776
11777         var clipMax = 1e9,
11778             clipMin = -clipMax; // TODO Use d3-polygon’s polygonContains here for the ring check?
11779         // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
11780
11781         function clipRectangle(x0, y0, x1, y1) {
11782           function visible(x, y) {
11783             return x0 <= x && x <= x1 && y0 <= y && y <= y1;
11784           }
11785
11786           function interpolate(from, to, direction, stream) {
11787             var a = 0,
11788                 a1 = 0;
11789
11790             if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoint(from, to) < 0 ^ direction > 0) {
11791               do {
11792                 stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
11793               } while ((a = (a + direction + 4) % 4) !== a1);
11794             } else {
11795               stream.point(to[0], to[1]);
11796             }
11797           }
11798
11799           function corner(p, direction) {
11800             return abs$2(p[0] - x0) < epsilon$1 ? direction > 0 ? 0 : 3 : abs$2(p[0] - x1) < epsilon$1 ? direction > 0 ? 2 : 1 : abs$2(p[1] - y0) < epsilon$1 ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
11801           }
11802
11803           function compareIntersection(a, b) {
11804             return comparePoint(a.x, b.x);
11805           }
11806
11807           function comparePoint(a, b) {
11808             var ca = corner(a, 1),
11809                 cb = corner(b, 1);
11810             return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
11811           }
11812
11813           return function (stream) {
11814             var activeStream = stream,
11815                 bufferStream = clipBuffer(),
11816                 segments,
11817                 polygon,
11818                 ring,
11819                 x__,
11820                 y__,
11821                 v__,
11822                 // first point
11823             x_,
11824                 y_,
11825                 v_,
11826                 // previous point
11827             first,
11828                 clean;
11829             var clipStream = {
11830               point: point,
11831               lineStart: lineStart,
11832               lineEnd: lineEnd,
11833               polygonStart: polygonStart,
11834               polygonEnd: polygonEnd
11835             };
11836
11837             function point(x, y) {
11838               if (visible(x, y)) activeStream.point(x, y);
11839             }
11840
11841             function polygonInside() {
11842               var winding = 0;
11843
11844               for (var i = 0, n = polygon.length; i < n; ++i) {
11845                 for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
11846                   a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
11847
11848                   if (a1 <= y1) {
11849                     if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding;
11850                   } else {
11851                     if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding;
11852                   }
11853                 }
11854               }
11855
11856               return winding;
11857             } // Buffer geometry within a polygon and then clip it en masse.
11858
11859
11860             function polygonStart() {
11861               activeStream = bufferStream, segments = [], polygon = [], clean = true;
11862             }
11863
11864             function polygonEnd() {
11865               var startInside = polygonInside(),
11866                   cleanInside = clean && startInside,
11867                   visible = (segments = merge$4(segments)).length;
11868
11869               if (cleanInside || visible) {
11870                 stream.polygonStart();
11871
11872                 if (cleanInside) {
11873                   stream.lineStart();
11874                   interpolate(null, null, 1, stream);
11875                   stream.lineEnd();
11876                 }
11877
11878                 if (visible) {
11879                   clipRejoin(segments, compareIntersection, startInside, interpolate, stream);
11880                 }
11881
11882                 stream.polygonEnd();
11883               }
11884
11885               activeStream = stream, segments = polygon = ring = null;
11886             }
11887
11888             function lineStart() {
11889               clipStream.point = linePoint;
11890               if (polygon) polygon.push(ring = []);
11891               first = true;
11892               v_ = false;
11893               x_ = y_ = NaN;
11894             } // TODO rather than special-case polygons, simply handle them separately.
11895             // Ideally, coincident intersection points should be jittered to avoid
11896             // clipping issues.
11897
11898
11899             function lineEnd() {
11900               if (segments) {
11901                 linePoint(x__, y__);
11902                 if (v__ && v_) bufferStream.rejoin();
11903                 segments.push(bufferStream.result());
11904               }
11905
11906               clipStream.point = point;
11907               if (v_) activeStream.lineEnd();
11908             }
11909
11910             function linePoint(x, y) {
11911               var v = visible(x, y);
11912               if (polygon) ring.push([x, y]);
11913
11914               if (first) {
11915                 x__ = x, y__ = y, v__ = v;
11916                 first = false;
11917
11918                 if (v) {
11919                   activeStream.lineStart();
11920                   activeStream.point(x, y);
11921                 }
11922               } else {
11923                 if (v && v_) activeStream.point(x, y);else {
11924                   var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
11925                       b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
11926
11927                   if (clipLine(a, b, x0, y0, x1, y1)) {
11928                     if (!v_) {
11929                       activeStream.lineStart();
11930                       activeStream.point(a[0], a[1]);
11931                     }
11932
11933                     activeStream.point(b[0], b[1]);
11934                     if (!v) activeStream.lineEnd();
11935                     clean = false;
11936                   } else if (v) {
11937                     activeStream.lineStart();
11938                     activeStream.point(x, y);
11939                     clean = false;
11940                   }
11941                 }
11942               }
11943
11944               x_ = x, y_ = y, v_ = v;
11945             }
11946
11947             return clipStream;
11948           };
11949         }
11950
11951         var lengthSum$1, lambda0, sinPhi0, cosPhi0;
11952         var lengthStream$1 = {
11953           sphere: noop$1,
11954           point: noop$1,
11955           lineStart: lengthLineStart,
11956           lineEnd: noop$1,
11957           polygonStart: noop$1,
11958           polygonEnd: noop$1
11959         };
11960
11961         function lengthLineStart() {
11962           lengthStream$1.point = lengthPointFirst$1;
11963           lengthStream$1.lineEnd = lengthLineEnd;
11964         }
11965
11966         function lengthLineEnd() {
11967           lengthStream$1.point = lengthStream$1.lineEnd = noop$1;
11968         }
11969
11970         function lengthPointFirst$1(lambda, phi) {
11971           lambda *= radians, phi *= radians;
11972           lambda0 = lambda, sinPhi0 = sin(phi), cosPhi0 = cos(phi);
11973           lengthStream$1.point = lengthPoint$1;
11974         }
11975
11976         function lengthPoint$1(lambda, phi) {
11977           lambda *= radians, phi *= radians;
11978           var sinPhi = sin(phi),
11979               cosPhi = cos(phi),
11980               delta = abs$2(lambda - lambda0),
11981               cosDelta = cos(delta),
11982               sinDelta = sin(delta),
11983               x = cosPhi * sinDelta,
11984               y = cosPhi0 * sinPhi - sinPhi0 * cosPhi * cosDelta,
11985               z = sinPhi0 * sinPhi + cosPhi0 * cosPhi * cosDelta;
11986           lengthSum$1.add(atan2(sqrt(x * x + y * y), z));
11987           lambda0 = lambda, sinPhi0 = sinPhi, cosPhi0 = cosPhi;
11988         }
11989
11990         function d3_geoLength (object) {
11991           lengthSum$1 = new Adder();
11992           d3_geoStream(object, lengthStream$1);
11993           return +lengthSum$1;
11994         }
11995
11996         var identity$4 = (function (x) {
11997           return x;
11998         });
11999
12000         var areaSum = new Adder(),
12001             areaRingSum = new Adder(),
12002             x00$2,
12003             y00$2,
12004             x0$3,
12005             y0$3;
12006         var areaStream = {
12007           point: noop$1,
12008           lineStart: noop$1,
12009           lineEnd: noop$1,
12010           polygonStart: function polygonStart() {
12011             areaStream.lineStart = areaRingStart;
12012             areaStream.lineEnd = areaRingEnd;
12013           },
12014           polygonEnd: function polygonEnd() {
12015             areaStream.lineStart = areaStream.lineEnd = areaStream.point = noop$1;
12016             areaSum.add(abs$2(areaRingSum));
12017             areaRingSum = new Adder();
12018           },
12019           result: function result() {
12020             var area = areaSum / 2;
12021             areaSum = new Adder();
12022             return area;
12023           }
12024         };
12025
12026         function areaRingStart() {
12027           areaStream.point = areaPointFirst;
12028         }
12029
12030         function areaPointFirst(x, y) {
12031           areaStream.point = areaPoint;
12032           x00$2 = x0$3 = x, y00$2 = y0$3 = y;
12033         }
12034
12035         function areaPoint(x, y) {
12036           areaRingSum.add(y0$3 * x - x0$3 * y);
12037           x0$3 = x, y0$3 = y;
12038         }
12039
12040         function areaRingEnd() {
12041           areaPoint(x00$2, y00$2);
12042         }
12043
12044         var x0$2 = Infinity,
12045             y0$2 = x0$2,
12046             x1 = -x0$2,
12047             y1 = x1;
12048         var boundsStream = {
12049           point: boundsPoint,
12050           lineStart: noop$1,
12051           lineEnd: noop$1,
12052           polygonStart: noop$1,
12053           polygonEnd: noop$1,
12054           result: function result() {
12055             var bounds = [[x0$2, y0$2], [x1, y1]];
12056             x1 = y1 = -(y0$2 = x0$2 = Infinity);
12057             return bounds;
12058           }
12059         };
12060
12061         function boundsPoint(x, y) {
12062           if (x < x0$2) x0$2 = x;
12063           if (x > x1) x1 = x;
12064           if (y < y0$2) y0$2 = y;
12065           if (y > y1) y1 = y;
12066         }
12067
12068         var X0 = 0,
12069             Y0 = 0,
12070             Z0 = 0,
12071             X1 = 0,
12072             Y1 = 0,
12073             Z1 = 0,
12074             X2 = 0,
12075             Y2 = 0,
12076             Z2 = 0,
12077             x00$1,
12078             y00$1,
12079             x0$1,
12080             y0$1;
12081         var centroidStream = {
12082           point: centroidPoint,
12083           lineStart: centroidLineStart,
12084           lineEnd: centroidLineEnd,
12085           polygonStart: function polygonStart() {
12086             centroidStream.lineStart = centroidRingStart;
12087             centroidStream.lineEnd = centroidRingEnd;
12088           },
12089           polygonEnd: function polygonEnd() {
12090             centroidStream.point = centroidPoint;
12091             centroidStream.lineStart = centroidLineStart;
12092             centroidStream.lineEnd = centroidLineEnd;
12093           },
12094           result: function result() {
12095             var centroid = Z2 ? [X2 / Z2, Y2 / Z2] : Z1 ? [X1 / Z1, Y1 / Z1] : Z0 ? [X0 / Z0, Y0 / Z0] : [NaN, NaN];
12096             X0 = Y0 = Z0 = X1 = Y1 = Z1 = X2 = Y2 = Z2 = 0;
12097             return centroid;
12098           }
12099         };
12100
12101         function centroidPoint(x, y) {
12102           X0 += x;
12103           Y0 += y;
12104           ++Z0;
12105         }
12106
12107         function centroidLineStart() {
12108           centroidStream.point = centroidPointFirstLine;
12109         }
12110
12111         function centroidPointFirstLine(x, y) {
12112           centroidStream.point = centroidPointLine;
12113           centroidPoint(x0$1 = x, y0$1 = y);
12114         }
12115
12116         function centroidPointLine(x, y) {
12117           var dx = x - x0$1,
12118               dy = y - y0$1,
12119               z = sqrt(dx * dx + dy * dy);
12120           X1 += z * (x0$1 + x) / 2;
12121           Y1 += z * (y0$1 + y) / 2;
12122           Z1 += z;
12123           centroidPoint(x0$1 = x, y0$1 = y);
12124         }
12125
12126         function centroidLineEnd() {
12127           centroidStream.point = centroidPoint;
12128         }
12129
12130         function centroidRingStart() {
12131           centroidStream.point = centroidPointFirstRing;
12132         }
12133
12134         function centroidRingEnd() {
12135           centroidPointRing(x00$1, y00$1);
12136         }
12137
12138         function centroidPointFirstRing(x, y) {
12139           centroidStream.point = centroidPointRing;
12140           centroidPoint(x00$1 = x0$1 = x, y00$1 = y0$1 = y);
12141         }
12142
12143         function centroidPointRing(x, y) {
12144           var dx = x - x0$1,
12145               dy = y - y0$1,
12146               z = sqrt(dx * dx + dy * dy);
12147           X1 += z * (x0$1 + x) / 2;
12148           Y1 += z * (y0$1 + y) / 2;
12149           Z1 += z;
12150           z = y0$1 * x - x0$1 * y;
12151           X2 += z * (x0$1 + x);
12152           Y2 += z * (y0$1 + y);
12153           Z2 += z * 3;
12154           centroidPoint(x0$1 = x, y0$1 = y);
12155         }
12156
12157         function PathContext(context) {
12158           this._context = context;
12159         }
12160         PathContext.prototype = {
12161           _radius: 4.5,
12162           pointRadius: function pointRadius(_) {
12163             return this._radius = _, this;
12164           },
12165           polygonStart: function polygonStart() {
12166             this._line = 0;
12167           },
12168           polygonEnd: function polygonEnd() {
12169             this._line = NaN;
12170           },
12171           lineStart: function lineStart() {
12172             this._point = 0;
12173           },
12174           lineEnd: function lineEnd() {
12175             if (this._line === 0) this._context.closePath();
12176             this._point = NaN;
12177           },
12178           point: function point(x, y) {
12179             switch (this._point) {
12180               case 0:
12181                 {
12182                   this._context.moveTo(x, y);
12183
12184                   this._point = 1;
12185                   break;
12186                 }
12187
12188               case 1:
12189                 {
12190                   this._context.lineTo(x, y);
12191
12192                   break;
12193                 }
12194
12195               default:
12196                 {
12197                   this._context.moveTo(x + this._radius, y);
12198
12199                   this._context.arc(x, y, this._radius, 0, tau);
12200
12201                   break;
12202                 }
12203             }
12204           },
12205           result: noop$1
12206         };
12207
12208         var lengthSum = new Adder(),
12209             lengthRing,
12210             x00,
12211             y00,
12212             x0,
12213             y0;
12214         var lengthStream = {
12215           point: noop$1,
12216           lineStart: function lineStart() {
12217             lengthStream.point = lengthPointFirst;
12218           },
12219           lineEnd: function lineEnd() {
12220             if (lengthRing) lengthPoint(x00, y00);
12221             lengthStream.point = noop$1;
12222           },
12223           polygonStart: function polygonStart() {
12224             lengthRing = true;
12225           },
12226           polygonEnd: function polygonEnd() {
12227             lengthRing = null;
12228           },
12229           result: function result() {
12230             var length = +lengthSum;
12231             lengthSum = new Adder();
12232             return length;
12233           }
12234         };
12235
12236         function lengthPointFirst(x, y) {
12237           lengthStream.point = lengthPoint;
12238           x00 = x0 = x, y00 = y0 = y;
12239         }
12240
12241         function lengthPoint(x, y) {
12242           x0 -= x, y0 -= y;
12243           lengthSum.add(sqrt(x0 * x0 + y0 * y0));
12244           x0 = x, y0 = y;
12245         }
12246
12247         function PathString() {
12248           this._string = [];
12249         }
12250         PathString.prototype = {
12251           _radius: 4.5,
12252           _circle: circle(4.5),
12253           pointRadius: function pointRadius(_) {
12254             if ((_ = +_) !== this._radius) this._radius = _, this._circle = null;
12255             return this;
12256           },
12257           polygonStart: function polygonStart() {
12258             this._line = 0;
12259           },
12260           polygonEnd: function polygonEnd() {
12261             this._line = NaN;
12262           },
12263           lineStart: function lineStart() {
12264             this._point = 0;
12265           },
12266           lineEnd: function lineEnd() {
12267             if (this._line === 0) this._string.push("Z");
12268             this._point = NaN;
12269           },
12270           point: function point(x, y) {
12271             switch (this._point) {
12272               case 0:
12273                 {
12274                   this._string.push("M", x, ",", y);
12275
12276                   this._point = 1;
12277                   break;
12278                 }
12279
12280               case 1:
12281                 {
12282                   this._string.push("L", x, ",", y);
12283
12284                   break;
12285                 }
12286
12287               default:
12288                 {
12289                   if (this._circle == null) this._circle = circle(this._radius);
12290
12291                   this._string.push("M", x, ",", y, this._circle);
12292
12293                   break;
12294                 }
12295             }
12296           },
12297           result: function result() {
12298             if (this._string.length) {
12299               var result = this._string.join("");
12300
12301               this._string = [];
12302               return result;
12303             } else {
12304               return null;
12305             }
12306           }
12307         };
12308
12309         function circle(radius) {
12310           return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
12311         }
12312
12313         function d3_geoPath (projection, context) {
12314           var pointRadius = 4.5,
12315               projectionStream,
12316               contextStream;
12317
12318           function path(object) {
12319             if (object) {
12320               if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
12321               d3_geoStream(object, projectionStream(contextStream));
12322             }
12323
12324             return contextStream.result();
12325           }
12326
12327           path.area = function (object) {
12328             d3_geoStream(object, projectionStream(areaStream));
12329             return areaStream.result();
12330           };
12331
12332           path.measure = function (object) {
12333             d3_geoStream(object, projectionStream(lengthStream));
12334             return lengthStream.result();
12335           };
12336
12337           path.bounds = function (object) {
12338             d3_geoStream(object, projectionStream(boundsStream));
12339             return boundsStream.result();
12340           };
12341
12342           path.centroid = function (object) {
12343             d3_geoStream(object, projectionStream(centroidStream));
12344             return centroidStream.result();
12345           };
12346
12347           path.projection = function (_) {
12348             return arguments.length ? (projectionStream = _ == null ? (projection = null, identity$4) : (projection = _).stream, path) : projection;
12349           };
12350
12351           path.context = function (_) {
12352             if (!arguments.length) return context;
12353             contextStream = _ == null ? (context = null, new PathString()) : new PathContext(context = _);
12354             if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
12355             return path;
12356           };
12357
12358           path.pointRadius = function (_) {
12359             if (!arguments.length) return pointRadius;
12360             pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
12361             return path;
12362           };
12363
12364           return path.projection(projection).context(context);
12365         }
12366
12367         function d3_geoTransform (methods) {
12368           return {
12369             stream: transformer$1(methods)
12370           };
12371         }
12372         function transformer$1(methods) {
12373           return function (stream) {
12374             var s = new TransformStream();
12375
12376             for (var key in methods) {
12377               s[key] = methods[key];
12378             }
12379
12380             s.stream = stream;
12381             return s;
12382           };
12383         }
12384
12385         function TransformStream() {}
12386
12387         TransformStream.prototype = {
12388           constructor: TransformStream,
12389           point: function point(x, y) {
12390             this.stream.point(x, y);
12391           },
12392           sphere: function sphere() {
12393             this.stream.sphere();
12394           },
12395           lineStart: function lineStart() {
12396             this.stream.lineStart();
12397           },
12398           lineEnd: function lineEnd() {
12399             this.stream.lineEnd();
12400           },
12401           polygonStart: function polygonStart() {
12402             this.stream.polygonStart();
12403           },
12404           polygonEnd: function polygonEnd() {
12405             this.stream.polygonEnd();
12406           }
12407         };
12408
12409         function fit(projection, fitBounds, object) {
12410           var clip = projection.clipExtent && projection.clipExtent();
12411           projection.scale(150).translate([0, 0]);
12412           if (clip != null) projection.clipExtent(null);
12413           d3_geoStream(object, projection.stream(boundsStream));
12414           fitBounds(boundsStream.result());
12415           if (clip != null) projection.clipExtent(clip);
12416           return projection;
12417         }
12418
12419         function fitExtent(projection, extent, object) {
12420           return fit(projection, function (b) {
12421             var w = extent[1][0] - extent[0][0],
12422                 h = extent[1][1] - extent[0][1],
12423                 k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
12424                 x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
12425                 y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
12426             projection.scale(150 * k).translate([x, y]);
12427           }, object);
12428         }
12429         function fitSize(projection, size, object) {
12430           return fitExtent(projection, [[0, 0], size], object);
12431         }
12432         function fitWidth(projection, width, object) {
12433           return fit(projection, function (b) {
12434             var w = +width,
12435                 k = w / (b[1][0] - b[0][0]),
12436                 x = (w - k * (b[1][0] + b[0][0])) / 2,
12437                 y = -k * b[0][1];
12438             projection.scale(150 * k).translate([x, y]);
12439           }, object);
12440         }
12441         function fitHeight(projection, height, object) {
12442           return fit(projection, function (b) {
12443             var h = +height,
12444                 k = h / (b[1][1] - b[0][1]),
12445                 x = -k * b[0][0],
12446                 y = (h - k * (b[1][1] + b[0][1])) / 2;
12447             projection.scale(150 * k).translate([x, y]);
12448           }, object);
12449         }
12450
12451         var maxDepth = 16,
12452             // maximum depth of subdivision
12453         cosMinDistance = cos(30 * radians); // cos(minimum angular distance)
12454
12455         function resample (project, delta2) {
12456           return +delta2 ? resample$1(project, delta2) : resampleNone(project);
12457         }
12458
12459         function resampleNone(project) {
12460           return transformer$1({
12461             point: function point(x, y) {
12462               x = project(x, y);
12463               this.stream.point(x[0], x[1]);
12464             }
12465           });
12466         }
12467
12468         function resample$1(project, delta2) {
12469           function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
12470             var dx = x1 - x0,
12471                 dy = y1 - y0,
12472                 d2 = dx * dx + dy * dy;
12473
12474             if (d2 > 4 * delta2 && depth--) {
12475               var a = a0 + a1,
12476                   b = b0 + b1,
12477                   c = c0 + c1,
12478                   m = sqrt(a * a + b * b + c * c),
12479                   phi2 = asin(c /= m),
12480                   lambda2 = abs$2(abs$2(c) - 1) < epsilon$1 || abs$2(lambda0 - lambda1) < epsilon$1 ? (lambda0 + lambda1) / 2 : atan2(b, a),
12481                   p = project(lambda2, phi2),
12482                   x2 = p[0],
12483                   y2 = p[1],
12484                   dx2 = x2 - x0,
12485                   dy2 = y2 - y0,
12486                   dz = dy * dx2 - dx * dy2;
12487
12488               if (dz * dz / d2 > delta2 // perpendicular projected distance
12489               || abs$2((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
12490               || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {
12491                 // angular distance
12492                 resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
12493                 stream.point(x2, y2);
12494                 resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
12495               }
12496             }
12497           }
12498
12499           return function (stream) {
12500             var lambda00, x00, y00, a00, b00, c00, // first point
12501             lambda0, x0, y0, a0, b0, c0; // previous point
12502
12503             var resampleStream = {
12504               point: point,
12505               lineStart: lineStart,
12506               lineEnd: lineEnd,
12507               polygonStart: function polygonStart() {
12508                 stream.polygonStart();
12509                 resampleStream.lineStart = ringStart;
12510               },
12511               polygonEnd: function polygonEnd() {
12512                 stream.polygonEnd();
12513                 resampleStream.lineStart = lineStart;
12514               }
12515             };
12516
12517             function point(x, y) {
12518               x = project(x, y);
12519               stream.point(x[0], x[1]);
12520             }
12521
12522             function lineStart() {
12523               x0 = NaN;
12524               resampleStream.point = linePoint;
12525               stream.lineStart();
12526             }
12527
12528             function linePoint(lambda, phi) {
12529               var c = cartesian([lambda, phi]),
12530                   p = project(lambda, phi);
12531               resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
12532               stream.point(x0, y0);
12533             }
12534
12535             function lineEnd() {
12536               resampleStream.point = point;
12537               stream.lineEnd();
12538             }
12539
12540             function ringStart() {
12541               lineStart();
12542               resampleStream.point = ringPoint;
12543               resampleStream.lineEnd = ringEnd;
12544             }
12545
12546             function ringPoint(lambda, phi) {
12547               linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
12548               resampleStream.point = linePoint;
12549             }
12550
12551             function ringEnd() {
12552               resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
12553               resampleStream.lineEnd = lineEnd;
12554               lineEnd();
12555             }
12556
12557             return resampleStream;
12558           };
12559         }
12560
12561         var transformRadians = transformer$1({
12562           point: function point(x, y) {
12563             this.stream.point(x * radians, y * radians);
12564           }
12565         });
12566
12567         function transformRotate(rotate) {
12568           return transformer$1({
12569             point: function point(x, y) {
12570               var r = rotate(x, y);
12571               return this.stream.point(r[0], r[1]);
12572             }
12573           });
12574         }
12575
12576         function scaleTranslate(k, dx, dy, sx, sy) {
12577           function transform(x, y) {
12578             x *= sx;
12579             y *= sy;
12580             return [dx + k * x, dy - k * y];
12581           }
12582
12583           transform.invert = function (x, y) {
12584             return [(x - dx) / k * sx, (dy - y) / k * sy];
12585           };
12586
12587           return transform;
12588         }
12589
12590         function scaleTranslateRotate(k, dx, dy, sx, sy, alpha) {
12591           if (!alpha) return scaleTranslate(k, dx, dy, sx, sy);
12592           var cosAlpha = cos(alpha),
12593               sinAlpha = sin(alpha),
12594               a = cosAlpha * k,
12595               b = sinAlpha * k,
12596               ai = cosAlpha / k,
12597               bi = sinAlpha / k,
12598               ci = (sinAlpha * dy - cosAlpha * dx) / k,
12599               fi = (sinAlpha * dx + cosAlpha * dy) / k;
12600
12601           function transform(x, y) {
12602             x *= sx;
12603             y *= sy;
12604             return [a * x - b * y + dx, dy - b * x - a * y];
12605           }
12606
12607           transform.invert = function (x, y) {
12608             return [sx * (ai * x - bi * y + ci), sy * (fi - bi * x - ai * y)];
12609           };
12610
12611           return transform;
12612         }
12613
12614         function projection(project) {
12615           return projectionMutator(function () {
12616             return project;
12617           })();
12618         }
12619         function projectionMutator(projectAt) {
12620           var project,
12621               k = 150,
12622               // scale
12623           x = 480,
12624               y = 250,
12625               // translate
12626           lambda = 0,
12627               phi = 0,
12628               // center
12629           deltaLambda = 0,
12630               deltaPhi = 0,
12631               deltaGamma = 0,
12632               rotate,
12633               // pre-rotate
12634           alpha = 0,
12635               // post-rotate angle
12636           sx = 1,
12637               // reflectX
12638           sy = 1,
12639               // reflectX
12640           theta = null,
12641               preclip = clipAntimeridian,
12642               // pre-clip angle
12643           x0 = null,
12644               y0,
12645               x1,
12646               y1,
12647               postclip = identity$4,
12648               // post-clip extent
12649           delta2 = 0.5,
12650               // precision
12651           projectResample,
12652               projectTransform,
12653               projectRotateTransform,
12654               cache,
12655               cacheStream;
12656
12657           function projection(point) {
12658             return projectRotateTransform(point[0] * radians, point[1] * radians);
12659           }
12660
12661           function invert(point) {
12662             point = projectRotateTransform.invert(point[0], point[1]);
12663             return point && [point[0] * degrees$1, point[1] * degrees$1];
12664           }
12665
12666           projection.stream = function (stream) {
12667             return cache && cacheStream === stream ? cache : cache = transformRadians(transformRotate(rotate)(preclip(projectResample(postclip(cacheStream = stream)))));
12668           };
12669
12670           projection.preclip = function (_) {
12671             return arguments.length ? (preclip = _, theta = undefined, reset()) : preclip;
12672           };
12673
12674           projection.postclip = function (_) {
12675             return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip;
12676           };
12677
12678           projection.clipAngle = function (_) {
12679             return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1;
12680           };
12681
12682           projection.clipExtent = function (_) {
12683             return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
12684           };
12685
12686           projection.scale = function (_) {
12687             return arguments.length ? (k = +_, recenter()) : k;
12688           };
12689
12690           projection.translate = function (_) {
12691             return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
12692           };
12693
12694           projection.center = function (_) {
12695             return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1];
12696           };
12697
12698           projection.rotate = function (_) {
12699             return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees$1, deltaPhi * degrees$1, deltaGamma * degrees$1];
12700           };
12701
12702           projection.angle = function (_) {
12703             return arguments.length ? (alpha = _ % 360 * radians, recenter()) : alpha * degrees$1;
12704           };
12705
12706           projection.reflectX = function (_) {
12707             return arguments.length ? (sx = _ ? -1 : 1, recenter()) : sx < 0;
12708           };
12709
12710           projection.reflectY = function (_) {
12711             return arguments.length ? (sy = _ ? -1 : 1, recenter()) : sy < 0;
12712           };
12713
12714           projection.precision = function (_) {
12715             return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2);
12716           };
12717
12718           projection.fitExtent = function (extent, object) {
12719             return fitExtent(projection, extent, object);
12720           };
12721
12722           projection.fitSize = function (size, object) {
12723             return fitSize(projection, size, object);
12724           };
12725
12726           projection.fitWidth = function (width, object) {
12727             return fitWidth(projection, width, object);
12728           };
12729
12730           projection.fitHeight = function (height, object) {
12731             return fitHeight(projection, height, object);
12732           };
12733
12734           function recenter() {
12735             var center = scaleTranslateRotate(k, 0, 0, sx, sy, alpha).apply(null, project(lambda, phi)),
12736                 transform = scaleTranslateRotate(k, x - center[0], y - center[1], sx, sy, alpha);
12737             rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma);
12738             projectTransform = compose(project, transform);
12739             projectRotateTransform = compose(rotate, projectTransform);
12740             projectResample = resample(projectTransform, delta2);
12741             return reset();
12742           }
12743
12744           function reset() {
12745             cache = cacheStream = null;
12746             return projection;
12747           }
12748
12749           return function () {
12750             project = projectAt.apply(this, arguments);
12751             projection.invert = project.invert && invert;
12752             return recenter();
12753           };
12754         }
12755
12756         function mercatorRaw(lambda, phi) {
12757           return [lambda, log$1(tan((halfPi + phi) / 2))];
12758         }
12759
12760         mercatorRaw.invert = function (x, y) {
12761           return [x, 2 * atan(exp$2(y)) - halfPi];
12762         };
12763
12764         function mercator () {
12765           return mercatorProjection(mercatorRaw).scale(961 / tau);
12766         }
12767         function mercatorProjection(project) {
12768           var m = projection(project),
12769               center = m.center,
12770               scale = m.scale,
12771               translate = m.translate,
12772               clipExtent = m.clipExtent,
12773               x0 = null,
12774               y0,
12775               x1,
12776               y1; // clip extent
12777
12778           m.scale = function (_) {
12779             return arguments.length ? (scale(_), reclip()) : scale();
12780           };
12781
12782           m.translate = function (_) {
12783             return arguments.length ? (translate(_), reclip()) : translate();
12784           };
12785
12786           m.center = function (_) {
12787             return arguments.length ? (center(_), reclip()) : center();
12788           };
12789
12790           m.clipExtent = function (_) {
12791             return arguments.length ? (_ == null ? x0 = y0 = x1 = y1 = null : (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reclip()) : x0 == null ? null : [[x0, y0], [x1, y1]];
12792           };
12793
12794           function reclip() {
12795             var k = pi * scale(),
12796                 t = m(rotation(m.rotate()).invert([0, 0]));
12797             return clipExtent(x0 == null ? [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]] : project === mercatorRaw ? [[Math.max(t[0] - k, x0), y0], [Math.min(t[0] + k, x1), y1]] : [[x0, Math.max(t[1] - k, y0)], [x1, Math.min(t[1] + k, y1)]]);
12798           }
12799
12800           return reclip();
12801         }
12802
12803         function d3_geoIdentity () {
12804           var k = 1,
12805               tx = 0,
12806               ty = 0,
12807               sx = 1,
12808               sy = 1,
12809               // scale, translate and reflect
12810           alpha = 0,
12811               ca,
12812               sa,
12813               // angle
12814           x0 = null,
12815               y0,
12816               x1,
12817               y1,
12818               // clip extent
12819           kx = 1,
12820               ky = 1,
12821               transform = transformer$1({
12822             point: function point(x, y) {
12823               var p = projection([x, y]);
12824               this.stream.point(p[0], p[1]);
12825             }
12826           }),
12827               postclip = identity$4,
12828               cache,
12829               cacheStream;
12830
12831           function reset() {
12832             kx = k * sx;
12833             ky = k * sy;
12834             cache = cacheStream = null;
12835             return projection;
12836           }
12837
12838           function projection(p) {
12839             var x = p[0] * kx,
12840                 y = p[1] * ky;
12841
12842             if (alpha) {
12843               var t = y * ca - x * sa;
12844               x = x * ca + y * sa;
12845               y = t;
12846             }
12847
12848             return [x + tx, y + ty];
12849           }
12850
12851           projection.invert = function (p) {
12852             var x = p[0] - tx,
12853                 y = p[1] - ty;
12854
12855             if (alpha) {
12856               var t = y * ca + x * sa;
12857               x = x * ca - y * sa;
12858               y = t;
12859             }
12860
12861             return [x / kx, y / ky];
12862           };
12863
12864           projection.stream = function (stream) {
12865             return cache && cacheStream === stream ? cache : cache = transform(postclip(cacheStream = stream));
12866           };
12867
12868           projection.postclip = function (_) {
12869             return arguments.length ? (postclip = _, x0 = y0 = x1 = y1 = null, reset()) : postclip;
12870           };
12871
12872           projection.clipExtent = function (_) {
12873             return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$4) : clipRectangle(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
12874           };
12875
12876           projection.scale = function (_) {
12877             return arguments.length ? (k = +_, reset()) : k;
12878           };
12879
12880           projection.translate = function (_) {
12881             return arguments.length ? (tx = +_[0], ty = +_[1], reset()) : [tx, ty];
12882           };
12883
12884           projection.angle = function (_) {
12885             return arguments.length ? (alpha = _ % 360 * radians, sa = sin(alpha), ca = cos(alpha), reset()) : alpha * degrees$1;
12886           };
12887
12888           projection.reflectX = function (_) {
12889             return arguments.length ? (sx = _ ? -1 : 1, reset()) : sx < 0;
12890           };
12891
12892           projection.reflectY = function (_) {
12893             return arguments.length ? (sy = _ ? -1 : 1, reset()) : sy < 0;
12894           };
12895
12896           projection.fitExtent = function (extent, object) {
12897             return fitExtent(projection, extent, object);
12898           };
12899
12900           projection.fitSize = function (size, object) {
12901             return fitSize(projection, size, object);
12902           };
12903
12904           projection.fitWidth = function (width, object) {
12905             return fitWidth(projection, width, object);
12906           };
12907
12908           projection.fitHeight = function (height, object) {
12909             return fitHeight(projection, height, object);
12910           };
12911
12912           return projection;
12913         }
12914
12915         // constants
12916         var TAU = 2 * Math.PI;
12917         var EQUATORIAL_RADIUS = 6356752.314245179;
12918         var POLAR_RADIUS = 6378137.0;
12919         function geoLatToMeters(dLat) {
12920           return dLat * (TAU * POLAR_RADIUS / 360);
12921         }
12922         function geoLonToMeters(dLon, atLat) {
12923           return Math.abs(atLat) >= 90 ? 0 : dLon * (TAU * EQUATORIAL_RADIUS / 360) * Math.abs(Math.cos(atLat * (Math.PI / 180)));
12924         }
12925         function geoMetersToLat(m) {
12926           return m / (TAU * POLAR_RADIUS / 360);
12927         }
12928         function geoMetersToLon(m, atLat) {
12929           return Math.abs(atLat) >= 90 ? 0 : m / (TAU * EQUATORIAL_RADIUS / 360) / Math.abs(Math.cos(atLat * (Math.PI / 180)));
12930         }
12931         function geoMetersToOffset(meters, tileSize) {
12932           tileSize = tileSize || 256;
12933           return [meters[0] * tileSize / (TAU * EQUATORIAL_RADIUS), -meters[1] * tileSize / (TAU * POLAR_RADIUS)];
12934         }
12935         function geoOffsetToMeters(offset, tileSize) {
12936           tileSize = tileSize || 256;
12937           return [offset[0] * TAU * EQUATORIAL_RADIUS / tileSize, -offset[1] * TAU * POLAR_RADIUS / tileSize];
12938         } // Equirectangular approximation of spherical distances on Earth
12939
12940         function geoSphericalDistance(a, b) {
12941           var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2);
12942           var y = geoLatToMeters(a[1] - b[1]);
12943           return Math.sqrt(x * x + y * y);
12944         } // scale to zoom
12945
12946         function geoScaleToZoom(k, tileSize) {
12947           tileSize = tileSize || 256;
12948           var log2ts = Math.log(tileSize) * Math.LOG2E;
12949           return Math.log(k * TAU) / Math.LN2 - log2ts;
12950         } // zoom to scale
12951
12952         function geoZoomToScale(z, tileSize) {
12953           tileSize = tileSize || 256;
12954           return tileSize * Math.pow(2, z) / TAU;
12955         } // returns info about the node from `nodes` closest to the given `point`
12956
12957         function geoSphericalClosestNode(nodes, point) {
12958           var minDistance = Infinity,
12959               distance;
12960           var indexOfMin;
12961
12962           for (var i in nodes) {
12963             distance = geoSphericalDistance(nodes[i].loc, point);
12964
12965             if (distance < minDistance) {
12966               minDistance = distance;
12967               indexOfMin = i;
12968             }
12969           }
12970
12971           if (indexOfMin !== undefined) {
12972             return {
12973               index: indexOfMin,
12974               distance: minDistance,
12975               node: nodes[indexOfMin]
12976             };
12977           } else {
12978             return null;
12979           }
12980         }
12981
12982         function geoExtent(min, max) {
12983           if (!(this instanceof geoExtent)) {
12984             return new geoExtent(min, max);
12985           } else if (min instanceof geoExtent) {
12986             return min;
12987           } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
12988             this[0] = min[0];
12989             this[1] = min[1];
12990           } else {
12991             this[0] = min || [Infinity, Infinity];
12992             this[1] = max || min || [-Infinity, -Infinity];
12993           }
12994         }
12995         geoExtent.prototype = new Array(2);
12996         Object.assign(geoExtent.prototype, {
12997           equals: function equals(obj) {
12998             return this[0][0] === obj[0][0] && this[0][1] === obj[0][1] && this[1][0] === obj[1][0] && this[1][1] === obj[1][1];
12999           },
13000           extend: function extend(obj) {
13001             if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
13002             return geoExtent([Math.min(obj[0][0], this[0][0]), Math.min(obj[0][1], this[0][1])], [Math.max(obj[1][0], this[1][0]), Math.max(obj[1][1], this[1][1])]);
13003           },
13004           _extend: function _extend(extent) {
13005             this[0][0] = Math.min(extent[0][0], this[0][0]);
13006             this[0][1] = Math.min(extent[0][1], this[0][1]);
13007             this[1][0] = Math.max(extent[1][0], this[1][0]);
13008             this[1][1] = Math.max(extent[1][1], this[1][1]);
13009           },
13010           area: function area() {
13011             return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
13012           },
13013           center: function center() {
13014             return [(this[0][0] + this[1][0]) / 2, (this[0][1] + this[1][1]) / 2];
13015           },
13016           rectangle: function rectangle() {
13017             return [this[0][0], this[0][1], this[1][0], this[1][1]];
13018           },
13019           bbox: function bbox() {
13020             return {
13021               minX: this[0][0],
13022               minY: this[0][1],
13023               maxX: this[1][0],
13024               maxY: this[1][1]
13025             };
13026           },
13027           polygon: function polygon() {
13028             return [[this[0][0], this[0][1]], [this[0][0], this[1][1]], [this[1][0], this[1][1]], [this[1][0], this[0][1]], [this[0][0], this[0][1]]];
13029           },
13030           contains: function contains(obj) {
13031             if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
13032             return obj[0][0] >= this[0][0] && obj[0][1] >= this[0][1] && obj[1][0] <= this[1][0] && obj[1][1] <= this[1][1];
13033           },
13034           intersects: function intersects(obj) {
13035             if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
13036             return obj[0][0] <= this[1][0] && obj[0][1] <= this[1][1] && obj[1][0] >= this[0][0] && obj[1][1] >= this[0][1];
13037           },
13038           intersection: function intersection(obj) {
13039             if (!this.intersects(obj)) return new geoExtent();
13040             return new geoExtent([Math.max(obj[0][0], this[0][0]), Math.max(obj[0][1], this[0][1])], [Math.min(obj[1][0], this[1][0]), Math.min(obj[1][1], this[1][1])]);
13041           },
13042           percentContainedIn: function percentContainedIn(obj) {
13043             if (!(obj instanceof geoExtent)) obj = new geoExtent(obj);
13044             var a1 = this.intersection(obj).area();
13045             var a2 = this.area();
13046
13047             if (a1 === Infinity || a2 === Infinity) {
13048               return 0;
13049             } else if (a1 === 0 || a2 === 0) {
13050               if (obj.contains(this)) {
13051                 return 1;
13052               }
13053
13054               return 0;
13055             } else {
13056               return a1 / a2;
13057             }
13058           },
13059           padByMeters: function padByMeters(meters) {
13060             var dLat = geoMetersToLat(meters);
13061             var dLon = geoMetersToLon(meters, this.center()[1]);
13062             return geoExtent([this[0][0] - dLon, this[0][1] - dLat], [this[1][0] + dLon, this[1][1] + dLat]);
13063           },
13064           toParam: function toParam() {
13065             return this.rectangle().join(',');
13066           }
13067         });
13068
13069         var $$w = _export;
13070         var $every = arrayIteration.every;
13071         var arrayMethodIsStrict$2 = arrayMethodIsStrict$9;
13072
13073         var STRICT_METHOD$2 = arrayMethodIsStrict$2('every');
13074
13075         // `Array.prototype.every` method
13076         // https://tc39.es/ecma262/#sec-array.prototype.every
13077         $$w({ target: 'Array', proto: true, forced: !STRICT_METHOD$2 }, {
13078           every: function every(callbackfn /* , thisArg */) {
13079             return $every(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
13080           }
13081         });
13082
13083         var $$v = _export;
13084         var $reduce = arrayReduce.left;
13085         var arrayMethodIsStrict$1 = arrayMethodIsStrict$9;
13086         var CHROME_VERSION$1 = engineV8Version;
13087         var IS_NODE$1 = engineIsNode;
13088
13089         var STRICT_METHOD$1 = arrayMethodIsStrict$1('reduce');
13090         // Chrome 80-82 has a critical bug
13091         // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
13092         var CHROME_BUG$1 = !IS_NODE$1 && CHROME_VERSION$1 > 79 && CHROME_VERSION$1 < 83;
13093
13094         // `Array.prototype.reduce` method
13095         // https://tc39.es/ecma262/#sec-array.prototype.reduce
13096         $$v({ target: 'Array', proto: true, forced: !STRICT_METHOD$1 || CHROME_BUG$1 }, {
13097           reduce: function reduce(callbackfn /* , initialValue */) {
13098             var length = arguments.length;
13099             return $reduce(this, callbackfn, length, length > 1 ? arguments[1] : undefined);
13100           }
13101         });
13102
13103         function d3_polygonArea (polygon) {
13104           var i = -1,
13105               n = polygon.length,
13106               a,
13107               b = polygon[n - 1],
13108               area = 0;
13109
13110           while (++i < n) {
13111             a = b;
13112             b = polygon[i];
13113             area += a[1] * b[0] - a[0] * b[1];
13114           }
13115
13116           return area / 2;
13117         }
13118
13119         function d3_polygonCentroid (polygon) {
13120           var i = -1,
13121               n = polygon.length,
13122               x = 0,
13123               y = 0,
13124               a,
13125               b = polygon[n - 1],
13126               c,
13127               k = 0;
13128
13129           while (++i < n) {
13130             a = b;
13131             b = polygon[i];
13132             k += c = a[0] * b[1] - b[0] * a[1];
13133             x += (a[0] + b[0]) * c;
13134             y += (a[1] + b[1]) * c;
13135           }
13136
13137           return k *= 3, [x / k, y / k];
13138         }
13139
13140         // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
13141         // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
13142         // right, +y is up). Returns a positive value if ABC is counter-clockwise,
13143         // negative if clockwise, and zero if the points are collinear.
13144         function cross (a, b, c) {
13145           return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
13146         }
13147
13148         function lexicographicOrder(a, b) {
13149           return a[0] - b[0] || a[1] - b[1];
13150         } // Computes the upper convex hull per the monotone chain algorithm.
13151         // Assumes points.length >= 3, is sorted by x, unique in y.
13152         // Returns an array of indices into points in left-to-right order.
13153
13154
13155         function computeUpperHullIndexes(points) {
13156           var n = points.length,
13157               indexes = [0, 1];
13158           var size = 2,
13159               i;
13160
13161           for (i = 2; i < n; ++i) {
13162             while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) {
13163               --size;
13164             }
13165
13166             indexes[size++] = i;
13167           }
13168
13169           return indexes.slice(0, size); // remove popped points
13170         }
13171
13172         function d3_polygonHull (points) {
13173           if ((n = points.length) < 3) return null;
13174           var i,
13175               n,
13176               sortedPoints = new Array(n),
13177               flippedPoints = new Array(n);
13178
13179           for (i = 0; i < n; ++i) {
13180             sortedPoints[i] = [+points[i][0], +points[i][1], i];
13181           }
13182
13183           sortedPoints.sort(lexicographicOrder);
13184
13185           for (i = 0; i < n; ++i) {
13186             flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]];
13187           }
13188
13189           var upperIndexes = computeUpperHullIndexes(sortedPoints),
13190               lowerIndexes = computeUpperHullIndexes(flippedPoints); // Construct the hull polygon, removing possible duplicate endpoints.
13191
13192           var skipLeft = lowerIndexes[0] === upperIndexes[0],
13193               skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1],
13194               hull = []; // Add upper hull in right-to-l order.
13195           // Then add lower hull in left-to-right order.
13196
13197           for (i = upperIndexes.length - 1; i >= 0; --i) {
13198             hull.push(points[sortedPoints[upperIndexes[i]][2]]);
13199           }
13200
13201           for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) {
13202             hull.push(points[sortedPoints[lowerIndexes[i]][2]]);
13203           }
13204
13205           return hull;
13206         }
13207
13208         // vector equals
13209         function geoVecEqual(a, b, epsilon) {
13210           if (epsilon) {
13211             return Math.abs(a[0] - b[0]) <= epsilon && Math.abs(a[1] - b[1]) <= epsilon;
13212           } else {
13213             return a[0] === b[0] && a[1] === b[1];
13214           }
13215         } // vector addition
13216
13217         function geoVecAdd(a, b) {
13218           return [a[0] + b[0], a[1] + b[1]];
13219         } // vector subtraction
13220
13221         function geoVecSubtract(a, b) {
13222           return [a[0] - b[0], a[1] - b[1]];
13223         } // vector scaling
13224
13225         function geoVecScale(a, mag) {
13226           return [a[0] * mag, a[1] * mag];
13227         } // vector rounding (was: geoRoundCoordinates)
13228
13229         function geoVecFloor(a) {
13230           return [Math.floor(a[0]), Math.floor(a[1])];
13231         } // linear interpolation
13232
13233         function geoVecInterp(a, b, t) {
13234           return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
13235         } // http://jsperf.com/id-dist-optimization
13236
13237         function geoVecLength(a, b) {
13238           return Math.sqrt(geoVecLengthSquare(a, b));
13239         } // length of vector raised to the power two
13240
13241         function geoVecLengthSquare(a, b) {
13242           b = b || [0, 0];
13243           var x = a[0] - b[0];
13244           var y = a[1] - b[1];
13245           return x * x + y * y;
13246         } // get a unit vector
13247
13248         function geoVecNormalize(a) {
13249           var length = Math.sqrt(a[0] * a[0] + a[1] * a[1]);
13250
13251           if (length !== 0) {
13252             return geoVecScale(a, 1 / length);
13253           }
13254
13255           return [0, 0];
13256         } // Return the counterclockwise angle in the range (-pi, pi)
13257         // between the positive X axis and the line intersecting a and b.
13258
13259         function geoVecAngle(a, b) {
13260           return Math.atan2(b[1] - a[1], b[0] - a[0]);
13261         } // dot product
13262
13263         function geoVecDot(a, b, origin) {
13264           origin = origin || [0, 0];
13265           var p = geoVecSubtract(a, origin);
13266           var q = geoVecSubtract(b, origin);
13267           return p[0] * q[0] + p[1] * q[1];
13268         } // normalized dot product
13269
13270         function geoVecNormalizedDot(a, b, origin) {
13271           origin = origin || [0, 0];
13272           var p = geoVecNormalize(geoVecSubtract(a, origin));
13273           var q = geoVecNormalize(geoVecSubtract(b, origin));
13274           return geoVecDot(p, q);
13275         } // 2D cross product of OA and OB vectors, returns magnitude of Z vector
13276         // Returns a positive value, if OAB makes a counter-clockwise turn,
13277         // negative for clockwise turn, and zero if the points are collinear.
13278
13279         function geoVecCross(a, b, origin) {
13280           origin = origin || [0, 0];
13281           var p = geoVecSubtract(a, origin);
13282           var q = geoVecSubtract(b, origin);
13283           return p[0] * q[1] - p[1] * q[0];
13284         } // find closest orthogonal projection of point onto points array
13285
13286         function geoVecProject(a, points) {
13287           var min = Infinity;
13288           var idx;
13289           var target;
13290
13291           for (var i = 0; i < points.length - 1; i++) {
13292             var o = points[i];
13293             var s = geoVecSubtract(points[i + 1], o);
13294             var v = geoVecSubtract(a, o);
13295             var proj = geoVecDot(v, s) / geoVecDot(s, s);
13296             var p;
13297
13298             if (proj < 0) {
13299               p = o;
13300             } else if (proj > 1) {
13301               p = points[i + 1];
13302             } else {
13303               p = [o[0] + proj * s[0], o[1] + proj * s[1]];
13304             }
13305
13306             var dist = geoVecLength(p, a);
13307
13308             if (dist < min) {
13309               min = dist;
13310               idx = i + 1;
13311               target = p;
13312             }
13313           }
13314
13315           if (idx !== undefined) {
13316             return {
13317               index: idx,
13318               distance: min,
13319               target: target
13320             };
13321           } else {
13322             return null;
13323           }
13324         }
13325
13326         // between the positive X axis and the line intersecting a and b.
13327
13328         function geoAngle(a, b, projection) {
13329           return geoVecAngle(projection(a.loc), projection(b.loc));
13330         }
13331         function geoEdgeEqual(a, b) {
13332           return a[0] === b[0] && a[1] === b[1] || a[0] === b[1] && a[1] === b[0];
13333         } // Rotate all points counterclockwise around a pivot point by given angle
13334
13335         function geoRotate(points, angle, around) {
13336           return points.map(function (point) {
13337             var radial = geoVecSubtract(point, around);
13338             return [radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + around[0], radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + around[1]];
13339           });
13340         } // Choose the edge with the minimal distance from `point` to its orthogonal
13341         // projection onto that edge, if such a projection exists, or the distance to
13342         // the closest vertex on that edge. Returns an object with the `index` of the
13343         // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
13344
13345         function geoChooseEdge(nodes, point, projection, activeID) {
13346           var dist = geoVecLength;
13347           var points = nodes.map(function (n) {
13348             return projection(n.loc);
13349           });
13350           var ids = nodes.map(function (n) {
13351             return n.id;
13352           });
13353           var min = Infinity;
13354           var idx;
13355           var loc;
13356
13357           for (var i = 0; i < points.length - 1; i++) {
13358             if (ids[i] === activeID || ids[i + 1] === activeID) continue;
13359             var o = points[i];
13360             var s = geoVecSubtract(points[i + 1], o);
13361             var v = geoVecSubtract(point, o);
13362             var proj = geoVecDot(v, s) / geoVecDot(s, s);
13363             var p;
13364
13365             if (proj < 0) {
13366               p = o;
13367             } else if (proj > 1) {
13368               p = points[i + 1];
13369             } else {
13370               p = [o[0] + proj * s[0], o[1] + proj * s[1]];
13371             }
13372
13373             var d = dist(p, point);
13374
13375             if (d < min) {
13376               min = d;
13377               idx = i + 1;
13378               loc = projection.invert(p);
13379             }
13380           }
13381
13382           if (idx !== undefined) {
13383             return {
13384               index: idx,
13385               distance: min,
13386               loc: loc
13387             };
13388           } else {
13389             return null;
13390           }
13391         } // Test active (dragged or drawing) segments against inactive segments
13392         // This is used to test e.g. multipolygon rings that cross
13393         // `activeNodes` is the ring containing the activeID being dragged.
13394         // `inactiveNodes` is the other ring to test against
13395
13396         function geoHasLineIntersections(activeNodes, inactiveNodes, activeID) {
13397           var actives = [];
13398           var inactives = [];
13399           var j, k, n1, n2, segment; // gather active segments (only segments in activeNodes that contain the activeID)
13400
13401           for (j = 0; j < activeNodes.length - 1; j++) {
13402             n1 = activeNodes[j];
13403             n2 = activeNodes[j + 1];
13404             segment = [n1.loc, n2.loc];
13405
13406             if (n1.id === activeID || n2.id === activeID) {
13407               actives.push(segment);
13408             }
13409           } // gather inactive segments
13410
13411
13412           for (j = 0; j < inactiveNodes.length - 1; j++) {
13413             n1 = inactiveNodes[j];
13414             n2 = inactiveNodes[j + 1];
13415             segment = [n1.loc, n2.loc];
13416             inactives.push(segment);
13417           } // test
13418
13419
13420           for (j = 0; j < actives.length; j++) {
13421             for (k = 0; k < inactives.length; k++) {
13422               var p = actives[j];
13423               var q = inactives[k];
13424               var hit = geoLineIntersection(p, q);
13425
13426               if (hit) {
13427                 return true;
13428               }
13429             }
13430           }
13431
13432           return false;
13433         } // Test active (dragged or drawing) segments against inactive segments
13434         // This is used to test whether a way intersects with itself.
13435
13436         function geoHasSelfIntersections(nodes, activeID) {
13437           var actives = [];
13438           var inactives = [];
13439           var j, k; // group active and passive segments along the nodes
13440
13441           for (j = 0; j < nodes.length - 1; j++) {
13442             var n1 = nodes[j];
13443             var n2 = nodes[j + 1];
13444             var segment = [n1.loc, n2.loc];
13445
13446             if (n1.id === activeID || n2.id === activeID) {
13447               actives.push(segment);
13448             } else {
13449               inactives.push(segment);
13450             }
13451           } // test
13452
13453
13454           for (j = 0; j < actives.length; j++) {
13455             for (k = 0; k < inactives.length; k++) {
13456               var p = actives[j];
13457               var q = inactives[k]; // skip if segments share an endpoint
13458
13459               if (geoVecEqual(p[1], q[0]) || geoVecEqual(p[0], q[1]) || geoVecEqual(p[0], q[0]) || geoVecEqual(p[1], q[1])) {
13460                 continue;
13461               }
13462
13463               var hit = geoLineIntersection(p, q);
13464
13465               if (hit) {
13466                 var epsilon = 1e-8; // skip if the hit is at the segment's endpoint
13467
13468                 if (geoVecEqual(p[1], hit, epsilon) || geoVecEqual(p[0], hit, epsilon) || geoVecEqual(q[1], hit, epsilon) || geoVecEqual(q[0], hit, epsilon)) {
13469                   continue;
13470                 } else {
13471                   return true;
13472                 }
13473               }
13474             }
13475           }
13476
13477           return false;
13478         } // Return the intersection point of 2 line segments.
13479         // From https://github.com/pgkelley4/line-segments-intersect
13480         // This uses the vector cross product approach described below:
13481         //  http://stackoverflow.com/a/565282/786339
13482
13483         function geoLineIntersection(a, b) {
13484           var p = [a[0][0], a[0][1]];
13485           var p2 = [a[1][0], a[1][1]];
13486           var q = [b[0][0], b[0][1]];
13487           var q2 = [b[1][0], b[1][1]];
13488           var r = geoVecSubtract(p2, p);
13489           var s = geoVecSubtract(q2, q);
13490           var uNumerator = geoVecCross(geoVecSubtract(q, p), r);
13491           var denominator = geoVecCross(r, s);
13492
13493           if (uNumerator && denominator) {
13494             var u = uNumerator / denominator;
13495             var t = geoVecCross(geoVecSubtract(q, p), s) / denominator;
13496
13497             if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
13498               return geoVecInterp(p, p2, t);
13499             }
13500           }
13501
13502           return null;
13503         }
13504         function geoPathIntersections(path1, path2) {
13505           var intersections = [];
13506
13507           for (var i = 0; i < path1.length - 1; i++) {
13508             for (var j = 0; j < path2.length - 1; j++) {
13509               var a = [path1[i], path1[i + 1]];
13510               var b = [path2[j], path2[j + 1]];
13511               var hit = geoLineIntersection(a, b);
13512
13513               if (hit) {
13514                 intersections.push(hit);
13515               }
13516             }
13517           }
13518
13519           return intersections;
13520         }
13521         function geoPathHasIntersections(path1, path2) {
13522           for (var i = 0; i < path1.length - 1; i++) {
13523             for (var j = 0; j < path2.length - 1; j++) {
13524               var a = [path1[i], path1[i + 1]];
13525               var b = [path2[j], path2[j + 1]];
13526               var hit = geoLineIntersection(a, b);
13527
13528               if (hit) {
13529                 return true;
13530               }
13531             }
13532           }
13533
13534           return false;
13535         } // Return whether point is contained in polygon.
13536         //
13537         // `point` should be a 2-item array of coordinates.
13538         // `polygon` should be an array of 2-item arrays of coordinates.
13539         //
13540         // From https://github.com/substack/point-in-polygon.
13541         // ray-casting algorithm based on
13542         // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
13543         //
13544
13545         function geoPointInPolygon(point, polygon) {
13546           var x = point[0];
13547           var y = point[1];
13548           var inside = false;
13549
13550           for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
13551             var xi = polygon[i][0];
13552             var yi = polygon[i][1];
13553             var xj = polygon[j][0];
13554             var yj = polygon[j][1];
13555             var intersect = yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi;
13556             if (intersect) inside = !inside;
13557           }
13558
13559           return inside;
13560         }
13561         function geoPolygonContainsPolygon(outer, inner) {
13562           return inner.every(function (point) {
13563             return geoPointInPolygon(point, outer);
13564           });
13565         }
13566         function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
13567           function testPoints(outer, inner) {
13568             return inner.some(function (point) {
13569               return geoPointInPolygon(point, outer);
13570             });
13571           }
13572
13573           return testPoints(outer, inner) || !!checkSegments && geoPathHasIntersections(outer, inner);
13574         } // http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points
13575         // http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756
13576
13577         function geoGetSmallestSurroundingRectangle(points) {
13578           var hull = d3_polygonHull(points);
13579           var centroid = d3_polygonCentroid(hull);
13580           var minArea = Infinity;
13581           var ssrExtent = [];
13582           var ssrAngle = 0;
13583           var c1 = hull[0];
13584
13585           for (var i = 0; i <= hull.length - 1; i++) {
13586             var c2 = i === hull.length - 1 ? hull[0] : hull[i + 1];
13587             var angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]);
13588             var poly = geoRotate(hull, -angle, centroid);
13589             var extent = poly.reduce(function (extent, point) {
13590               return extent.extend(geoExtent(point));
13591             }, geoExtent());
13592             var area = extent.area();
13593
13594             if (area < minArea) {
13595               minArea = area;
13596               ssrExtent = extent;
13597               ssrAngle = angle;
13598             }
13599
13600             c1 = c2;
13601           }
13602
13603           return {
13604             poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid),
13605             angle: ssrAngle
13606           };
13607         }
13608         function geoPathLength(path) {
13609           var length = 0;
13610
13611           for (var i = 0; i < path.length - 1; i++) {
13612             length += geoVecLength(path[i], path[i + 1]);
13613           }
13614
13615           return length;
13616         } // If the given point is at the edge of the padded viewport,
13617         // return a vector that will nudge the viewport in that direction
13618
13619         function geoViewportEdge(point, dimensions) {
13620           var pad = [80, 20, 50, 20]; // top, right, bottom, left
13621
13622           var x = 0;
13623           var y = 0;
13624
13625           if (point[0] > dimensions[0] - pad[1]) {
13626             x = -10;
13627           }
13628
13629           if (point[0] < pad[3]) {
13630             x = 10;
13631           }
13632
13633           if (point[1] > dimensions[1] - pad[2]) {
13634             y = -10;
13635           }
13636
13637           if (point[1] < pad[0]) {
13638             y = 10;
13639           }
13640
13641           if (x || y) {
13642             return [x, y];
13643           } else {
13644             return null;
13645           }
13646         }
13647
13648         var noop = {
13649           value: function value() {}
13650         };
13651
13652         function dispatch$8() {
13653           for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
13654             if (!(t = arguments[i] + "") || t in _ || /[\s.]/.test(t)) throw new Error("illegal type: " + t);
13655             _[t] = [];
13656           }
13657
13658           return new Dispatch(_);
13659         }
13660
13661         function Dispatch(_) {
13662           this._ = _;
13663         }
13664
13665         function parseTypenames$1(typenames, types) {
13666           return typenames.trim().split(/^|\s+/).map(function (t) {
13667             var name = "",
13668                 i = t.indexOf(".");
13669             if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
13670             if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
13671             return {
13672               type: t,
13673               name: name
13674             };
13675           });
13676         }
13677
13678         Dispatch.prototype = dispatch$8.prototype = {
13679           constructor: Dispatch,
13680           on: function on(typename, callback) {
13681             var _ = this._,
13682                 T = parseTypenames$1(typename + "", _),
13683                 t,
13684                 i = -1,
13685                 n = T.length; // If no callback was specified, return the callback of the given type and name.
13686
13687             if (arguments.length < 2) {
13688               while (++i < n) {
13689                 if ((t = (typename = T[i]).type) && (t = get$2(_[t], typename.name))) return t;
13690               }
13691
13692               return;
13693             } // If a type was specified, set the callback for the given type and name.
13694             // Otherwise, if a null callback was specified, remove callbacks of the given name.
13695
13696
13697             if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
13698
13699             while (++i < n) {
13700               if (t = (typename = T[i]).type) _[t] = set$1(_[t], typename.name, callback);else if (callback == null) for (t in _) {
13701                 _[t] = set$1(_[t], typename.name, null);
13702               }
13703             }
13704
13705             return this;
13706           },
13707           copy: function copy() {
13708             var copy = {},
13709                 _ = this._;
13710
13711             for (var t in _) {
13712               copy[t] = _[t].slice();
13713             }
13714
13715             return new Dispatch(copy);
13716           },
13717           call: function call(type, that) {
13718             if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) {
13719               args[i] = arguments[i + 2];
13720             }
13721             if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
13722
13723             for (t = this._[type], i = 0, n = t.length; i < n; ++i) {
13724               t[i].value.apply(that, args);
13725             }
13726           },
13727           apply: function apply(type, that, args) {
13728             if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
13729
13730             for (var t = this._[type], i = 0, n = t.length; i < n; ++i) {
13731               t[i].value.apply(that, args);
13732             }
13733           }
13734         };
13735
13736         function get$2(type, name) {
13737           for (var i = 0, n = type.length, c; i < n; ++i) {
13738             if ((c = type[i]).name === name) {
13739               return c.value;
13740             }
13741           }
13742         }
13743
13744         function set$1(type, name, callback) {
13745           for (var i = 0, n = type.length; i < n; ++i) {
13746             if (type[i].name === name) {
13747               type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));
13748               break;
13749             }
13750           }
13751
13752           if (callback != null) type.push({
13753             name: name,
13754             value: callback
13755           });
13756           return type;
13757         }
13758
13759         var xhtml = "http://www.w3.org/1999/xhtml";
13760         var namespaces = {
13761           svg: "http://www.w3.org/2000/svg",
13762           xhtml: xhtml,
13763           xlink: "http://www.w3.org/1999/xlink",
13764           xml: "http://www.w3.org/XML/1998/namespace",
13765           xmlns: "http://www.w3.org/2000/xmlns/"
13766         };
13767
13768         function namespace (name) {
13769           var prefix = name += "",
13770               i = prefix.indexOf(":");
13771           if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
13772           return namespaces.hasOwnProperty(prefix) ? {
13773             space: namespaces[prefix],
13774             local: name
13775           } : name; // eslint-disable-line no-prototype-builtins
13776         }
13777
13778         function creatorInherit(name) {
13779           return function () {
13780             var document = this.ownerDocument,
13781                 uri = this.namespaceURI;
13782             return uri === xhtml && document.documentElement.namespaceURI === xhtml ? document.createElement(name) : document.createElementNS(uri, name);
13783           };
13784         }
13785
13786         function creatorFixed(fullname) {
13787           return function () {
13788             return this.ownerDocument.createElementNS(fullname.space, fullname.local);
13789           };
13790         }
13791
13792         function creator (name) {
13793           var fullname = namespace(name);
13794           return (fullname.local ? creatorFixed : creatorInherit)(fullname);
13795         }
13796
13797         function none() {}
13798
13799         function selector (selector) {
13800           return selector == null ? none : function () {
13801             return this.querySelector(selector);
13802           };
13803         }
13804
13805         function selection_select (select) {
13806           if (typeof select !== "function") select = selector(select);
13807
13808           for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
13809             for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
13810               if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
13811                 if ("__data__" in node) subnode.__data__ = node.__data__;
13812                 subgroup[i] = subnode;
13813               }
13814             }
13815           }
13816
13817           return new Selection$1(subgroups, this._parents);
13818         }
13819
13820         function array (x) {
13821           return _typeof(x) === "object" && "length" in x ? x // Array, TypedArray, NodeList, array-like
13822           : Array.from(x); // Map, Set, iterable, string, or anything else
13823         }
13824
13825         function empty() {
13826           return [];
13827         }
13828
13829         function selectorAll (selector) {
13830           return selector == null ? empty : function () {
13831             return this.querySelectorAll(selector);
13832           };
13833         }
13834
13835         function arrayAll(select) {
13836           return function () {
13837             var group = select.apply(this, arguments);
13838             return group == null ? [] : array(group);
13839           };
13840         }
13841
13842         function selection_selectAll (select) {
13843           if (typeof select === "function") select = arrayAll(select);else select = selectorAll(select);
13844
13845           for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
13846             for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
13847               if (node = group[i]) {
13848                 subgroups.push(select.call(node, node.__data__, i, group));
13849                 parents.push(node);
13850               }
13851             }
13852           }
13853
13854           return new Selection$1(subgroups, parents);
13855         }
13856
13857         var $$u = _export;
13858         var $find = arrayIteration.find;
13859         var addToUnscopables$3 = addToUnscopables$6;
13860
13861         var FIND = 'find';
13862         var SKIPS_HOLES$1 = true;
13863
13864         // Shouldn't skip holes
13865         if (FIND in []) Array(1)[FIND](function () { SKIPS_HOLES$1 = false; });
13866
13867         // `Array.prototype.find` method
13868         // https://tc39.es/ecma262/#sec-array.prototype.find
13869         $$u({ target: 'Array', proto: true, forced: SKIPS_HOLES$1 }, {
13870           find: function find(callbackfn /* , that = undefined */) {
13871             return $find(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
13872           }
13873         });
13874
13875         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
13876         addToUnscopables$3(FIND);
13877
13878         function matcher (selector) {
13879           return function () {
13880             return this.matches(selector);
13881           };
13882         }
13883         function childMatcher(selector) {
13884           return function (node) {
13885             return node.matches(selector);
13886           };
13887         }
13888
13889         var find = Array.prototype.find;
13890
13891         function childFind(match) {
13892           return function () {
13893             return find.call(this.children, match);
13894           };
13895         }
13896
13897         function childFirst() {
13898           return this.firstElementChild;
13899         }
13900
13901         function selection_selectChild (match) {
13902           return this.select(match == null ? childFirst : childFind(typeof match === "function" ? match : childMatcher(match)));
13903         }
13904
13905         var filter = Array.prototype.filter;
13906
13907         function children() {
13908           return this.children;
13909         }
13910
13911         function childrenFilter(match) {
13912           return function () {
13913             return filter.call(this.children, match);
13914           };
13915         }
13916
13917         function selection_selectChildren (match) {
13918           return this.selectAll(match == null ? children : childrenFilter(typeof match === "function" ? match : childMatcher(match)));
13919         }
13920
13921         function selection_filter (match) {
13922           if (typeof match !== "function") match = matcher(match);
13923
13924           for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
13925             for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
13926               if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
13927                 subgroup.push(node);
13928               }
13929             }
13930           }
13931
13932           return new Selection$1(subgroups, this._parents);
13933         }
13934
13935         function sparse (update) {
13936           return new Array(update.length);
13937         }
13938
13939         function selection_enter () {
13940           return new Selection$1(this._enter || this._groups.map(sparse), this._parents);
13941         }
13942         function EnterNode(parent, datum) {
13943           this.ownerDocument = parent.ownerDocument;
13944           this.namespaceURI = parent.namespaceURI;
13945           this._next = null;
13946           this._parent = parent;
13947           this.__data__ = datum;
13948         }
13949         EnterNode.prototype = {
13950           constructor: EnterNode,
13951           appendChild: function appendChild(child) {
13952             return this._parent.insertBefore(child, this._next);
13953           },
13954           insertBefore: function insertBefore(child, next) {
13955             return this._parent.insertBefore(child, next);
13956           },
13957           querySelector: function querySelector(selector) {
13958             return this._parent.querySelector(selector);
13959           },
13960           querySelectorAll: function querySelectorAll(selector) {
13961             return this._parent.querySelectorAll(selector);
13962           }
13963         };
13964
13965         function constant$3 (x) {
13966           return function () {
13967             return x;
13968           };
13969         }
13970
13971         function bindIndex(parent, group, enter, update, exit, data) {
13972           var i = 0,
13973               node,
13974               groupLength = group.length,
13975               dataLength = data.length; // Put any non-null nodes that fit into update.
13976           // Put any null nodes into enter.
13977           // Put any remaining data into enter.
13978
13979           for (; i < dataLength; ++i) {
13980             if (node = group[i]) {
13981               node.__data__ = data[i];
13982               update[i] = node;
13983             } else {
13984               enter[i] = new EnterNode(parent, data[i]);
13985             }
13986           } // Put any non-null nodes that don’t fit into exit.
13987
13988
13989           for (; i < groupLength; ++i) {
13990             if (node = group[i]) {
13991               exit[i] = node;
13992             }
13993           }
13994         }
13995
13996         function bindKey(parent, group, enter, update, exit, data, key) {
13997           var i,
13998               node,
13999               nodeByKeyValue = new Map(),
14000               groupLength = group.length,
14001               dataLength = data.length,
14002               keyValues = new Array(groupLength),
14003               keyValue; // Compute the key for each node.
14004           // If multiple nodes have the same key, the duplicates are added to exit.
14005
14006           for (i = 0; i < groupLength; ++i) {
14007             if (node = group[i]) {
14008               keyValues[i] = keyValue = key.call(node, node.__data__, i, group) + "";
14009
14010               if (nodeByKeyValue.has(keyValue)) {
14011                 exit[i] = node;
14012               } else {
14013                 nodeByKeyValue.set(keyValue, node);
14014               }
14015             }
14016           } // Compute the key for each datum.
14017           // If there a node associated with this key, join and add it to update.
14018           // If there is not (or the key is a duplicate), add it to enter.
14019
14020
14021           for (i = 0; i < dataLength; ++i) {
14022             keyValue = key.call(parent, data[i], i, data) + "";
14023
14024             if (node = nodeByKeyValue.get(keyValue)) {
14025               update[i] = node;
14026               node.__data__ = data[i];
14027               nodeByKeyValue["delete"](keyValue);
14028             } else {
14029               enter[i] = new EnterNode(parent, data[i]);
14030             }
14031           } // Add any remaining nodes that were not bound to data to exit.
14032
14033
14034           for (i = 0; i < groupLength; ++i) {
14035             if ((node = group[i]) && nodeByKeyValue.get(keyValues[i]) === node) {
14036               exit[i] = node;
14037             }
14038           }
14039         }
14040
14041         function datum(node) {
14042           return node.__data__;
14043         }
14044
14045         function selection_data (value, key) {
14046           if (!arguments.length) return Array.from(this, datum);
14047           var bind = key ? bindKey : bindIndex,
14048               parents = this._parents,
14049               groups = this._groups;
14050           if (typeof value !== "function") value = constant$3(value);
14051
14052           for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
14053             var parent = parents[j],
14054                 group = groups[j],
14055                 groupLength = group.length,
14056                 data = array(value.call(parent, parent && parent.__data__, j, parents)),
14057                 dataLength = data.length,
14058                 enterGroup = enter[j] = new Array(dataLength),
14059                 updateGroup = update[j] = new Array(dataLength),
14060                 exitGroup = exit[j] = new Array(groupLength);
14061             bind(parent, group, enterGroup, updateGroup, exitGroup, data, key); // Now connect the enter nodes to their following update node, such that
14062             // appendChild can insert the materialized enter node before this node,
14063             // rather than at the end of the parent node.
14064
14065             for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
14066               if (previous = enterGroup[i0]) {
14067                 if (i0 >= i1) i1 = i0 + 1;
14068
14069                 while (!(next = updateGroup[i1]) && ++i1 < dataLength) {
14070                 }
14071
14072                 previous._next = next || null;
14073               }
14074             }
14075           }
14076
14077           update = new Selection$1(update, parents);
14078           update._enter = enter;
14079           update._exit = exit;
14080           return update;
14081         }
14082
14083         function selection_exit () {
14084           return new Selection$1(this._exit || this._groups.map(sparse), this._parents);
14085         }
14086
14087         function selection_join (onenter, onupdate, onexit) {
14088           var enter = this.enter(),
14089               update = this,
14090               exit = this.exit();
14091           enter = typeof onenter === "function" ? onenter(enter) : enter.append(onenter + "");
14092           if (onupdate != null) update = onupdate(update);
14093           if (onexit == null) exit.remove();else onexit(exit);
14094           return enter && update ? enter.merge(update).order() : update;
14095         }
14096
14097         function selection_merge (selection) {
14098           if (!(selection instanceof Selection$1)) throw new Error("invalid merge");
14099
14100           for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
14101             for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
14102               if (node = group0[i] || group1[i]) {
14103                 merge[i] = node;
14104               }
14105             }
14106           }
14107
14108           for (; j < m0; ++j) {
14109             merges[j] = groups0[j];
14110           }
14111
14112           return new Selection$1(merges, this._parents);
14113         }
14114
14115         function selection_order () {
14116           for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
14117             for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
14118               if (node = group[i]) {
14119                 if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next);
14120                 next = node;
14121               }
14122             }
14123           }
14124
14125           return this;
14126         }
14127
14128         function selection_sort (compare) {
14129           if (!compare) compare = ascending;
14130
14131           function compareNode(a, b) {
14132             return a && b ? compare(a.__data__, b.__data__) : !a - !b;
14133           }
14134
14135           for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
14136             for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
14137               if (node = group[i]) {
14138                 sortgroup[i] = node;
14139               }
14140             }
14141
14142             sortgroup.sort(compareNode);
14143           }
14144
14145           return new Selection$1(sortgroups, this._parents).order();
14146         }
14147
14148         function ascending(a, b) {
14149           return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
14150         }
14151
14152         function selection_call () {
14153           var callback = arguments[0];
14154           arguments[0] = this;
14155           callback.apply(null, arguments);
14156           return this;
14157         }
14158
14159         function selection_nodes () {
14160           return Array.from(this);
14161         }
14162
14163         function selection_node () {
14164           for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
14165             for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
14166               var node = group[i];
14167               if (node) return node;
14168             }
14169           }
14170
14171           return null;
14172         }
14173
14174         function selection_size () {
14175           var size = 0;
14176
14177           var _iterator = _createForOfIteratorHelper(this),
14178               _step;
14179
14180           try {
14181             for (_iterator.s(); !(_step = _iterator.n()).done;) {
14182               var node = _step.value;
14183               ++size;
14184             } // eslint-disable-line no-unused-vars
14185
14186           } catch (err) {
14187             _iterator.e(err);
14188           } finally {
14189             _iterator.f();
14190           }
14191
14192           return size;
14193         }
14194
14195         function selection_empty () {
14196           return !this.node();
14197         }
14198
14199         function selection_each (callback) {
14200           for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
14201             for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
14202               if (node = group[i]) callback.call(node, node.__data__, i, group);
14203             }
14204           }
14205
14206           return this;
14207         }
14208
14209         function attrRemove$1(name) {
14210           return function () {
14211             this.removeAttribute(name);
14212           };
14213         }
14214
14215         function attrRemoveNS$1(fullname) {
14216           return function () {
14217             this.removeAttributeNS(fullname.space, fullname.local);
14218           };
14219         }
14220
14221         function attrConstant$1(name, value) {
14222           return function () {
14223             this.setAttribute(name, value);
14224           };
14225         }
14226
14227         function attrConstantNS$1(fullname, value) {
14228           return function () {
14229             this.setAttributeNS(fullname.space, fullname.local, value);
14230           };
14231         }
14232
14233         function attrFunction$1(name, value) {
14234           return function () {
14235             var v = value.apply(this, arguments);
14236             if (v == null) this.removeAttribute(name);else this.setAttribute(name, v);
14237           };
14238         }
14239
14240         function attrFunctionNS$1(fullname, value) {
14241           return function () {
14242             var v = value.apply(this, arguments);
14243             if (v == null) this.removeAttributeNS(fullname.space, fullname.local);else this.setAttributeNS(fullname.space, fullname.local, v);
14244           };
14245         }
14246
14247         function selection_attr (name, value) {
14248           var fullname = namespace(name);
14249
14250           if (arguments.length < 2) {
14251             var node = this.node();
14252             return fullname.local ? node.getAttributeNS(fullname.space, fullname.local) : node.getAttribute(fullname);
14253           }
14254
14255           return this.each((value == null ? fullname.local ? attrRemoveNS$1 : attrRemove$1 : typeof value === "function" ? fullname.local ? attrFunctionNS$1 : attrFunction$1 : fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, value));
14256         }
14257
14258         function defaultView (node) {
14259           return node.ownerDocument && node.ownerDocument.defaultView // node is a Node
14260           || node.document && node // node is a Window
14261           || node.defaultView; // node is a Document
14262         }
14263
14264         function styleRemove$1(name) {
14265           return function () {
14266             this.style.removeProperty(name);
14267           };
14268         }
14269
14270         function styleConstant$1(name, value, priority) {
14271           return function () {
14272             this.style.setProperty(name, value, priority);
14273           };
14274         }
14275
14276         function styleFunction$1(name, value, priority) {
14277           return function () {
14278             var v = value.apply(this, arguments);
14279             if (v == null) this.style.removeProperty(name);else this.style.setProperty(name, v, priority);
14280           };
14281         }
14282
14283         function selection_style (name, value, priority) {
14284           return arguments.length > 1 ? this.each((value == null ? styleRemove$1 : typeof value === "function" ? styleFunction$1 : styleConstant$1)(name, value, priority == null ? "" : priority)) : styleValue(this.node(), name);
14285         }
14286         function styleValue(node, name) {
14287           return node.style.getPropertyValue(name) || defaultView(node).getComputedStyle(node, null).getPropertyValue(name);
14288         }
14289
14290         function propertyRemove(name) {
14291           return function () {
14292             delete this[name];
14293           };
14294         }
14295
14296         function propertyConstant(name, value) {
14297           return function () {
14298             this[name] = value;
14299           };
14300         }
14301
14302         function propertyFunction(name, value) {
14303           return function () {
14304             var v = value.apply(this, arguments);
14305             if (v == null) delete this[name];else this[name] = v;
14306           };
14307         }
14308
14309         function selection_property (name, value) {
14310           return arguments.length > 1 ? this.each((value == null ? propertyRemove : typeof value === "function" ? propertyFunction : propertyConstant)(name, value)) : this.node()[name];
14311         }
14312
14313         function classArray(string) {
14314           return string.trim().split(/^|\s+/);
14315         }
14316
14317         function classList(node) {
14318           return node.classList || new ClassList(node);
14319         }
14320
14321         function ClassList(node) {
14322           this._node = node;
14323           this._names = classArray(node.getAttribute("class") || "");
14324         }
14325
14326         ClassList.prototype = {
14327           add: function add(name) {
14328             var i = this._names.indexOf(name);
14329
14330             if (i < 0) {
14331               this._names.push(name);
14332
14333               this._node.setAttribute("class", this._names.join(" "));
14334             }
14335           },
14336           remove: function remove(name) {
14337             var i = this._names.indexOf(name);
14338
14339             if (i >= 0) {
14340               this._names.splice(i, 1);
14341
14342               this._node.setAttribute("class", this._names.join(" "));
14343             }
14344           },
14345           contains: function contains(name) {
14346             return this._names.indexOf(name) >= 0;
14347           }
14348         };
14349
14350         function classedAdd(node, names) {
14351           var list = classList(node),
14352               i = -1,
14353               n = names.length;
14354
14355           while (++i < n) {
14356             list.add(names[i]);
14357           }
14358         }
14359
14360         function classedRemove(node, names) {
14361           var list = classList(node),
14362               i = -1,
14363               n = names.length;
14364
14365           while (++i < n) {
14366             list.remove(names[i]);
14367           }
14368         }
14369
14370         function classedTrue(names) {
14371           return function () {
14372             classedAdd(this, names);
14373           };
14374         }
14375
14376         function classedFalse(names) {
14377           return function () {
14378             classedRemove(this, names);
14379           };
14380         }
14381
14382         function classedFunction(names, value) {
14383           return function () {
14384             (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
14385           };
14386         }
14387
14388         function selection_classed (name, value) {
14389           var names = classArray(name + "");
14390
14391           if (arguments.length < 2) {
14392             var list = classList(this.node()),
14393                 i = -1,
14394                 n = names.length;
14395
14396             while (++i < n) {
14397               if (!list.contains(names[i])) return false;
14398             }
14399
14400             return true;
14401           }
14402
14403           return this.each((typeof value === "function" ? classedFunction : value ? classedTrue : classedFalse)(names, value));
14404         }
14405
14406         function textRemove() {
14407           this.textContent = "";
14408         }
14409
14410         function textConstant$1(value) {
14411           return function () {
14412             this.textContent = value;
14413           };
14414         }
14415
14416         function textFunction$1(value) {
14417           return function () {
14418             var v = value.apply(this, arguments);
14419             this.textContent = v == null ? "" : v;
14420           };
14421         }
14422
14423         function selection_text (value) {
14424           return arguments.length ? this.each(value == null ? textRemove : (typeof value === "function" ? textFunction$1 : textConstant$1)(value)) : this.node().textContent;
14425         }
14426
14427         function htmlRemove() {
14428           this.innerHTML = "";
14429         }
14430
14431         function htmlConstant(value) {
14432           return function () {
14433             this.innerHTML = value;
14434           };
14435         }
14436
14437         function htmlFunction(value) {
14438           return function () {
14439             var v = value.apply(this, arguments);
14440             this.innerHTML = v == null ? "" : v;
14441           };
14442         }
14443
14444         function selection_html (value) {
14445           return arguments.length ? this.each(value == null ? htmlRemove : (typeof value === "function" ? htmlFunction : htmlConstant)(value)) : this.node().innerHTML;
14446         }
14447
14448         function raise() {
14449           if (this.nextSibling) this.parentNode.appendChild(this);
14450         }
14451
14452         function selection_raise () {
14453           return this.each(raise);
14454         }
14455
14456         function lower() {
14457           if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
14458         }
14459
14460         function selection_lower () {
14461           return this.each(lower);
14462         }
14463
14464         function selection_append (name) {
14465           var create = typeof name === "function" ? name : creator(name);
14466           return this.select(function () {
14467             return this.appendChild(create.apply(this, arguments));
14468           });
14469         }
14470
14471         function constantNull() {
14472           return null;
14473         }
14474
14475         function selection_insert (name, before) {
14476           var create = typeof name === "function" ? name : creator(name),
14477               select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
14478           return this.select(function () {
14479             return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
14480           });
14481         }
14482
14483         function remove$7() {
14484           var parent = this.parentNode;
14485           if (parent) parent.removeChild(this);
14486         }
14487
14488         function selection_remove () {
14489           return this.each(remove$7);
14490         }
14491
14492         function selection_cloneShallow() {
14493           var clone = this.cloneNode(false),
14494               parent = this.parentNode;
14495           return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
14496         }
14497
14498         function selection_cloneDeep() {
14499           var clone = this.cloneNode(true),
14500               parent = this.parentNode;
14501           return parent ? parent.insertBefore(clone, this.nextSibling) : clone;
14502         }
14503
14504         function selection_clone (deep) {
14505           return this.select(deep ? selection_cloneDeep : selection_cloneShallow);
14506         }
14507
14508         function selection_datum (value) {
14509           return arguments.length ? this.property("__data__", value) : this.node().__data__;
14510         }
14511
14512         function contextListener(listener) {
14513           return function (event) {
14514             listener.call(this, event, this.__data__);
14515           };
14516         }
14517
14518         function parseTypenames(typenames) {
14519           return typenames.trim().split(/^|\s+/).map(function (t) {
14520             var name = "",
14521                 i = t.indexOf(".");
14522             if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
14523             return {
14524               type: t,
14525               name: name
14526             };
14527           });
14528         }
14529
14530         function onRemove(typename) {
14531           return function () {
14532             var on = this.__on;
14533             if (!on) return;
14534
14535             for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
14536               if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
14537                 this.removeEventListener(o.type, o.listener, o.options);
14538               } else {
14539                 on[++i] = o;
14540               }
14541             }
14542
14543             if (++i) on.length = i;else delete this.__on;
14544           };
14545         }
14546
14547         function onAdd(typename, value, options) {
14548           return function () {
14549             var on = this.__on,
14550                 o,
14551                 listener = contextListener(value);
14552             if (on) for (var j = 0, m = on.length; j < m; ++j) {
14553               if ((o = on[j]).type === typename.type && o.name === typename.name) {
14554                 this.removeEventListener(o.type, o.listener, o.options);
14555                 this.addEventListener(o.type, o.listener = listener, o.options = options);
14556                 o.value = value;
14557                 return;
14558               }
14559             }
14560             this.addEventListener(typename.type, listener, options);
14561             o = {
14562               type: typename.type,
14563               name: typename.name,
14564               value: value,
14565               listener: listener,
14566               options: options
14567             };
14568             if (!on) this.__on = [o];else on.push(o);
14569           };
14570         }
14571
14572         function selection_on (typename, value, options) {
14573           var typenames = parseTypenames(typename + ""),
14574               i,
14575               n = typenames.length,
14576               t;
14577
14578           if (arguments.length < 2) {
14579             var on = this.node().__on;
14580
14581             if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
14582               for (i = 0, o = on[j]; i < n; ++i) {
14583                 if ((t = typenames[i]).type === o.type && t.name === o.name) {
14584                   return o.value;
14585                 }
14586               }
14587             }
14588             return;
14589           }
14590
14591           on = value ? onAdd : onRemove;
14592
14593           for (i = 0; i < n; ++i) {
14594             this.each(on(typenames[i], value, options));
14595           }
14596
14597           return this;
14598         }
14599
14600         function dispatchEvent(node, type, params) {
14601           var window = defaultView(node),
14602               event = window.CustomEvent;
14603
14604           if (typeof event === "function") {
14605             event = new event(type, params);
14606           } else {
14607             event = window.document.createEvent("Event");
14608             if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;else event.initEvent(type, false, false);
14609           }
14610
14611           node.dispatchEvent(event);
14612         }
14613
14614         function dispatchConstant(type, params) {
14615           return function () {
14616             return dispatchEvent(this, type, params);
14617           };
14618         }
14619
14620         function dispatchFunction(type, params) {
14621           return function () {
14622             return dispatchEvent(this, type, params.apply(this, arguments));
14623           };
14624         }
14625
14626         function selection_dispatch (type, params) {
14627           return this.each((typeof params === "function" ? dispatchFunction : dispatchConstant)(type, params));
14628         }
14629
14630         var _marked$1 = /*#__PURE__*/regeneratorRuntime.mark(_callee);
14631
14632         function _callee() {
14633           var groups, j, m, group, i, n, node;
14634           return regeneratorRuntime.wrap(function _callee$(_context) {
14635             while (1) {
14636               switch (_context.prev = _context.next) {
14637                 case 0:
14638                   groups = this._groups, j = 0, m = groups.length;
14639
14640                 case 1:
14641                   if (!(j < m)) {
14642                     _context.next = 13;
14643                     break;
14644                   }
14645
14646                   group = groups[j], i = 0, n = group.length;
14647
14648                 case 3:
14649                   if (!(i < n)) {
14650                     _context.next = 10;
14651                     break;
14652                   }
14653
14654                   if (!(node = group[i])) {
14655                     _context.next = 7;
14656                     break;
14657                   }
14658
14659                   _context.next = 7;
14660                   return node;
14661
14662                 case 7:
14663                   ++i;
14664                   _context.next = 3;
14665                   break;
14666
14667                 case 10:
14668                   ++j;
14669                   _context.next = 1;
14670                   break;
14671
14672                 case 13:
14673                 case "end":
14674                   return _context.stop();
14675               }
14676             }
14677           }, _marked$1, this);
14678         }
14679
14680         var root$1 = [null];
14681         function Selection$1(groups, parents) {
14682           this._groups = groups;
14683           this._parents = parents;
14684         }
14685
14686         function selection() {
14687           return new Selection$1([[document.documentElement]], root$1);
14688         }
14689
14690         function selection_selection() {
14691           return this;
14692         }
14693
14694         Selection$1.prototype = selection.prototype = _defineProperty({
14695           constructor: Selection$1,
14696           select: selection_select,
14697           selectAll: selection_selectAll,
14698           selectChild: selection_selectChild,
14699           selectChildren: selection_selectChildren,
14700           filter: selection_filter,
14701           data: selection_data,
14702           enter: selection_enter,
14703           exit: selection_exit,
14704           join: selection_join,
14705           merge: selection_merge,
14706           selection: selection_selection,
14707           order: selection_order,
14708           sort: selection_sort,
14709           call: selection_call,
14710           nodes: selection_nodes,
14711           node: selection_node,
14712           size: selection_size,
14713           empty: selection_empty,
14714           each: selection_each,
14715           attr: selection_attr,
14716           style: selection_style,
14717           property: selection_property,
14718           classed: selection_classed,
14719           text: selection_text,
14720           html: selection_html,
14721           raise: selection_raise,
14722           lower: selection_lower,
14723           append: selection_append,
14724           insert: selection_insert,
14725           remove: selection_remove,
14726           clone: selection_clone,
14727           datum: selection_datum,
14728           on: selection_on,
14729           dispatch: selection_dispatch
14730         }, Symbol.iterator, _callee);
14731
14732         function select (selector) {
14733           return typeof selector === "string" ? new Selection$1([[document.querySelector(selector)]], [document.documentElement]) : new Selection$1([[selector]], root$1);
14734         }
14735
14736         function sourceEvent (event) {
14737           var sourceEvent;
14738
14739           while (sourceEvent = event.sourceEvent) {
14740             event = sourceEvent;
14741           }
14742
14743           return event;
14744         }
14745
14746         function pointer (event, node) {
14747           event = sourceEvent(event);
14748           if (node === undefined) node = event.currentTarget;
14749
14750           if (node) {
14751             var svg = node.ownerSVGElement || node;
14752
14753             if (svg.createSVGPoint) {
14754               var point = svg.createSVGPoint();
14755               point.x = event.clientX, point.y = event.clientY;
14756               point = point.matrixTransform(node.getScreenCTM().inverse());
14757               return [point.x, point.y];
14758             }
14759
14760             if (node.getBoundingClientRect) {
14761               var rect = node.getBoundingClientRect();
14762               return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
14763             }
14764           }
14765
14766           return [event.pageX, event.pageY];
14767         }
14768
14769         function selectAll (selector) {
14770           return typeof selector === "string" ? new Selection$1([document.querySelectorAll(selector)], [document.documentElement]) : new Selection$1([selector == null ? [] : array(selector)], root$1);
14771         }
14772
14773         function nopropagation$1(event) {
14774           event.stopImmediatePropagation();
14775         }
14776         function noevent$1 (event) {
14777           event.preventDefault();
14778           event.stopImmediatePropagation();
14779         }
14780
14781         function dragDisable (view) {
14782           var root = view.document.documentElement,
14783               selection = select(view).on("dragstart.drag", noevent$1, true);
14784
14785           if ("onselectstart" in root) {
14786             selection.on("selectstart.drag", noevent$1, true);
14787           } else {
14788             root.__noselect = root.style.MozUserSelect;
14789             root.style.MozUserSelect = "none";
14790           }
14791         }
14792         function yesdrag(view, noclick) {
14793           var root = view.document.documentElement,
14794               selection = select(view).on("dragstart.drag", null);
14795
14796           if (noclick) {
14797             selection.on("click.drag", noevent$1, true);
14798             setTimeout(function () {
14799               selection.on("click.drag", null);
14800             }, 0);
14801           }
14802
14803           if ("onselectstart" in root) {
14804             selection.on("selectstart.drag", null);
14805           } else {
14806             root.style.MozUserSelect = root.__noselect;
14807             delete root.__noselect;
14808           }
14809         }
14810
14811         var constant$2 = (function (x) {
14812           return function () {
14813             return x;
14814           };
14815         });
14816
14817         function DragEvent(type, _ref) {
14818           var sourceEvent = _ref.sourceEvent,
14819               subject = _ref.subject,
14820               target = _ref.target,
14821               identifier = _ref.identifier,
14822               active = _ref.active,
14823               x = _ref.x,
14824               y = _ref.y,
14825               dx = _ref.dx,
14826               dy = _ref.dy,
14827               dispatch = _ref.dispatch;
14828           Object.defineProperties(this, {
14829             type: {
14830               value: type,
14831               enumerable: true,
14832               configurable: true
14833             },
14834             sourceEvent: {
14835               value: sourceEvent,
14836               enumerable: true,
14837               configurable: true
14838             },
14839             subject: {
14840               value: subject,
14841               enumerable: true,
14842               configurable: true
14843             },
14844             target: {
14845               value: target,
14846               enumerable: true,
14847               configurable: true
14848             },
14849             identifier: {
14850               value: identifier,
14851               enumerable: true,
14852               configurable: true
14853             },
14854             active: {
14855               value: active,
14856               enumerable: true,
14857               configurable: true
14858             },
14859             x: {
14860               value: x,
14861               enumerable: true,
14862               configurable: true
14863             },
14864             y: {
14865               value: y,
14866               enumerable: true,
14867               configurable: true
14868             },
14869             dx: {
14870               value: dx,
14871               enumerable: true,
14872               configurable: true
14873             },
14874             dy: {
14875               value: dy,
14876               enumerable: true,
14877               configurable: true
14878             },
14879             _: {
14880               value: dispatch
14881             }
14882           });
14883         }
14884
14885         DragEvent.prototype.on = function () {
14886           var value = this._.on.apply(this._, arguments);
14887
14888           return value === this._ ? this : value;
14889         };
14890
14891         function defaultFilter$2(event) {
14892           return !event.ctrlKey && !event.button;
14893         }
14894
14895         function defaultContainer() {
14896           return this.parentNode;
14897         }
14898
14899         function defaultSubject(event, d) {
14900           return d == null ? {
14901             x: event.x,
14902             y: event.y
14903           } : d;
14904         }
14905
14906         function defaultTouchable$1() {
14907           return navigator.maxTouchPoints || "ontouchstart" in this;
14908         }
14909
14910         function d3_drag () {
14911           var filter = defaultFilter$2,
14912               container = defaultContainer,
14913               subject = defaultSubject,
14914               touchable = defaultTouchable$1,
14915               gestures = {},
14916               listeners = dispatch$8("start", "drag", "end"),
14917               active = 0,
14918               mousedownx,
14919               mousedowny,
14920               mousemoving,
14921               touchending,
14922               clickDistance2 = 0;
14923
14924           function drag(selection) {
14925             selection.on("mousedown.drag", mousedowned).filter(touchable).on("touchstart.drag", touchstarted).on("touchmove.drag", touchmoved).on("touchend.drag touchcancel.drag", touchended).style("touch-action", "none").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
14926           }
14927
14928           function mousedowned(event, d) {
14929             if (touchending || !filter.call(this, event, d)) return;
14930             var gesture = beforestart(this, container.call(this, event, d), event, d, "mouse");
14931             if (!gesture) return;
14932             select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true);
14933             dragDisable(event.view);
14934             nopropagation$1(event);
14935             mousemoving = false;
14936             mousedownx = event.clientX;
14937             mousedowny = event.clientY;
14938             gesture("start", event);
14939           }
14940
14941           function mousemoved(event) {
14942             noevent$1(event);
14943
14944             if (!mousemoving) {
14945               var dx = event.clientX - mousedownx,
14946                   dy = event.clientY - mousedowny;
14947               mousemoving = dx * dx + dy * dy > clickDistance2;
14948             }
14949
14950             gestures.mouse("drag", event);
14951           }
14952
14953           function mouseupped(event) {
14954             select(event.view).on("mousemove.drag mouseup.drag", null);
14955             yesdrag(event.view, mousemoving);
14956             noevent$1(event);
14957             gestures.mouse("end", event);
14958           }
14959
14960           function touchstarted(event, d) {
14961             if (!filter.call(this, event, d)) return;
14962             var touches = event.changedTouches,
14963                 c = container.call(this, event, d),
14964                 n = touches.length,
14965                 i,
14966                 gesture;
14967
14968             for (i = 0; i < n; ++i) {
14969               if (gesture = beforestart(this, c, event, d, touches[i].identifier, touches[i])) {
14970                 nopropagation$1(event);
14971                 gesture("start", event, touches[i]);
14972               }
14973             }
14974           }
14975
14976           function touchmoved(event) {
14977             var touches = event.changedTouches,
14978                 n = touches.length,
14979                 i,
14980                 gesture;
14981
14982             for (i = 0; i < n; ++i) {
14983               if (gesture = gestures[touches[i].identifier]) {
14984                 noevent$1(event);
14985                 gesture("drag", event, touches[i]);
14986               }
14987             }
14988           }
14989
14990           function touchended(event) {
14991             var touches = event.changedTouches,
14992                 n = touches.length,
14993                 i,
14994                 gesture;
14995             if (touchending) clearTimeout(touchending);
14996             touchending = setTimeout(function () {
14997               touchending = null;
14998             }, 500); // Ghost clicks are delayed!
14999
15000             for (i = 0; i < n; ++i) {
15001               if (gesture = gestures[touches[i].identifier]) {
15002                 nopropagation$1(event);
15003                 gesture("end", event, touches[i]);
15004               }
15005             }
15006           }
15007
15008           function beforestart(that, container, event, d, identifier, touch) {
15009             var dispatch = listeners.copy(),
15010                 p = pointer(touch || event, container),
15011                 dx,
15012                 dy,
15013                 s;
15014             if ((s = subject.call(that, new DragEvent("beforestart", {
15015               sourceEvent: event,
15016               target: drag,
15017               identifier: identifier,
15018               active: active,
15019               x: p[0],
15020               y: p[1],
15021               dx: 0,
15022               dy: 0,
15023               dispatch: dispatch
15024             }), d)) == null) return;
15025             dx = s.x - p[0] || 0;
15026             dy = s.y - p[1] || 0;
15027             return function gesture(type, event, touch) {
15028               var p0 = p,
15029                   n;
15030
15031               switch (type) {
15032                 case "start":
15033                   gestures[identifier] = gesture, n = active++;
15034                   break;
15035
15036                 case "end":
15037                   delete gestures[identifier], --active;
15038                 // nobreak
15039
15040                 case "drag":
15041                   p = pointer(touch || event, container), n = active;
15042                   break;
15043               }
15044
15045               dispatch.call(type, that, new DragEvent(type, {
15046                 sourceEvent: event,
15047                 subject: s,
15048                 target: drag,
15049                 identifier: identifier,
15050                 active: n,
15051                 x: p[0] + dx,
15052                 y: p[1] + dy,
15053                 dx: p[0] - p0[0],
15054                 dy: p[1] - p0[1],
15055                 dispatch: dispatch
15056               }), d);
15057             };
15058           }
15059
15060           drag.filter = function (_) {
15061             return arguments.length ? (filter = typeof _ === "function" ? _ : constant$2(!!_), drag) : filter;
15062           };
15063
15064           drag.container = function (_) {
15065             return arguments.length ? (container = typeof _ === "function" ? _ : constant$2(_), drag) : container;
15066           };
15067
15068           drag.subject = function (_) {
15069             return arguments.length ? (subject = typeof _ === "function" ? _ : constant$2(_), drag) : subject;
15070           };
15071
15072           drag.touchable = function (_) {
15073             return arguments.length ? (touchable = typeof _ === "function" ? _ : constant$2(!!_), drag) : touchable;
15074           };
15075
15076           drag.on = function () {
15077             var value = listeners.on.apply(listeners, arguments);
15078             return value === listeners ? drag : value;
15079           };
15080
15081           drag.clickDistance = function (_) {
15082             return arguments.length ? (clickDistance2 = (_ = +_) * _, drag) : Math.sqrt(clickDistance2);
15083           };
15084
15085           return drag;
15086         }
15087
15088         var DESCRIPTORS$4 = descriptors;
15089         var global$b = global$1o;
15090         var uncurryThis$e = functionUncurryThis;
15091         var isForced$1 = isForced_1;
15092         var inheritIfRequired$1 = inheritIfRequired$4;
15093         var createNonEnumerableProperty = createNonEnumerableProperty$b;
15094         var defineProperty$1 = objectDefineProperty.f;
15095         var getOwnPropertyNames$1 = objectGetOwnPropertyNames.f;
15096         var isPrototypeOf$1 = objectIsPrototypeOf;
15097         var isRegExp$1 = isRegexp;
15098         var toString$9 = toString$k;
15099         var regExpFlags$1 = regexpFlags$1;
15100         var stickyHelpers = regexpStickyHelpers;
15101         var redefine$3 = redefine$h.exports;
15102         var fails$a = fails$V;
15103         var hasOwn$2 = hasOwnProperty_1;
15104         var enforceInternalState = internalState.enforce;
15105         var setSpecies = setSpecies$5;
15106         var wellKnownSymbol$1 = wellKnownSymbol$t;
15107         var UNSUPPORTED_DOT_ALL = regexpUnsupportedDotAll;
15108         var UNSUPPORTED_NCG = regexpUnsupportedNcg;
15109
15110         var MATCH$1 = wellKnownSymbol$1('match');
15111         var NativeRegExp = global$b.RegExp;
15112         var RegExpPrototype$1 = NativeRegExp.prototype;
15113         var SyntaxError$1 = global$b.SyntaxError;
15114         var getFlags = uncurryThis$e(regExpFlags$1);
15115         var exec$2 = uncurryThis$e(RegExpPrototype$1.exec);
15116         var charAt$1 = uncurryThis$e(''.charAt);
15117         var replace$3 = uncurryThis$e(''.replace);
15118         var stringIndexOf$1 = uncurryThis$e(''.indexOf);
15119         var stringSlice$4 = uncurryThis$e(''.slice);
15120         // TODO: Use only propper RegExpIdentifierName
15121         var IS_NCG = /^\?<[^\s\d!#%&*+<=>@^][^\s!#%&*+<=>@^]*>/;
15122         var re1 = /a/g;
15123         var re2 = /a/g;
15124
15125         // "new" should create a new object, old webkit bug
15126         var CORRECT_NEW = new NativeRegExp(re1) !== re1;
15127
15128         var MISSED_STICKY = stickyHelpers.MISSED_STICKY;
15129         var UNSUPPORTED_Y = stickyHelpers.UNSUPPORTED_Y;
15130
15131         var BASE_FORCED = DESCRIPTORS$4 &&
15132           (!CORRECT_NEW || MISSED_STICKY || UNSUPPORTED_DOT_ALL || UNSUPPORTED_NCG || fails$a(function () {
15133             re2[MATCH$1] = false;
15134             // RegExp constructor can alter flags and IsRegExp works correct with @@match
15135             return NativeRegExp(re1) != re1 || NativeRegExp(re2) == re2 || NativeRegExp(re1, 'i') != '/a/i';
15136           }));
15137
15138         var handleDotAll = function (string) {
15139           var length = string.length;
15140           var index = 0;
15141           var result = '';
15142           var brackets = false;
15143           var chr;
15144           for (; index <= length; index++) {
15145             chr = charAt$1(string, index);
15146             if (chr === '\\') {
15147               result += chr + charAt$1(string, ++index);
15148               continue;
15149             }
15150             if (!brackets && chr === '.') {
15151               result += '[\\s\\S]';
15152             } else {
15153               if (chr === '[') {
15154                 brackets = true;
15155               } else if (chr === ']') {
15156                 brackets = false;
15157               } result += chr;
15158             }
15159           } return result;
15160         };
15161
15162         var handleNCG = function (string) {
15163           var length = string.length;
15164           var index = 0;
15165           var result = '';
15166           var named = [];
15167           var names = {};
15168           var brackets = false;
15169           var ncg = false;
15170           var groupid = 0;
15171           var groupname = '';
15172           var chr;
15173           for (; index <= length; index++) {
15174             chr = charAt$1(string, index);
15175             if (chr === '\\') {
15176               chr = chr + charAt$1(string, ++index);
15177             } else if (chr === ']') {
15178               brackets = false;
15179             } else if (!brackets) switch (true) {
15180               case chr === '[':
15181                 brackets = true;
15182                 break;
15183               case chr === '(':
15184                 if (exec$2(IS_NCG, stringSlice$4(string, index + 1))) {
15185                   index += 2;
15186                   ncg = true;
15187                 }
15188                 result += chr;
15189                 groupid++;
15190                 continue;
15191               case chr === '>' && ncg:
15192                 if (groupname === '' || hasOwn$2(names, groupname)) {
15193                   throw new SyntaxError$1('Invalid capture group name');
15194                 }
15195                 names[groupname] = true;
15196                 named[named.length] = [groupname, groupid];
15197                 ncg = false;
15198                 groupname = '';
15199                 continue;
15200             }
15201             if (ncg) groupname += chr;
15202             else result += chr;
15203           } return [result, named];
15204         };
15205
15206         // `RegExp` constructor
15207         // https://tc39.es/ecma262/#sec-regexp-constructor
15208         if (isForced$1('RegExp', BASE_FORCED)) {
15209           var RegExpWrapper = function RegExp(pattern, flags) {
15210             var thisIsRegExp = isPrototypeOf$1(RegExpPrototype$1, this);
15211             var patternIsRegExp = isRegExp$1(pattern);
15212             var flagsAreUndefined = flags === undefined;
15213             var groups = [];
15214             var rawPattern = pattern;
15215             var rawFlags, dotAll, sticky, handled, result, state;
15216
15217             if (!thisIsRegExp && patternIsRegExp && flagsAreUndefined && pattern.constructor === RegExpWrapper) {
15218               return pattern;
15219             }
15220
15221             if (patternIsRegExp || isPrototypeOf$1(RegExpPrototype$1, pattern)) {
15222               pattern = pattern.source;
15223               if (flagsAreUndefined) flags = 'flags' in rawPattern ? rawPattern.flags : getFlags(rawPattern);
15224             }
15225
15226             pattern = pattern === undefined ? '' : toString$9(pattern);
15227             flags = flags === undefined ? '' : toString$9(flags);
15228             rawPattern = pattern;
15229
15230             if (UNSUPPORTED_DOT_ALL && 'dotAll' in re1) {
15231               dotAll = !!flags && stringIndexOf$1(flags, 's') > -1;
15232               if (dotAll) flags = replace$3(flags, /s/g, '');
15233             }
15234
15235             rawFlags = flags;
15236
15237             if (MISSED_STICKY && 'sticky' in re1) {
15238               sticky = !!flags && stringIndexOf$1(flags, 'y') > -1;
15239               if (sticky && UNSUPPORTED_Y) flags = replace$3(flags, /y/g, '');
15240             }
15241
15242             if (UNSUPPORTED_NCG) {
15243               handled = handleNCG(pattern);
15244               pattern = handled[0];
15245               groups = handled[1];
15246             }
15247
15248             result = inheritIfRequired$1(NativeRegExp(pattern, flags), thisIsRegExp ? this : RegExpPrototype$1, RegExpWrapper);
15249
15250             if (dotAll || sticky || groups.length) {
15251               state = enforceInternalState(result);
15252               if (dotAll) {
15253                 state.dotAll = true;
15254                 state.raw = RegExpWrapper(handleDotAll(pattern), rawFlags);
15255               }
15256               if (sticky) state.sticky = true;
15257               if (groups.length) state.groups = groups;
15258             }
15259
15260             if (pattern !== rawPattern) try {
15261               // fails in old engines, but we have no alternatives for unsupported regex syntax
15262               createNonEnumerableProperty(result, 'source', rawPattern === '' ? '(?:)' : rawPattern);
15263             } catch (error) { /* empty */ }
15264
15265             return result;
15266           };
15267
15268           var proxy = function (key) {
15269             key in RegExpWrapper || defineProperty$1(RegExpWrapper, key, {
15270               configurable: true,
15271               get: function () { return NativeRegExp[key]; },
15272               set: function (it) { NativeRegExp[key] = it; }
15273             });
15274           };
15275
15276           for (var keys$1 = getOwnPropertyNames$1(NativeRegExp), index$1 = 0; keys$1.length > index$1;) {
15277             proxy(keys$1[index$1++]);
15278           }
15279
15280           RegExpPrototype$1.constructor = RegExpWrapper;
15281           RegExpWrapper.prototype = RegExpPrototype$1;
15282           redefine$3(global$b, 'RegExp', RegExpWrapper);
15283         }
15284
15285         // https://tc39.es/ecma262/#sec-get-regexp-@@species
15286         setSpecies('RegExp');
15287
15288         function define (constructor, factory, prototype) {
15289           constructor.prototype = factory.prototype = prototype;
15290           prototype.constructor = constructor;
15291         }
15292         function extend$3(parent, definition) {
15293           var prototype = Object.create(parent.prototype);
15294
15295           for (var key in definition) {
15296             prototype[key] = definition[key];
15297           }
15298
15299           return prototype;
15300         }
15301
15302         function Color() {}
15303         var _darker = 0.7;
15304
15305         var _brighter = 1 / _darker;
15306         var reI = "\\s*([+-]?\\d+)\\s*",
15307             reN = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",
15308             reP = "\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",
15309             reHex = /^#([0-9a-f]{3,8})$/,
15310             reRgbInteger = new RegExp("^rgb\\(" + [reI, reI, reI] + "\\)$"),
15311             reRgbPercent = new RegExp("^rgb\\(" + [reP, reP, reP] + "\\)$"),
15312             reRgbaInteger = new RegExp("^rgba\\(" + [reI, reI, reI, reN] + "\\)$"),
15313             reRgbaPercent = new RegExp("^rgba\\(" + [reP, reP, reP, reN] + "\\)$"),
15314             reHslPercent = new RegExp("^hsl\\(" + [reN, reP, reP] + "\\)$"),
15315             reHslaPercent = new RegExp("^hsla\\(" + [reN, reP, reP, reN] + "\\)$");
15316         var named = {
15317           aliceblue: 0xf0f8ff,
15318           antiquewhite: 0xfaebd7,
15319           aqua: 0x00ffff,
15320           aquamarine: 0x7fffd4,
15321           azure: 0xf0ffff,
15322           beige: 0xf5f5dc,
15323           bisque: 0xffe4c4,
15324           black: 0x000000,
15325           blanchedalmond: 0xffebcd,
15326           blue: 0x0000ff,
15327           blueviolet: 0x8a2be2,
15328           brown: 0xa52a2a,
15329           burlywood: 0xdeb887,
15330           cadetblue: 0x5f9ea0,
15331           chartreuse: 0x7fff00,
15332           chocolate: 0xd2691e,
15333           coral: 0xff7f50,
15334           cornflowerblue: 0x6495ed,
15335           cornsilk: 0xfff8dc,
15336           crimson: 0xdc143c,
15337           cyan: 0x00ffff,
15338           darkblue: 0x00008b,
15339           darkcyan: 0x008b8b,
15340           darkgoldenrod: 0xb8860b,
15341           darkgray: 0xa9a9a9,
15342           darkgreen: 0x006400,
15343           darkgrey: 0xa9a9a9,
15344           darkkhaki: 0xbdb76b,
15345           darkmagenta: 0x8b008b,
15346           darkolivegreen: 0x556b2f,
15347           darkorange: 0xff8c00,
15348           darkorchid: 0x9932cc,
15349           darkred: 0x8b0000,
15350           darksalmon: 0xe9967a,
15351           darkseagreen: 0x8fbc8f,
15352           darkslateblue: 0x483d8b,
15353           darkslategray: 0x2f4f4f,
15354           darkslategrey: 0x2f4f4f,
15355           darkturquoise: 0x00ced1,
15356           darkviolet: 0x9400d3,
15357           deeppink: 0xff1493,
15358           deepskyblue: 0x00bfff,
15359           dimgray: 0x696969,
15360           dimgrey: 0x696969,
15361           dodgerblue: 0x1e90ff,
15362           firebrick: 0xb22222,
15363           floralwhite: 0xfffaf0,
15364           forestgreen: 0x228b22,
15365           fuchsia: 0xff00ff,
15366           gainsboro: 0xdcdcdc,
15367           ghostwhite: 0xf8f8ff,
15368           gold: 0xffd700,
15369           goldenrod: 0xdaa520,
15370           gray: 0x808080,
15371           green: 0x008000,
15372           greenyellow: 0xadff2f,
15373           grey: 0x808080,
15374           honeydew: 0xf0fff0,
15375           hotpink: 0xff69b4,
15376           indianred: 0xcd5c5c,
15377           indigo: 0x4b0082,
15378           ivory: 0xfffff0,
15379           khaki: 0xf0e68c,
15380           lavender: 0xe6e6fa,
15381           lavenderblush: 0xfff0f5,
15382           lawngreen: 0x7cfc00,
15383           lemonchiffon: 0xfffacd,
15384           lightblue: 0xadd8e6,
15385           lightcoral: 0xf08080,
15386           lightcyan: 0xe0ffff,
15387           lightgoldenrodyellow: 0xfafad2,
15388           lightgray: 0xd3d3d3,
15389           lightgreen: 0x90ee90,
15390           lightgrey: 0xd3d3d3,
15391           lightpink: 0xffb6c1,
15392           lightsalmon: 0xffa07a,
15393           lightseagreen: 0x20b2aa,
15394           lightskyblue: 0x87cefa,
15395           lightslategray: 0x778899,
15396           lightslategrey: 0x778899,
15397           lightsteelblue: 0xb0c4de,
15398           lightyellow: 0xffffe0,
15399           lime: 0x00ff00,
15400           limegreen: 0x32cd32,
15401           linen: 0xfaf0e6,
15402           magenta: 0xff00ff,
15403           maroon: 0x800000,
15404           mediumaquamarine: 0x66cdaa,
15405           mediumblue: 0x0000cd,
15406           mediumorchid: 0xba55d3,
15407           mediumpurple: 0x9370db,
15408           mediumseagreen: 0x3cb371,
15409           mediumslateblue: 0x7b68ee,
15410           mediumspringgreen: 0x00fa9a,
15411           mediumturquoise: 0x48d1cc,
15412           mediumvioletred: 0xc71585,
15413           midnightblue: 0x191970,
15414           mintcream: 0xf5fffa,
15415           mistyrose: 0xffe4e1,
15416           moccasin: 0xffe4b5,
15417           navajowhite: 0xffdead,
15418           navy: 0x000080,
15419           oldlace: 0xfdf5e6,
15420           olive: 0x808000,
15421           olivedrab: 0x6b8e23,
15422           orange: 0xffa500,
15423           orangered: 0xff4500,
15424           orchid: 0xda70d6,
15425           palegoldenrod: 0xeee8aa,
15426           palegreen: 0x98fb98,
15427           paleturquoise: 0xafeeee,
15428           palevioletred: 0xdb7093,
15429           papayawhip: 0xffefd5,
15430           peachpuff: 0xffdab9,
15431           peru: 0xcd853f,
15432           pink: 0xffc0cb,
15433           plum: 0xdda0dd,
15434           powderblue: 0xb0e0e6,
15435           purple: 0x800080,
15436           rebeccapurple: 0x663399,
15437           red: 0xff0000,
15438           rosybrown: 0xbc8f8f,
15439           royalblue: 0x4169e1,
15440           saddlebrown: 0x8b4513,
15441           salmon: 0xfa8072,
15442           sandybrown: 0xf4a460,
15443           seagreen: 0x2e8b57,
15444           seashell: 0xfff5ee,
15445           sienna: 0xa0522d,
15446           silver: 0xc0c0c0,
15447           skyblue: 0x87ceeb,
15448           slateblue: 0x6a5acd,
15449           slategray: 0x708090,
15450           slategrey: 0x708090,
15451           snow: 0xfffafa,
15452           springgreen: 0x00ff7f,
15453           steelblue: 0x4682b4,
15454           tan: 0xd2b48c,
15455           teal: 0x008080,
15456           thistle: 0xd8bfd8,
15457           tomato: 0xff6347,
15458           turquoise: 0x40e0d0,
15459           violet: 0xee82ee,
15460           wheat: 0xf5deb3,
15461           white: 0xffffff,
15462           whitesmoke: 0xf5f5f5,
15463           yellow: 0xffff00,
15464           yellowgreen: 0x9acd32
15465         };
15466         define(Color, color, {
15467           copy: function copy(channels) {
15468             return Object.assign(new this.constructor(), this, channels);
15469           },
15470           displayable: function displayable() {
15471             return this.rgb().displayable();
15472           },
15473           hex: color_formatHex,
15474           // Deprecated! Use color.formatHex.
15475           formatHex: color_formatHex,
15476           formatHsl: color_formatHsl,
15477           formatRgb: color_formatRgb,
15478           toString: color_formatRgb
15479         });
15480
15481         function color_formatHex() {
15482           return this.rgb().formatHex();
15483         }
15484
15485         function color_formatHsl() {
15486           return hslConvert(this).formatHsl();
15487         }
15488
15489         function color_formatRgb() {
15490           return this.rgb().formatRgb();
15491         }
15492
15493         function color(format) {
15494           var m, l;
15495           format = (format + "").trim().toLowerCase();
15496           return (m = reHex.exec(format)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) // #ff0000
15497           : l === 3 ? new Rgb(m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, (m & 0xf) << 4 | m & 0xf, 1) // #f00
15498           : l === 8 ? rgba(m >> 24 & 0xff, m >> 16 & 0xff, m >> 8 & 0xff, (m & 0xff) / 0xff) // #ff000000
15499           : l === 4 ? rgba(m >> 12 & 0xf | m >> 8 & 0xf0, m >> 8 & 0xf | m >> 4 & 0xf0, m >> 4 & 0xf | m & 0xf0, ((m & 0xf) << 4 | m & 0xf) / 0xff) // #f000
15500           : null // invalid hex
15501           ) : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
15502           : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
15503           : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
15504           : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
15505           : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
15506           : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
15507           : named.hasOwnProperty(format) ? rgbn(named[format]) // eslint-disable-line no-prototype-builtins
15508           : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0) : null;
15509         }
15510
15511         function rgbn(n) {
15512           return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
15513         }
15514
15515         function rgba(r, g, b, a) {
15516           if (a <= 0) r = g = b = NaN;
15517           return new Rgb(r, g, b, a);
15518         }
15519
15520         function rgbConvert(o) {
15521           if (!(o instanceof Color)) o = color(o);
15522           if (!o) return new Rgb();
15523           o = o.rgb();
15524           return new Rgb(o.r, o.g, o.b, o.opacity);
15525         }
15526         function rgb(r, g, b, opacity) {
15527           return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
15528         }
15529         function Rgb(r, g, b, opacity) {
15530           this.r = +r;
15531           this.g = +g;
15532           this.b = +b;
15533           this.opacity = +opacity;
15534         }
15535         define(Rgb, rgb, extend$3(Color, {
15536           brighter: function brighter(k) {
15537             k = k == null ? _brighter : Math.pow(_brighter, k);
15538             return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
15539           },
15540           darker: function darker(k) {
15541             k = k == null ? _darker : Math.pow(_darker, k);
15542             return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
15543           },
15544           rgb: function rgb() {
15545             return this;
15546           },
15547           displayable: function displayable() {
15548             return -0.5 <= this.r && this.r < 255.5 && -0.5 <= this.g && this.g < 255.5 && -0.5 <= this.b && this.b < 255.5 && 0 <= this.opacity && this.opacity <= 1;
15549           },
15550           hex: rgb_formatHex,
15551           // Deprecated! Use color.formatHex.
15552           formatHex: rgb_formatHex,
15553           formatRgb: rgb_formatRgb,
15554           toString: rgb_formatRgb
15555         }));
15556
15557         function rgb_formatHex() {
15558           return "#" + hex$1(this.r) + hex$1(this.g) + hex$1(this.b);
15559         }
15560
15561         function rgb_formatRgb() {
15562           var a = this.opacity;
15563           a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
15564           return (a === 1 ? "rgb(" : "rgba(") + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", " + Math.max(0, Math.min(255, Math.round(this.b) || 0)) + (a === 1 ? ")" : ", " + a + ")");
15565         }
15566
15567         function hex$1(value) {
15568           value = Math.max(0, Math.min(255, Math.round(value) || 0));
15569           return (value < 16 ? "0" : "") + value.toString(16);
15570         }
15571
15572         function hsla(h, s, l, a) {
15573           if (a <= 0) h = s = l = NaN;else if (l <= 0 || l >= 1) h = s = NaN;else if (s <= 0) h = NaN;
15574           return new Hsl(h, s, l, a);
15575         }
15576
15577         function hslConvert(o) {
15578           if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
15579           if (!(o instanceof Color)) o = color(o);
15580           if (!o) return new Hsl();
15581           if (o instanceof Hsl) return o;
15582           o = o.rgb();
15583           var r = o.r / 255,
15584               g = o.g / 255,
15585               b = o.b / 255,
15586               min = Math.min(r, g, b),
15587               max = Math.max(r, g, b),
15588               h = NaN,
15589               s = max - min,
15590               l = (max + min) / 2;
15591
15592           if (s) {
15593             if (r === max) h = (g - b) / s + (g < b) * 6;else if (g === max) h = (b - r) / s + 2;else h = (r - g) / s + 4;
15594             s /= l < 0.5 ? max + min : 2 - max - min;
15595             h *= 60;
15596           } else {
15597             s = l > 0 && l < 1 ? 0 : h;
15598           }
15599
15600           return new Hsl(h, s, l, o.opacity);
15601         }
15602         function hsl(h, s, l, opacity) {
15603           return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
15604         }
15605
15606         function Hsl(h, s, l, opacity) {
15607           this.h = +h;
15608           this.s = +s;
15609           this.l = +l;
15610           this.opacity = +opacity;
15611         }
15612
15613         define(Hsl, hsl, extend$3(Color, {
15614           brighter: function brighter(k) {
15615             k = k == null ? _brighter : Math.pow(_brighter, k);
15616             return new Hsl(this.h, this.s, this.l * k, this.opacity);
15617           },
15618           darker: function darker(k) {
15619             k = k == null ? _darker : Math.pow(_darker, k);
15620             return new Hsl(this.h, this.s, this.l * k, this.opacity);
15621           },
15622           rgb: function rgb() {
15623             var h = this.h % 360 + (this.h < 0) * 360,
15624                 s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
15625                 l = this.l,
15626                 m2 = l + (l < 0.5 ? l : 1 - l) * s,
15627                 m1 = 2 * l - m2;
15628             return new Rgb(hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2), hsl2rgb(h, m1, m2), hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2), this.opacity);
15629           },
15630           displayable: function displayable() {
15631             return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && 0 <= this.l && this.l <= 1 && 0 <= this.opacity && this.opacity <= 1;
15632           },
15633           formatHsl: function formatHsl() {
15634             var a = this.opacity;
15635             a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
15636             return (a === 1 ? "hsl(" : "hsla(") + (this.h || 0) + ", " + (this.s || 0) * 100 + "%, " + (this.l || 0) * 100 + "%" + (a === 1 ? ")" : ", " + a + ")");
15637           }
15638         }));
15639         /* From FvD 13.37, CSS Color Module Level 3 */
15640
15641         function hsl2rgb(h, m1, m2) {
15642           return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;
15643         }
15644
15645         var constant$1 = (function (x) {
15646           return function () {
15647             return x;
15648           };
15649         });
15650
15651         function linear$2(a, d) {
15652           return function (t) {
15653             return a + t * d;
15654           };
15655         }
15656
15657         function exponential(a, b, y) {
15658           return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function (t) {
15659             return Math.pow(a + t * b, y);
15660           };
15661         }
15662         function gamma(y) {
15663           return (y = +y) === 1 ? nogamma : function (a, b) {
15664             return b - a ? exponential(a, b, y) : constant$1(isNaN(a) ? b : a);
15665           };
15666         }
15667         function nogamma(a, b) {
15668           var d = b - a;
15669           return d ? linear$2(a, d) : constant$1(isNaN(a) ? b : a);
15670         }
15671
15672         var d3_interpolateRgb = (function rgbGamma(y) {
15673           var color = gamma(y);
15674
15675           function rgb$1(start, end) {
15676             var r = color((start = rgb(start)).r, (end = rgb(end)).r),
15677                 g = color(start.g, end.g),
15678                 b = color(start.b, end.b),
15679                 opacity = nogamma(start.opacity, end.opacity);
15680             return function (t) {
15681               start.r = r(t);
15682               start.g = g(t);
15683               start.b = b(t);
15684               start.opacity = opacity(t);
15685               return start + "";
15686             };
15687           }
15688
15689           rgb$1.gamma = rgbGamma;
15690           return rgb$1;
15691         })(1);
15692
15693         function numberArray (a, b) {
15694           if (!b) b = [];
15695           var n = a ? Math.min(b.length, a.length) : 0,
15696               c = b.slice(),
15697               i;
15698           return function (t) {
15699             for (i = 0; i < n; ++i) {
15700               c[i] = a[i] * (1 - t) + b[i] * t;
15701             }
15702
15703             return c;
15704           };
15705         }
15706         function isNumberArray(x) {
15707           return ArrayBuffer.isView(x) && !(x instanceof DataView);
15708         }
15709
15710         function genericArray(a, b) {
15711           var nb = b ? b.length : 0,
15712               na = a ? Math.min(nb, a.length) : 0,
15713               x = new Array(na),
15714               c = new Array(nb),
15715               i;
15716
15717           for (i = 0; i < na; ++i) {
15718             x[i] = interpolate$1(a[i], b[i]);
15719           }
15720
15721           for (; i < nb; ++i) {
15722             c[i] = b[i];
15723           }
15724
15725           return function (t) {
15726             for (i = 0; i < na; ++i) {
15727               c[i] = x[i](t);
15728             }
15729
15730             return c;
15731           };
15732         }
15733
15734         function date (a, b) {
15735           var d = new Date();
15736           return a = +a, b = +b, function (t) {
15737             return d.setTime(a * (1 - t) + b * t), d;
15738           };
15739         }
15740
15741         function d3_interpolateNumber (a, b) {
15742           return a = +a, b = +b, function (t) {
15743             return a * (1 - t) + b * t;
15744           };
15745         }
15746
15747         function object (a, b) {
15748           var i = {},
15749               c = {},
15750               k;
15751           if (a === null || _typeof(a) !== "object") a = {};
15752           if (b === null || _typeof(b) !== "object") b = {};
15753
15754           for (k in b) {
15755             if (k in a) {
15756               i[k] = interpolate$1(a[k], b[k]);
15757             } else {
15758               c[k] = b[k];
15759             }
15760           }
15761
15762           return function (t) {
15763             for (k in i) {
15764               c[k] = i[k](t);
15765             }
15766
15767             return c;
15768           };
15769         }
15770
15771         var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
15772             reB = new RegExp(reA.source, "g");
15773
15774         function zero(b) {
15775           return function () {
15776             return b;
15777           };
15778         }
15779
15780         function one(b) {
15781           return function (t) {
15782             return b(t) + "";
15783           };
15784         }
15785
15786         function interpolateString (a, b) {
15787           var bi = reA.lastIndex = reB.lastIndex = 0,
15788               // scan index for next number in b
15789           am,
15790               // current match in a
15791           bm,
15792               // current match in b
15793           bs,
15794               // string preceding current number in b, if any
15795           i = -1,
15796               // index in s
15797           s = [],
15798               // string constants and placeholders
15799           q = []; // number interpolators
15800           // Coerce inputs to strings.
15801
15802           a = a + "", b = b + ""; // Interpolate pairs of numbers in a & b.
15803
15804           while ((am = reA.exec(a)) && (bm = reB.exec(b))) {
15805             if ((bs = bm.index) > bi) {
15806               // a string precedes the next number in b
15807               bs = b.slice(bi, bs);
15808               if (s[i]) s[i] += bs; // coalesce with previous string
15809               else s[++i] = bs;
15810             }
15811
15812             if ((am = am[0]) === (bm = bm[0])) {
15813               // numbers in a & b match
15814               if (s[i]) s[i] += bm; // coalesce with previous string
15815               else s[++i] = bm;
15816             } else {
15817               // interpolate non-matching numbers
15818               s[++i] = null;
15819               q.push({
15820                 i: i,
15821                 x: d3_interpolateNumber(am, bm)
15822               });
15823             }
15824
15825             bi = reB.lastIndex;
15826           } // Add remains of b.
15827
15828
15829           if (bi < b.length) {
15830             bs = b.slice(bi);
15831             if (s[i]) s[i] += bs; // coalesce with previous string
15832             else s[++i] = bs;
15833           } // Special optimization for only a single match.
15834           // Otherwise, interpolate each of the numbers and rejoin the string.
15835
15836
15837           return s.length < 2 ? q[0] ? one(q[0].x) : zero(b) : (b = q.length, function (t) {
15838             for (var i = 0, o; i < b; ++i) {
15839               s[(o = q[i]).i] = o.x(t);
15840             }
15841
15842             return s.join("");
15843           });
15844         }
15845
15846         function interpolate$1 (a, b) {
15847           var t = _typeof(b),
15848               c;
15849
15850           return b == null || t === "boolean" ? constant$1(b) : (t === "number" ? d3_interpolateNumber : t === "string" ? (c = color(b)) ? (b = c, d3_interpolateRgb) : interpolateString : b instanceof color ? d3_interpolateRgb : b instanceof Date ? date : isNumberArray(b) ? numberArray : Array.isArray(b) ? genericArray : typeof b.valueOf !== "function" && typeof b.toString !== "function" || isNaN(b) ? object : d3_interpolateNumber)(a, b);
15851         }
15852
15853         function interpolateRound (a, b) {
15854           return a = +a, b = +b, function (t) {
15855             return Math.round(a * (1 - t) + b * t);
15856           };
15857         }
15858
15859         var degrees = 180 / Math.PI;
15860         var identity$3 = {
15861           translateX: 0,
15862           translateY: 0,
15863           rotate: 0,
15864           skewX: 0,
15865           scaleX: 1,
15866           scaleY: 1
15867         };
15868         function decompose (a, b, c, d, e, f) {
15869           var scaleX, scaleY, skewX;
15870           if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
15871           if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
15872           if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
15873           if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
15874           return {
15875             translateX: e,
15876             translateY: f,
15877             rotate: Math.atan2(b, a) * degrees,
15878             skewX: Math.atan(skewX) * degrees,
15879             scaleX: scaleX,
15880             scaleY: scaleY
15881           };
15882         }
15883
15884         var svgNode;
15885         /* eslint-disable no-undef */
15886
15887         function parseCss(value) {
15888           var m = new (typeof DOMMatrix === "function" ? DOMMatrix : WebKitCSSMatrix)(value + "");
15889           return m.isIdentity ? identity$3 : decompose(m.a, m.b, m.c, m.d, m.e, m.f);
15890         }
15891         function parseSvg(value) {
15892           if (value == null) return identity$3;
15893           if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
15894           svgNode.setAttribute("transform", value);
15895           if (!(value = svgNode.transform.baseVal.consolidate())) return identity$3;
15896           value = value.matrix;
15897           return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
15898         }
15899
15900         function interpolateTransform(parse, pxComma, pxParen, degParen) {
15901           function pop(s) {
15902             return s.length ? s.pop() + " " : "";
15903           }
15904
15905           function translate(xa, ya, xb, yb, s, q) {
15906             if (xa !== xb || ya !== yb) {
15907               var i = s.push("translate(", null, pxComma, null, pxParen);
15908               q.push({
15909                 i: i - 4,
15910                 x: d3_interpolateNumber(xa, xb)
15911               }, {
15912                 i: i - 2,
15913                 x: d3_interpolateNumber(ya, yb)
15914               });
15915             } else if (xb || yb) {
15916               s.push("translate(" + xb + pxComma + yb + pxParen);
15917             }
15918           }
15919
15920           function rotate(a, b, s, q) {
15921             if (a !== b) {
15922               if (a - b > 180) b += 360;else if (b - a > 180) a += 360; // shortest path
15923
15924               q.push({
15925                 i: s.push(pop(s) + "rotate(", null, degParen) - 2,
15926                 x: d3_interpolateNumber(a, b)
15927               });
15928             } else if (b) {
15929               s.push(pop(s) + "rotate(" + b + degParen);
15930             }
15931           }
15932
15933           function skewX(a, b, s, q) {
15934             if (a !== b) {
15935               q.push({
15936                 i: s.push(pop(s) + "skewX(", null, degParen) - 2,
15937                 x: d3_interpolateNumber(a, b)
15938               });
15939             } else if (b) {
15940               s.push(pop(s) + "skewX(" + b + degParen);
15941             }
15942           }
15943
15944           function scale(xa, ya, xb, yb, s, q) {
15945             if (xa !== xb || ya !== yb) {
15946               var i = s.push(pop(s) + "scale(", null, ",", null, ")");
15947               q.push({
15948                 i: i - 4,
15949                 x: d3_interpolateNumber(xa, xb)
15950               }, {
15951                 i: i - 2,
15952                 x: d3_interpolateNumber(ya, yb)
15953               });
15954             } else if (xb !== 1 || yb !== 1) {
15955               s.push(pop(s) + "scale(" + xb + "," + yb + ")");
15956             }
15957           }
15958
15959           return function (a, b) {
15960             var s = [],
15961                 // string constants and placeholders
15962             q = []; // number interpolators
15963
15964             a = parse(a), b = parse(b);
15965             translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
15966             rotate(a.rotate, b.rotate, s, q);
15967             skewX(a.skewX, b.skewX, s, q);
15968             scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
15969             a = b = null; // gc
15970
15971             return function (t) {
15972               var i = -1,
15973                   n = q.length,
15974                   o;
15975
15976               while (++i < n) {
15977                 s[(o = q[i]).i] = o.x(t);
15978               }
15979
15980               return s.join("");
15981             };
15982           };
15983         }
15984
15985         var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
15986         var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");
15987
15988         var epsilon2 = 1e-12;
15989
15990         function cosh(x) {
15991           return ((x = Math.exp(x)) + 1 / x) / 2;
15992         }
15993
15994         function sinh(x) {
15995           return ((x = Math.exp(x)) - 1 / x) / 2;
15996         }
15997
15998         function tanh(x) {
15999           return ((x = Math.exp(2 * x)) - 1) / (x + 1);
16000         }
16001
16002         var interpolateZoom = (function zoomRho(rho, rho2, rho4) {
16003           // p0 = [ux0, uy0, w0]
16004           // p1 = [ux1, uy1, w1]
16005           function zoom(p0, p1) {
16006             var ux0 = p0[0],
16007                 uy0 = p0[1],
16008                 w0 = p0[2],
16009                 ux1 = p1[0],
16010                 uy1 = p1[1],
16011                 w1 = p1[2],
16012                 dx = ux1 - ux0,
16013                 dy = uy1 - uy0,
16014                 d2 = dx * dx + dy * dy,
16015                 i,
16016                 S; // Special case for u0 ≅ u1.
16017
16018             if (d2 < epsilon2) {
16019               S = Math.log(w1 / w0) / rho;
16020
16021               i = function i(t) {
16022                 return [ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(rho * t * S)];
16023               };
16024             } // General case.
16025             else {
16026               var d1 = Math.sqrt(d2),
16027                   b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
16028                   b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
16029                   r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
16030                   r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
16031               S = (r1 - r0) / rho;
16032
16033               i = function i(t) {
16034                 var s = t * S,
16035                     coshr0 = cosh(r0),
16036                     u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
16037                 return [ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / cosh(rho * s + r0)];
16038               };
16039             }
16040
16041             i.duration = S * 1000 * rho / Math.SQRT2;
16042             return i;
16043           }
16044
16045           zoom.rho = function (_) {
16046             var _1 = Math.max(1e-3, +_),
16047                 _2 = _1 * _1,
16048                 _4 = _2 * _2;
16049
16050             return zoomRho(_1, _2, _4);
16051           };
16052
16053           return zoom;
16054         })(Math.SQRT2, 2, 4);
16055
16056         function d3_quantize (interpolator, n) {
16057           var samples = new Array(n);
16058
16059           for (var i = 0; i < n; ++i) {
16060             samples[i] = interpolator(i / (n - 1));
16061           }
16062
16063           return samples;
16064         }
16065
16066         var $$t = _export;
16067         var bind$4 = functionBind;
16068
16069         // `Function.prototype.bind` method
16070         // https://tc39.es/ecma262/#sec-function.prototype.bind
16071         $$t({ target: 'Function', proto: true, forced: Function.bind !== bind$4 }, {
16072           bind: bind$4
16073         });
16074
16075         var frame = 0,
16076             // is an animation frame pending?
16077         timeout = 0,
16078             // is a timeout pending?
16079         interval = 0,
16080             // are any timers active?
16081         pokeDelay = 1000,
16082             // how frequently we check for clock skew
16083         taskHead,
16084             taskTail,
16085             clockLast = 0,
16086             clockNow = 0,
16087             clockSkew = 0,
16088             clock = (typeof performance === "undefined" ? "undefined" : _typeof(performance)) === "object" && performance.now ? performance : Date,
16089             setFrame = (typeof window === "undefined" ? "undefined" : _typeof(window)) === "object" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function (f) {
16090           setTimeout(f, 17);
16091         };
16092         function now$1() {
16093           return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
16094         }
16095
16096         function clearNow() {
16097           clockNow = 0;
16098         }
16099
16100         function Timer() {
16101           this._call = this._time = this._next = null;
16102         }
16103         Timer.prototype = timer.prototype = {
16104           constructor: Timer,
16105           restart: function restart(callback, delay, time) {
16106             if (typeof callback !== "function") throw new TypeError("callback is not a function");
16107             time = (time == null ? now$1() : +time) + (delay == null ? 0 : +delay);
16108
16109             if (!this._next && taskTail !== this) {
16110               if (taskTail) taskTail._next = this;else taskHead = this;
16111               taskTail = this;
16112             }
16113
16114             this._call = callback;
16115             this._time = time;
16116             sleep();
16117           },
16118           stop: function stop() {
16119             if (this._call) {
16120               this._call = null;
16121               this._time = Infinity;
16122               sleep();
16123             }
16124           }
16125         };
16126         function timer(callback, delay, time) {
16127           var t = new Timer();
16128           t.restart(callback, delay, time);
16129           return t;
16130         }
16131         function timerFlush() {
16132           now$1(); // Get the current time, if not already set.
16133
16134           ++frame; // Pretend we’ve set an alarm, if we haven’t already.
16135
16136           var t = taskHead,
16137               e;
16138
16139           while (t) {
16140             if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
16141             t = t._next;
16142           }
16143
16144           --frame;
16145         }
16146
16147         function wake() {
16148           clockNow = (clockLast = clock.now()) + clockSkew;
16149           frame = timeout = 0;
16150
16151           try {
16152             timerFlush();
16153           } finally {
16154             frame = 0;
16155             nap();
16156             clockNow = 0;
16157           }
16158         }
16159
16160         function poke() {
16161           var now = clock.now(),
16162               delay = now - clockLast;
16163           if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
16164         }
16165
16166         function nap() {
16167           var t0,
16168               t1 = taskHead,
16169               t2,
16170               time = Infinity;
16171
16172           while (t1) {
16173             if (t1._call) {
16174               if (time > t1._time) time = t1._time;
16175               t0 = t1, t1 = t1._next;
16176             } else {
16177               t2 = t1._next, t1._next = null;
16178               t1 = t0 ? t0._next = t2 : taskHead = t2;
16179             }
16180           }
16181
16182           taskTail = t0;
16183           sleep(time);
16184         }
16185
16186         function sleep(time) {
16187           if (frame) return; // Soonest alarm already set, or will be.
16188
16189           if (timeout) timeout = clearTimeout(timeout);
16190           var delay = time - clockNow; // Strictly less than if we recomputed clockNow.
16191
16192           if (delay > 24) {
16193             if (time < Infinity) timeout = setTimeout(wake, time - clock.now() - clockSkew);
16194             if (interval) interval = clearInterval(interval);
16195           } else {
16196             if (!interval) clockLast = clock.now(), interval = setInterval(poke, pokeDelay);
16197             frame = 1, setFrame(wake);
16198           }
16199         }
16200
16201         function d3_timeout (callback, delay, time) {
16202           var t = new Timer();
16203           delay = delay == null ? 0 : +delay;
16204           t.restart(function (elapsed) {
16205             t.stop();
16206             callback(elapsed + delay);
16207           }, delay, time);
16208           return t;
16209         }
16210
16211         var emptyOn = dispatch$8("start", "end", "cancel", "interrupt");
16212         var emptyTween = [];
16213         var CREATED = 0;
16214         var SCHEDULED = 1;
16215         var STARTING = 2;
16216         var STARTED = 3;
16217         var RUNNING = 4;
16218         var ENDING = 5;
16219         var ENDED = 6;
16220         function schedule (node, name, id, index, group, timing) {
16221           var schedules = node.__transition;
16222           if (!schedules) node.__transition = {};else if (id in schedules) return;
16223           create$2(node, id, {
16224             name: name,
16225             index: index,
16226             // For context during callback.
16227             group: group,
16228             // For context during callback.
16229             on: emptyOn,
16230             tween: emptyTween,
16231             time: timing.time,
16232             delay: timing.delay,
16233             duration: timing.duration,
16234             ease: timing.ease,
16235             timer: null,
16236             state: CREATED
16237           });
16238         }
16239         function init(node, id) {
16240           var schedule = get$1(node, id);
16241           if (schedule.state > CREATED) throw new Error("too late; already scheduled");
16242           return schedule;
16243         }
16244         function set(node, id) {
16245           var schedule = get$1(node, id);
16246           if (schedule.state > STARTED) throw new Error("too late; already running");
16247           return schedule;
16248         }
16249         function get$1(node, id) {
16250           var schedule = node.__transition;
16251           if (!schedule || !(schedule = schedule[id])) throw new Error("transition not found");
16252           return schedule;
16253         }
16254
16255         function create$2(node, id, self) {
16256           var schedules = node.__transition,
16257               tween; // Initialize the self timer when the transition is created.
16258           // Note the actual delay is not known until the first callback!
16259
16260           schedules[id] = self;
16261           self.timer = timer(schedule, 0, self.time);
16262
16263           function schedule(elapsed) {
16264             self.state = SCHEDULED;
16265             self.timer.restart(start, self.delay, self.time); // If the elapsed delay is less than our first sleep, start immediately.
16266
16267             if (self.delay <= elapsed) start(elapsed - self.delay);
16268           }
16269
16270           function start(elapsed) {
16271             var i, j, n, o; // If the state is not SCHEDULED, then we previously errored on start.
16272
16273             if (self.state !== SCHEDULED) return stop();
16274
16275             for (i in schedules) {
16276               o = schedules[i];
16277               if (o.name !== self.name) continue; // While this element already has a starting transition during this frame,
16278               // defer starting an interrupting transition until that transition has a
16279               // chance to tick (and possibly end); see d3/d3-transition#54!
16280
16281               if (o.state === STARTED) return d3_timeout(start); // Interrupt the active transition, if any.
16282
16283               if (o.state === RUNNING) {
16284                 o.state = ENDED;
16285                 o.timer.stop();
16286                 o.on.call("interrupt", node, node.__data__, o.index, o.group);
16287                 delete schedules[i];
16288               } // Cancel any pre-empted transitions.
16289               else if (+i < id) {
16290                 o.state = ENDED;
16291                 o.timer.stop();
16292                 o.on.call("cancel", node, node.__data__, o.index, o.group);
16293                 delete schedules[i];
16294               }
16295             } // Defer the first tick to end of the current frame; see d3/d3#1576.
16296             // Note the transition may be canceled after start and before the first tick!
16297             // Note this must be scheduled before the start event; see d3/d3-transition#16!
16298             // Assuming this is successful, subsequent callbacks go straight to tick.
16299
16300
16301             d3_timeout(function () {
16302               if (self.state === STARTED) {
16303                 self.state = RUNNING;
16304                 self.timer.restart(tick, self.delay, self.time);
16305                 tick(elapsed);
16306               }
16307             }); // Dispatch the start event.
16308             // Note this must be done before the tween are initialized.
16309
16310             self.state = STARTING;
16311             self.on.call("start", node, node.__data__, self.index, self.group);
16312             if (self.state !== STARTING) return; // interrupted
16313
16314             self.state = STARTED; // Initialize the tween, deleting null tween.
16315
16316             tween = new Array(n = self.tween.length);
16317
16318             for (i = 0, j = -1; i < n; ++i) {
16319               if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
16320                 tween[++j] = o;
16321               }
16322             }
16323
16324             tween.length = j + 1;
16325           }
16326
16327           function tick(elapsed) {
16328             var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
16329                 i = -1,
16330                 n = tween.length;
16331
16332             while (++i < n) {
16333               tween[i].call(node, t);
16334             } // Dispatch the end event.
16335
16336
16337             if (self.state === ENDING) {
16338               self.on.call("end", node, node.__data__, self.index, self.group);
16339               stop();
16340             }
16341           }
16342
16343           function stop() {
16344             self.state = ENDED;
16345             self.timer.stop();
16346             delete schedules[id];
16347
16348             for (var i in schedules) {
16349               return;
16350             } // eslint-disable-line no-unused-vars
16351
16352
16353             delete node.__transition;
16354           }
16355         }
16356
16357         function interrupt (node, name) {
16358           var schedules = node.__transition,
16359               schedule,
16360               active,
16361               empty = true,
16362               i;
16363           if (!schedules) return;
16364           name = name == null ? null : name + "";
16365
16366           for (i in schedules) {
16367             if ((schedule = schedules[i]).name !== name) {
16368               empty = false;
16369               continue;
16370             }
16371
16372             active = schedule.state > STARTING && schedule.state < ENDING;
16373             schedule.state = ENDED;
16374             schedule.timer.stop();
16375             schedule.on.call(active ? "interrupt" : "cancel", node, node.__data__, schedule.index, schedule.group);
16376             delete schedules[i];
16377           }
16378
16379           if (empty) delete node.__transition;
16380         }
16381
16382         function selection_interrupt (name) {
16383           return this.each(function () {
16384             interrupt(this, name);
16385           });
16386         }
16387
16388         function tweenRemove(id, name) {
16389           var tween0, tween1;
16390           return function () {
16391             var schedule = set(this, id),
16392                 tween = schedule.tween; // If this node shared tween with the previous node,
16393             // just assign the updated shared tween and we’re done!
16394             // Otherwise, copy-on-write.
16395
16396             if (tween !== tween0) {
16397               tween1 = tween0 = tween;
16398
16399               for (var i = 0, n = tween1.length; i < n; ++i) {
16400                 if (tween1[i].name === name) {
16401                   tween1 = tween1.slice();
16402                   tween1.splice(i, 1);
16403                   break;
16404                 }
16405               }
16406             }
16407
16408             schedule.tween = tween1;
16409           };
16410         }
16411
16412         function tweenFunction(id, name, value) {
16413           var tween0, tween1;
16414           if (typeof value !== "function") throw new Error();
16415           return function () {
16416             var schedule = set(this, id),
16417                 tween = schedule.tween; // If this node shared tween with the previous node,
16418             // just assign the updated shared tween and we’re done!
16419             // Otherwise, copy-on-write.
16420
16421             if (tween !== tween0) {
16422               tween1 = (tween0 = tween).slice();
16423
16424               for (var t = {
16425                 name: name,
16426                 value: value
16427               }, i = 0, n = tween1.length; i < n; ++i) {
16428                 if (tween1[i].name === name) {
16429                   tween1[i] = t;
16430                   break;
16431                 }
16432               }
16433
16434               if (i === n) tween1.push(t);
16435             }
16436
16437             schedule.tween = tween1;
16438           };
16439         }
16440
16441         function transition_tween (name, value) {
16442           var id = this._id;
16443           name += "";
16444
16445           if (arguments.length < 2) {
16446             var tween = get$1(this.node(), id).tween;
16447
16448             for (var i = 0, n = tween.length, t; i < n; ++i) {
16449               if ((t = tween[i]).name === name) {
16450                 return t.value;
16451               }
16452             }
16453
16454             return null;
16455           }
16456
16457           return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value));
16458         }
16459         function tweenValue(transition, name, value) {
16460           var id = transition._id;
16461           transition.each(function () {
16462             var schedule = set(this, id);
16463             (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments);
16464           });
16465           return function (node) {
16466             return get$1(node, id).value[name];
16467           };
16468         }
16469
16470         function interpolate (a, b) {
16471           var c;
16472           return (typeof b === "number" ? d3_interpolateNumber : b instanceof color ? d3_interpolateRgb : (c = color(b)) ? (b = c, d3_interpolateRgb) : interpolateString)(a, b);
16473         }
16474
16475         function attrRemove(name) {
16476           return function () {
16477             this.removeAttribute(name);
16478           };
16479         }
16480
16481         function attrRemoveNS(fullname) {
16482           return function () {
16483             this.removeAttributeNS(fullname.space, fullname.local);
16484           };
16485         }
16486
16487         function attrConstant(name, interpolate, value1) {
16488           var string00,
16489               string1 = value1 + "",
16490               interpolate0;
16491           return function () {
16492             var string0 = this.getAttribute(name);
16493             return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
16494           };
16495         }
16496
16497         function attrConstantNS(fullname, interpolate, value1) {
16498           var string00,
16499               string1 = value1 + "",
16500               interpolate0;
16501           return function () {
16502             var string0 = this.getAttributeNS(fullname.space, fullname.local);
16503             return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
16504           };
16505         }
16506
16507         function attrFunction(name, interpolate, value) {
16508           var string00, string10, interpolate0;
16509           return function () {
16510             var string0,
16511                 value1 = value(this),
16512                 string1;
16513             if (value1 == null) return void this.removeAttribute(name);
16514             string0 = this.getAttribute(name);
16515             string1 = value1 + "";
16516             return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
16517           };
16518         }
16519
16520         function attrFunctionNS(fullname, interpolate, value) {
16521           var string00, string10, interpolate0;
16522           return function () {
16523             var string0,
16524                 value1 = value(this),
16525                 string1;
16526             if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
16527             string0 = this.getAttributeNS(fullname.space, fullname.local);
16528             string1 = value1 + "";
16529             return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
16530           };
16531         }
16532
16533         function transition_attr (name, value) {
16534           var fullname = namespace(name),
16535               i = fullname === "transform" ? interpolateTransformSvg : interpolate;
16536           return this.attrTween(name, typeof value === "function" ? (fullname.local ? attrFunctionNS : attrFunction)(fullname, i, tweenValue(this, "attr." + name, value)) : value == null ? (fullname.local ? attrRemoveNS : attrRemove)(fullname) : (fullname.local ? attrConstantNS : attrConstant)(fullname, i, value));
16537         }
16538
16539         function attrInterpolate(name, i) {
16540           return function (t) {
16541             this.setAttribute(name, i.call(this, t));
16542           };
16543         }
16544
16545         function attrInterpolateNS(fullname, i) {
16546           return function (t) {
16547             this.setAttributeNS(fullname.space, fullname.local, i.call(this, t));
16548           };
16549         }
16550
16551         function attrTweenNS(fullname, value) {
16552           var t0, i0;
16553
16554           function tween() {
16555             var i = value.apply(this, arguments);
16556             if (i !== i0) t0 = (i0 = i) && attrInterpolateNS(fullname, i);
16557             return t0;
16558           }
16559
16560           tween._value = value;
16561           return tween;
16562         }
16563
16564         function attrTween(name, value) {
16565           var t0, i0;
16566
16567           function tween() {
16568             var i = value.apply(this, arguments);
16569             if (i !== i0) t0 = (i0 = i) && attrInterpolate(name, i);
16570             return t0;
16571           }
16572
16573           tween._value = value;
16574           return tween;
16575         }
16576
16577         function transition_attrTween (name, value) {
16578           var key = "attr." + name;
16579           if (arguments.length < 2) return (key = this.tween(key)) && key._value;
16580           if (value == null) return this.tween(key, null);
16581           if (typeof value !== "function") throw new Error();
16582           var fullname = namespace(name);
16583           return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));
16584         }
16585
16586         function delayFunction(id, value) {
16587           return function () {
16588             init(this, id).delay = +value.apply(this, arguments);
16589           };
16590         }
16591
16592         function delayConstant(id, value) {
16593           return value = +value, function () {
16594             init(this, id).delay = value;
16595           };
16596         }
16597
16598         function transition_delay (value) {
16599           var id = this._id;
16600           return arguments.length ? this.each((typeof value === "function" ? delayFunction : delayConstant)(id, value)) : get$1(this.node(), id).delay;
16601         }
16602
16603         function durationFunction(id, value) {
16604           return function () {
16605             set(this, id).duration = +value.apply(this, arguments);
16606           };
16607         }
16608
16609         function durationConstant(id, value) {
16610           return value = +value, function () {
16611             set(this, id).duration = value;
16612           };
16613         }
16614
16615         function transition_duration (value) {
16616           var id = this._id;
16617           return arguments.length ? this.each((typeof value === "function" ? durationFunction : durationConstant)(id, value)) : get$1(this.node(), id).duration;
16618         }
16619
16620         function easeConstant(id, value) {
16621           if (typeof value !== "function") throw new Error();
16622           return function () {
16623             set(this, id).ease = value;
16624           };
16625         }
16626
16627         function transition_ease (value) {
16628           var id = this._id;
16629           return arguments.length ? this.each(easeConstant(id, value)) : get$1(this.node(), id).ease;
16630         }
16631
16632         function easeVarying(id, value) {
16633           return function () {
16634             var v = value.apply(this, arguments);
16635             if (typeof v !== "function") throw new Error();
16636             set(this, id).ease = v;
16637           };
16638         }
16639
16640         function transition_easeVarying (value) {
16641           if (typeof value !== "function") throw new Error();
16642           return this.each(easeVarying(this._id, value));
16643         }
16644
16645         function transition_filter (match) {
16646           if (typeof match !== "function") match = matcher(match);
16647
16648           for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
16649             for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
16650               if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
16651                 subgroup.push(node);
16652               }
16653             }
16654           }
16655
16656           return new Transition(subgroups, this._parents, this._name, this._id);
16657         }
16658
16659         function transition_merge (transition) {
16660           if (transition._id !== this._id) throw new Error();
16661
16662           for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
16663             for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
16664               if (node = group0[i] || group1[i]) {
16665                 merge[i] = node;
16666               }
16667             }
16668           }
16669
16670           for (; j < m0; ++j) {
16671             merges[j] = groups0[j];
16672           }
16673
16674           return new Transition(merges, this._parents, this._name, this._id);
16675         }
16676
16677         function start(name) {
16678           return (name + "").trim().split(/^|\s+/).every(function (t) {
16679             var i = t.indexOf(".");
16680             if (i >= 0) t = t.slice(0, i);
16681             return !t || t === "start";
16682           });
16683         }
16684
16685         function onFunction(id, name, listener) {
16686           var on0,
16687               on1,
16688               sit = start(name) ? init : set;
16689           return function () {
16690             var schedule = sit(this, id),
16691                 on = schedule.on; // If this node shared a dispatch with the previous node,
16692             // just assign the updated shared dispatch and we’re done!
16693             // Otherwise, copy-on-write.
16694
16695             if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener);
16696             schedule.on = on1;
16697           };
16698         }
16699
16700         function transition_on (name, listener) {
16701           var id = this._id;
16702           return arguments.length < 2 ? get$1(this.node(), id).on.on(name) : this.each(onFunction(id, name, listener));
16703         }
16704
16705         function removeFunction(id) {
16706           return function () {
16707             var parent = this.parentNode;
16708
16709             for (var i in this.__transition) {
16710               if (+i !== id) return;
16711             }
16712
16713             if (parent) parent.removeChild(this);
16714           };
16715         }
16716
16717         function transition_remove () {
16718           return this.on("end.remove", removeFunction(this._id));
16719         }
16720
16721         function transition_select (select) {
16722           var name = this._name,
16723               id = this._id;
16724           if (typeof select !== "function") select = selector(select);
16725
16726           for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
16727             for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
16728               if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
16729                 if ("__data__" in node) subnode.__data__ = node.__data__;
16730                 subgroup[i] = subnode;
16731                 schedule(subgroup[i], name, id, i, subgroup, get$1(node, id));
16732               }
16733             }
16734           }
16735
16736           return new Transition(subgroups, this._parents, name, id);
16737         }
16738
16739         function transition_selectAll (select) {
16740           var name = this._name,
16741               id = this._id;
16742           if (typeof select !== "function") select = selectorAll(select);
16743
16744           for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
16745             for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
16746               if (node = group[i]) {
16747                 for (var children = select.call(node, node.__data__, i, group), child, inherit = get$1(node, id), k = 0, l = children.length; k < l; ++k) {
16748                   if (child = children[k]) {
16749                     schedule(child, name, id, k, children, inherit);
16750                   }
16751                 }
16752
16753                 subgroups.push(children);
16754                 parents.push(node);
16755               }
16756             }
16757           }
16758
16759           return new Transition(subgroups, parents, name, id);
16760         }
16761
16762         var Selection = selection.prototype.constructor;
16763         function transition_selection () {
16764           return new Selection(this._groups, this._parents);
16765         }
16766
16767         function styleNull(name, interpolate) {
16768           var string00, string10, interpolate0;
16769           return function () {
16770             var string0 = styleValue(this, name),
16771                 string1 = (this.style.removeProperty(name), styleValue(this, name));
16772             return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : interpolate0 = interpolate(string00 = string0, string10 = string1);
16773           };
16774         }
16775
16776         function styleRemove(name) {
16777           return function () {
16778             this.style.removeProperty(name);
16779           };
16780         }
16781
16782         function styleConstant(name, interpolate, value1) {
16783           var string00,
16784               string1 = value1 + "",
16785               interpolate0;
16786           return function () {
16787             var string0 = styleValue(this, name);
16788             return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);
16789           };
16790         }
16791
16792         function styleFunction(name, interpolate, value) {
16793           var string00, string10, interpolate0;
16794           return function () {
16795             var string0 = styleValue(this, name),
16796                 value1 = value(this),
16797                 string1 = value1 + "";
16798             if (value1 == null) string1 = value1 = (this.style.removeProperty(name), styleValue(this, name));
16799             return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));
16800           };
16801         }
16802
16803         function styleMaybeRemove(id, name) {
16804           var on0,
16805               on1,
16806               listener0,
16807               key = "style." + name,
16808               event = "end." + key,
16809               remove;
16810           return function () {
16811             var schedule = set(this, id),
16812                 on = schedule.on,
16813                 listener = schedule.value[key] == null ? remove || (remove = styleRemove(name)) : undefined; // If this node shared a dispatch with the previous node,
16814             // just assign the updated shared dispatch and we’re done!
16815             // Otherwise, copy-on-write.
16816
16817             if (on !== on0 || listener0 !== listener) (on1 = (on0 = on).copy()).on(event, listener0 = listener);
16818             schedule.on = on1;
16819           };
16820         }
16821
16822         function transition_style (name, value, priority) {
16823           var i = (name += "") === "transform" ? interpolateTransformCss : interpolate;
16824           return value == null ? this.styleTween(name, styleNull(name, i)).on("end.style." + name, styleRemove(name)) : typeof value === "function" ? this.styleTween(name, styleFunction(name, i, tweenValue(this, "style." + name, value))).each(styleMaybeRemove(this._id, name)) : this.styleTween(name, styleConstant(name, i, value), priority).on("end.style." + name, null);
16825         }
16826
16827         function styleInterpolate(name, i, priority) {
16828           return function (t) {
16829             this.style.setProperty(name, i.call(this, t), priority);
16830           };
16831         }
16832
16833         function styleTween(name, value, priority) {
16834           var t, i0;
16835
16836           function tween() {
16837             var i = value.apply(this, arguments);
16838             if (i !== i0) t = (i0 = i) && styleInterpolate(name, i, priority);
16839             return t;
16840           }
16841
16842           tween._value = value;
16843           return tween;
16844         }
16845
16846         function transition_styleTween (name, value, priority) {
16847           var key = "style." + (name += "");
16848           if (arguments.length < 2) return (key = this.tween(key)) && key._value;
16849           if (value == null) return this.tween(key, null);
16850           if (typeof value !== "function") throw new Error();
16851           return this.tween(key, styleTween(name, value, priority == null ? "" : priority));
16852         }
16853
16854         function textConstant(value) {
16855           return function () {
16856             this.textContent = value;
16857           };
16858         }
16859
16860         function textFunction(value) {
16861           return function () {
16862             var value1 = value(this);
16863             this.textContent = value1 == null ? "" : value1;
16864           };
16865         }
16866
16867         function transition_text (value) {
16868           return this.tween("text", typeof value === "function" ? textFunction(tweenValue(this, "text", value)) : textConstant(value == null ? "" : value + ""));
16869         }
16870
16871         function textInterpolate(i) {
16872           return function (t) {
16873             this.textContent = i.call(this, t);
16874           };
16875         }
16876
16877         function textTween(value) {
16878           var t0, i0;
16879
16880           function tween() {
16881             var i = value.apply(this, arguments);
16882             if (i !== i0) t0 = (i0 = i) && textInterpolate(i);
16883             return t0;
16884           }
16885
16886           tween._value = value;
16887           return tween;
16888         }
16889
16890         function transition_textTween (value) {
16891           var key = "text";
16892           if (arguments.length < 1) return (key = this.tween(key)) && key._value;
16893           if (value == null) return this.tween(key, null);
16894           if (typeof value !== "function") throw new Error();
16895           return this.tween(key, textTween(value));
16896         }
16897
16898         function transition_transition () {
16899           var name = this._name,
16900               id0 = this._id,
16901               id1 = newId();
16902
16903           for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
16904             for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
16905               if (node = group[i]) {
16906                 var inherit = get$1(node, id0);
16907                 schedule(node, name, id1, i, group, {
16908                   time: inherit.time + inherit.delay + inherit.duration,
16909                   delay: 0,
16910                   duration: inherit.duration,
16911                   ease: inherit.ease
16912                 });
16913               }
16914             }
16915           }
16916
16917           return new Transition(groups, this._parents, name, id1);
16918         }
16919
16920         function transition_end () {
16921           var on0,
16922               on1,
16923               that = this,
16924               id = that._id,
16925               size = that.size();
16926           return new Promise(function (resolve, reject) {
16927             var cancel = {
16928               value: reject
16929             },
16930                 end = {
16931               value: function value() {
16932                 if (--size === 0) resolve();
16933               }
16934             };
16935             that.each(function () {
16936               var schedule = set(this, id),
16937                   on = schedule.on; // If this node shared a dispatch with the previous node,
16938               // just assign the updated shared dispatch and we’re done!
16939               // Otherwise, copy-on-write.
16940
16941               if (on !== on0) {
16942                 on1 = (on0 = on).copy();
16943
16944                 on1._.cancel.push(cancel);
16945
16946                 on1._.interrupt.push(cancel);
16947
16948                 on1._.end.push(end);
16949               }
16950
16951               schedule.on = on1;
16952             }); // The selection was empty, resolve end immediately
16953
16954             if (size === 0) resolve();
16955           });
16956         }
16957
16958         var id = 0;
16959         function Transition(groups, parents, name, id) {
16960           this._groups = groups;
16961           this._parents = parents;
16962           this._name = name;
16963           this._id = id;
16964         }
16965         function newId() {
16966           return ++id;
16967         }
16968         var selection_prototype = selection.prototype;
16969         Transition.prototype = _defineProperty({
16970           constructor: Transition,
16971           select: transition_select,
16972           selectAll: transition_selectAll,
16973           filter: transition_filter,
16974           merge: transition_merge,
16975           selection: transition_selection,
16976           transition: transition_transition,
16977           call: selection_prototype.call,
16978           nodes: selection_prototype.nodes,
16979           node: selection_prototype.node,
16980           size: selection_prototype.size,
16981           empty: selection_prototype.empty,
16982           each: selection_prototype.each,
16983           on: transition_on,
16984           attr: transition_attr,
16985           attrTween: transition_attrTween,
16986           style: transition_style,
16987           styleTween: transition_styleTween,
16988           text: transition_text,
16989           textTween: transition_textTween,
16990           remove: transition_remove,
16991           tween: transition_tween,
16992           delay: transition_delay,
16993           duration: transition_duration,
16994           ease: transition_ease,
16995           easeVarying: transition_easeVarying,
16996           end: transition_end
16997         }, Symbol.iterator, selection_prototype[Symbol.iterator]);
16998
16999         var linear$1 = function linear(t) {
17000           return +t;
17001         };
17002
17003         function cubicInOut(t) {
17004           return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
17005         }
17006
17007         var defaultTiming = {
17008           time: null,
17009           // Set on use.
17010           delay: 0,
17011           duration: 250,
17012           ease: cubicInOut
17013         };
17014
17015         function inherit(node, id) {
17016           var timing;
17017
17018           while (!(timing = node.__transition) || !(timing = timing[id])) {
17019             if (!(node = node.parentNode)) {
17020               throw new Error("transition ".concat(id, " not found"));
17021             }
17022           }
17023
17024           return timing;
17025         }
17026
17027         function selection_transition (name) {
17028           var id, timing;
17029
17030           if (name instanceof Transition) {
17031             id = name._id, name = name._name;
17032           } else {
17033             id = newId(), (timing = defaultTiming).time = now$1(), name = name == null ? null : name + "";
17034           }
17035
17036           for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
17037             for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
17038               if (node = group[i]) {
17039                 schedule(node, name, id, i, group, timing || inherit(node, id));
17040               }
17041             }
17042           }
17043
17044           return new Transition(groups, this._parents, name, id);
17045         }
17046
17047         selection.prototype.interrupt = selection_interrupt;
17048         selection.prototype.transition = selection_transition;
17049
17050         var constant = (function (x) {
17051           return function () {
17052             return x;
17053           };
17054         });
17055
17056         function ZoomEvent(type, _ref) {
17057           var sourceEvent = _ref.sourceEvent,
17058               target = _ref.target,
17059               transform = _ref.transform,
17060               dispatch = _ref.dispatch;
17061           Object.defineProperties(this, {
17062             type: {
17063               value: type,
17064               enumerable: true,
17065               configurable: true
17066             },
17067             sourceEvent: {
17068               value: sourceEvent,
17069               enumerable: true,
17070               configurable: true
17071             },
17072             target: {
17073               value: target,
17074               enumerable: true,
17075               configurable: true
17076             },
17077             transform: {
17078               value: transform,
17079               enumerable: true,
17080               configurable: true
17081             },
17082             _: {
17083               value: dispatch
17084             }
17085           });
17086         }
17087
17088         function Transform(k, x, y) {
17089           this.k = k;
17090           this.x = x;
17091           this.y = y;
17092         }
17093         Transform.prototype = {
17094           constructor: Transform,
17095           scale: function scale(k) {
17096             return k === 1 ? this : new Transform(this.k * k, this.x, this.y);
17097           },
17098           translate: function translate(x, y) {
17099             return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
17100           },
17101           apply: function apply(point) {
17102             return [point[0] * this.k + this.x, point[1] * this.k + this.y];
17103           },
17104           applyX: function applyX(x) {
17105             return x * this.k + this.x;
17106           },
17107           applyY: function applyY(y) {
17108             return y * this.k + this.y;
17109           },
17110           invert: function invert(location) {
17111             return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
17112           },
17113           invertX: function invertX(x) {
17114             return (x - this.x) / this.k;
17115           },
17116           invertY: function invertY(y) {
17117             return (y - this.y) / this.k;
17118           },
17119           rescaleX: function rescaleX(x) {
17120             return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x));
17121           },
17122           rescaleY: function rescaleY(y) {
17123             return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y));
17124           },
17125           toString: function toString() {
17126             return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
17127           }
17128         };
17129         var identity$2 = new Transform(1, 0, 0);
17130
17131         function nopropagation(event) {
17132           event.stopImmediatePropagation();
17133         }
17134         function noevent (event) {
17135           event.preventDefault();
17136           event.stopImmediatePropagation();
17137         }
17138
17139         // except for pinch-to-zoom, which is sent as a wheel+ctrlKey event
17140
17141         function defaultFilter$1(event) {
17142           return (!event.ctrlKey || event.type === 'wheel') && !event.button;
17143         }
17144
17145         function defaultExtent$1() {
17146           var e = this;
17147
17148           if (e instanceof SVGElement) {
17149             e = e.ownerSVGElement || e;
17150
17151             if (e.hasAttribute("viewBox")) {
17152               e = e.viewBox.baseVal;
17153               return [[e.x, e.y], [e.x + e.width, e.y + e.height]];
17154             }
17155
17156             return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]];
17157           }
17158
17159           return [[0, 0], [e.clientWidth, e.clientHeight]];
17160         }
17161
17162         function defaultTransform() {
17163           return this.__zoom || identity$2;
17164         }
17165
17166         function defaultWheelDelta$1(event) {
17167           return -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 0.002) * (event.ctrlKey ? 10 : 1);
17168         }
17169
17170         function defaultTouchable() {
17171           return navigator.maxTouchPoints || "ontouchstart" in this;
17172         }
17173
17174         function defaultConstrain$1(transform, extent, translateExtent) {
17175           var dx0 = transform.invertX(extent[0][0]) - translateExtent[0][0],
17176               dx1 = transform.invertX(extent[1][0]) - translateExtent[1][0],
17177               dy0 = transform.invertY(extent[0][1]) - translateExtent[0][1],
17178               dy1 = transform.invertY(extent[1][1]) - translateExtent[1][1];
17179           return transform.translate(dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1));
17180         }
17181
17182         function d3_zoom () {
17183           var filter = defaultFilter$1,
17184               extent = defaultExtent$1,
17185               constrain = defaultConstrain$1,
17186               wheelDelta = defaultWheelDelta$1,
17187               touchable = defaultTouchable,
17188               scaleExtent = [0, Infinity],
17189               translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]],
17190               duration = 250,
17191               interpolate = interpolateZoom,
17192               listeners = dispatch$8("start", "zoom", "end"),
17193               touchstarting,
17194               touchfirst,
17195               touchending,
17196               touchDelay = 500,
17197               wheelDelay = 150,
17198               clickDistance2 = 0,
17199               tapDistance = 10;
17200
17201           function zoom(selection) {
17202             selection.property("__zoom", defaultTransform).on("wheel.zoom", wheeled).on("mousedown.zoom", mousedowned).on("dblclick.zoom", dblclicked).filter(touchable).on("touchstart.zoom", touchstarted).on("touchmove.zoom", touchmoved).on("touchend.zoom touchcancel.zoom", touchended).style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
17203           }
17204
17205           zoom.transform = function (collection, transform, point, event) {
17206             var selection = collection.selection ? collection.selection() : collection;
17207             selection.property("__zoom", defaultTransform);
17208
17209             if (collection !== selection) {
17210               schedule(collection, transform, point, event);
17211             } else {
17212               selection.interrupt().each(function () {
17213                 gesture(this, arguments).event(event).start().zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform).end();
17214               });
17215             }
17216           };
17217
17218           zoom.scaleBy = function (selection, k, p, event) {
17219             zoom.scaleTo(selection, function () {
17220               var k0 = this.__zoom.k,
17221                   k1 = typeof k === "function" ? k.apply(this, arguments) : k;
17222               return k0 * k1;
17223             }, p, event);
17224           };
17225
17226           zoom.scaleTo = function (selection, k, p, event) {
17227             zoom.transform(selection, function () {
17228               var e = extent.apply(this, arguments),
17229                   t0 = this.__zoom,
17230                   p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p,
17231                   p1 = t0.invert(p0),
17232                   k1 = typeof k === "function" ? k.apply(this, arguments) : k;
17233               return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent);
17234             }, p, event);
17235           };
17236
17237           zoom.translateBy = function (selection, x, y, event) {
17238             zoom.transform(selection, function () {
17239               return constrain(this.__zoom.translate(typeof x === "function" ? x.apply(this, arguments) : x, typeof y === "function" ? y.apply(this, arguments) : y), extent.apply(this, arguments), translateExtent);
17240             }, null, event);
17241           };
17242
17243           zoom.translateTo = function (selection, x, y, p, event) {
17244             zoom.transform(selection, function () {
17245               var e = extent.apply(this, arguments),
17246                   t = this.__zoom,
17247                   p0 = p == null ? centroid(e) : typeof p === "function" ? p.apply(this, arguments) : p;
17248               return constrain(identity$2.translate(p0[0], p0[1]).scale(t.k).translate(typeof x === "function" ? -x.apply(this, arguments) : -x, typeof y === "function" ? -y.apply(this, arguments) : -y), e, translateExtent);
17249             }, p, event);
17250           };
17251
17252           function scale(transform, k) {
17253             k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k));
17254             return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
17255           }
17256
17257           function translate(transform, p0, p1) {
17258             var x = p0[0] - p1[0] * transform.k,
17259                 y = p0[1] - p1[1] * transform.k;
17260             return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
17261           }
17262
17263           function centroid(extent) {
17264             return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
17265           }
17266
17267           function schedule(transition, transform, point, event) {
17268             transition.on("start.zoom", function () {
17269               gesture(this, arguments).event(event).start();
17270             }).on("interrupt.zoom end.zoom", function () {
17271               gesture(this, arguments).event(event).end();
17272             }).tween("zoom", function () {
17273               var that = this,
17274                   args = arguments,
17275                   g = gesture(that, args).event(event),
17276                   e = extent.apply(that, args),
17277                   p = point == null ? centroid(e) : typeof point === "function" ? point.apply(that, args) : point,
17278                   w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
17279                   a = that.__zoom,
17280                   b = typeof transform === "function" ? transform.apply(that, args) : transform,
17281                   i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
17282               return function (t) {
17283                 if (t === 1) t = b; // Avoid rounding error on end.
17284                 else {
17285                   var l = i(t),
17286                       k = w / l[2];
17287                   t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k);
17288                 }
17289                 g.zoom(null, t);
17290               };
17291             });
17292           }
17293
17294           function gesture(that, args, clean) {
17295             return !clean && that.__zooming || new Gesture(that, args);
17296           }
17297
17298           function Gesture(that, args) {
17299             this.that = that;
17300             this.args = args;
17301             this.active = 0;
17302             this.sourceEvent = null;
17303             this.extent = extent.apply(that, args);
17304             this.taps = 0;
17305           }
17306
17307           Gesture.prototype = {
17308             event: function event(_event) {
17309               if (_event) this.sourceEvent = _event;
17310               return this;
17311             },
17312             start: function start() {
17313               if (++this.active === 1) {
17314                 this.that.__zooming = this;
17315                 this.emit("start");
17316               }
17317
17318               return this;
17319             },
17320             zoom: function zoom(key, transform) {
17321               if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]);
17322               if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]);
17323               if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]);
17324               this.that.__zoom = transform;
17325               this.emit("zoom");
17326               return this;
17327             },
17328             end: function end() {
17329               if (--this.active === 0) {
17330                 delete this.that.__zooming;
17331                 this.emit("end");
17332               }
17333
17334               return this;
17335             },
17336             emit: function emit(type) {
17337               var d = select(this.that).datum();
17338               listeners.call(type, this.that, new ZoomEvent(type, {
17339                 sourceEvent: this.sourceEvent,
17340                 target: zoom,
17341                 type: type,
17342                 transform: this.that.__zoom,
17343                 dispatch: listeners
17344               }), d);
17345             }
17346           };
17347
17348           function wheeled(event) {
17349             for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
17350               args[_key - 1] = arguments[_key];
17351             }
17352
17353             if (!filter.apply(this, arguments)) return;
17354             var g = gesture(this, args).event(event),
17355                 t = this.__zoom,
17356                 k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))),
17357                 p = pointer(event); // If the mouse is in the same location as before, reuse it.
17358             // If there were recent wheel events, reset the wheel idle timeout.
17359
17360             if (g.wheel) {
17361               if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
17362                 g.mouse[1] = t.invert(g.mouse[0] = p);
17363               }
17364
17365               clearTimeout(g.wheel);
17366             } // If this wheel event won’t trigger a transform change, ignore it.
17367             else if (t.k === k) return; // Otherwise, capture the mouse point and location at the start.
17368             else {
17369               g.mouse = [p, t.invert(p)];
17370               interrupt(this);
17371               g.start();
17372             }
17373
17374             noevent(event);
17375             g.wheel = setTimeout(wheelidled, wheelDelay);
17376             g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent));
17377
17378             function wheelidled() {
17379               g.wheel = null;
17380               g.end();
17381             }
17382           }
17383
17384           function mousedowned(event) {
17385             for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
17386               args[_key2 - 1] = arguments[_key2];
17387             }
17388
17389             if (touchending || !filter.apply(this, arguments)) return;
17390             var g = gesture(this, args, true).event(event),
17391                 v = select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
17392                 p = pointer(event, currentTarget),
17393                 currentTarget = event.currentTarget,
17394                 x0 = event.clientX,
17395                 y0 = event.clientY;
17396             dragDisable(event.view);
17397             nopropagation(event);
17398             g.mouse = [p, this.__zoom.invert(p)];
17399             interrupt(this);
17400             g.start();
17401
17402             function mousemoved(event) {
17403               noevent(event);
17404
17405               if (!g.moved) {
17406                 var dx = event.clientX - x0,
17407                     dy = event.clientY - y0;
17408                 g.moved = dx * dx + dy * dy > clickDistance2;
17409               }
17410
17411               g.event(event).zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = pointer(event, currentTarget), g.mouse[1]), g.extent, translateExtent));
17412             }
17413
17414             function mouseupped(event) {
17415               v.on("mousemove.zoom mouseup.zoom", null);
17416               yesdrag(event.view, g.moved);
17417               noevent(event);
17418               g.event(event).end();
17419             }
17420           }
17421
17422           function dblclicked(event) {
17423             for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
17424               args[_key3 - 1] = arguments[_key3];
17425             }
17426
17427             if (!filter.apply(this, arguments)) return;
17428             var t0 = this.__zoom,
17429                 p0 = pointer(event.changedTouches ? event.changedTouches[0] : event, this),
17430                 p1 = t0.invert(p0),
17431                 k1 = t0.k * (event.shiftKey ? 0.5 : 2),
17432                 t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, args), translateExtent);
17433             noevent(event);
17434             if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0, event);else select(this).call(zoom.transform, t1, p0, event);
17435           }
17436
17437           function touchstarted(event) {
17438             for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
17439               args[_key4 - 1] = arguments[_key4];
17440             }
17441
17442             if (!filter.apply(this, arguments)) return;
17443             var touches = event.touches,
17444                 n = touches.length,
17445                 g = gesture(this, args, event.changedTouches.length === n).event(event),
17446                 started,
17447                 i,
17448                 t,
17449                 p;
17450             nopropagation(event);
17451
17452             for (i = 0; i < n; ++i) {
17453               t = touches[i], p = pointer(t, this);
17454               p = [p, this.__zoom.invert(p), t.identifier];
17455               if (!g.touch0) g.touch0 = p, started = true, g.taps = 1 + !!touchstarting;else if (!g.touch1 && g.touch0[2] !== p[2]) g.touch1 = p, g.taps = 0;
17456             }
17457
17458             if (touchstarting) touchstarting = clearTimeout(touchstarting);
17459
17460             if (started) {
17461               if (g.taps < 2) touchfirst = p[0], touchstarting = setTimeout(function () {
17462                 touchstarting = null;
17463               }, touchDelay);
17464               interrupt(this);
17465               g.start();
17466             }
17467           }
17468
17469           function touchmoved(event) {
17470             if (!this.__zooming) return;
17471
17472             for (var _len5 = arguments.length, args = new Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {
17473               args[_key5 - 1] = arguments[_key5];
17474             }
17475
17476             var g = gesture(this, args).event(event),
17477                 touches = event.changedTouches,
17478                 n = touches.length,
17479                 i,
17480                 t,
17481                 p,
17482                 l;
17483             noevent(event);
17484
17485             for (i = 0; i < n; ++i) {
17486               t = touches[i], p = pointer(t, this);
17487               if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;
17488             }
17489
17490             t = g.that.__zoom;
17491
17492             if (g.touch1) {
17493               var p0 = g.touch0[0],
17494                   l0 = g.touch0[1],
17495                   p1 = g.touch1[0],
17496                   l1 = g.touch1[1],
17497                   dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
17498                   dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
17499               t = scale(t, Math.sqrt(dp / dl));
17500               p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
17501               l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
17502             } else if (g.touch0) p = g.touch0[0], l = g.touch0[1];else return;
17503
17504             g.zoom("touch", constrain(translate(t, p, l), g.extent, translateExtent));
17505           }
17506
17507           function touchended(event) {
17508             for (var _len6 = arguments.length, args = new Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {
17509               args[_key6 - 1] = arguments[_key6];
17510             }
17511
17512             if (!this.__zooming) return;
17513             var g = gesture(this, args).event(event),
17514                 touches = event.changedTouches,
17515                 n = touches.length,
17516                 i,
17517                 t;
17518             nopropagation(event);
17519             if (touchending) clearTimeout(touchending);
17520             touchending = setTimeout(function () {
17521               touchending = null;
17522             }, touchDelay);
17523
17524             for (i = 0; i < n; ++i) {
17525               t = touches[i];
17526               if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
17527             }
17528
17529             if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
17530             if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]);else {
17531               g.end(); // If this was a dbltap, reroute to the (optional) dblclick.zoom handler.
17532
17533               if (g.taps === 2) {
17534                 t = pointer(t, this);
17535
17536                 if (Math.hypot(touchfirst[0] - t[0], touchfirst[1] - t[1]) < tapDistance) {
17537                   var p = select(this).on("dblclick.zoom");
17538                   if (p) p.apply(this, arguments);
17539                 }
17540               }
17541             }
17542           }
17543
17544           zoom.wheelDelta = function (_) {
17545             return arguments.length ? (wheelDelta = typeof _ === "function" ? _ : constant(+_), zoom) : wheelDelta;
17546           };
17547
17548           zoom.filter = function (_) {
17549             return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), zoom) : filter;
17550           };
17551
17552           zoom.touchable = function (_) {
17553             return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), zoom) : touchable;
17554           };
17555
17556           zoom.extent = function (_) {
17557             return arguments.length ? (extent = typeof _ === "function" ? _ : constant([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
17558           };
17559
17560           zoom.scaleExtent = function (_) {
17561             return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]];
17562           };
17563
17564           zoom.translateExtent = function (_) {
17565             return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]];
17566           };
17567
17568           zoom.constrain = function (_) {
17569             return arguments.length ? (constrain = _, zoom) : constrain;
17570           };
17571
17572           zoom.duration = function (_) {
17573             return arguments.length ? (duration = +_, zoom) : duration;
17574           };
17575
17576           zoom.interpolate = function (_) {
17577             return arguments.length ? (interpolate = _, zoom) : interpolate;
17578           };
17579
17580           zoom.on = function () {
17581             var value = listeners.on.apply(listeners, arguments);
17582             return value === listeners ? zoom : value;
17583           };
17584
17585           zoom.clickDistance = function (_) {
17586             return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2);
17587           };
17588
17589           zoom.tapDistance = function (_) {
17590             return arguments.length ? (tapDistance = +_, zoom) : tapDistance;
17591           };
17592
17593           return zoom;
17594         }
17595
17596         /*
17597             Bypasses features of D3's default projection stream pipeline that are unnecessary:
17598             * Antimeridian clipping
17599             * Spherical rotation
17600             * Resampling
17601         */
17602
17603         function geoRawMercator() {
17604           var project = mercatorRaw;
17605           var k = 512 / Math.PI; // scale
17606
17607           var x = 0;
17608           var y = 0; // translate
17609
17610           var clipExtent = [[0, 0], [0, 0]];
17611
17612           function projection(point) {
17613             point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
17614             return [point[0] * k + x, y - point[1] * k];
17615           }
17616
17617           projection.invert = function (point) {
17618             point = project.invert((point[0] - x) / k, (y - point[1]) / k);
17619             return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
17620           };
17621
17622           projection.scale = function (_) {
17623             if (!arguments.length) return k;
17624             k = +_;
17625             return projection;
17626           };
17627
17628           projection.translate = function (_) {
17629             if (!arguments.length) return [x, y];
17630             x = +_[0];
17631             y = +_[1];
17632             return projection;
17633           };
17634
17635           projection.clipExtent = function (_) {
17636             if (!arguments.length) return clipExtent;
17637             clipExtent = _;
17638             return projection;
17639           };
17640
17641           projection.transform = function (obj) {
17642             if (!arguments.length) return identity$2.translate(x, y).scale(k);
17643             x = +obj.x;
17644             y = +obj.y;
17645             k = +obj.k;
17646             return projection;
17647           };
17648
17649           projection.stream = d3_geoTransform({
17650             point: function point(x, y) {
17651               var vec = projection([x, y]);
17652               this.stream.point(vec[0], vec[1]);
17653             }
17654           }).stream;
17655           return projection;
17656         }
17657
17658         function geoOrthoNormalizedDotProduct(a, b, origin) {
17659           if (geoVecEqual(origin, a) || geoVecEqual(origin, b)) {
17660             return 1; // coincident points, treat as straight and try to remove
17661           }
17662
17663           return geoVecNormalizedDot(a, b, origin);
17664         }
17665
17666         function geoOrthoFilterDotProduct(dotp, epsilon, lowerThreshold, upperThreshold, allowStraightAngles) {
17667           var val = Math.abs(dotp);
17668
17669           if (val < epsilon) {
17670             return 0; // already orthogonal
17671           } else if (allowStraightAngles && Math.abs(val - 1) < epsilon) {
17672             return 0; // straight angle, which is okay in this case
17673           } else if (val < lowerThreshold || val > upperThreshold) {
17674             return dotp; // can be adjusted
17675           } else {
17676             return null; // ignore vertex
17677           }
17678         }
17679
17680         function geoOrthoCalcScore(points, isClosed, epsilon, threshold) {
17681           var score = 0;
17682           var first = isClosed ? 0 : 1;
17683           var last = isClosed ? points.length : points.length - 1;
17684           var coords = points.map(function (p) {
17685             return p.coord;
17686           });
17687           var lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180);
17688           var upperThreshold = Math.cos(threshold * Math.PI / 180);
17689
17690           for (var i = first; i < last; i++) {
17691             var a = coords[(i - 1 + coords.length) % coords.length];
17692             var origin = coords[i];
17693             var b = coords[(i + 1) % coords.length];
17694             var dotp = geoOrthoFilterDotProduct(geoOrthoNormalizedDotProduct(a, b, origin), epsilon, lowerThreshold, upperThreshold);
17695             if (dotp === null) continue; // ignore vertex
17696
17697             score = score + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
17698           }
17699
17700           return score;
17701         } // returns the maximum angle less than `lessThan` between the actual corner and a 0° or 90° corner
17702
17703         function geoOrthoMaxOffsetAngle(coords, isClosed, lessThan) {
17704           var max = -Infinity;
17705           var first = isClosed ? 0 : 1;
17706           var last = isClosed ? coords.length : coords.length - 1;
17707
17708           for (var i = first; i < last; i++) {
17709             var a = coords[(i - 1 + coords.length) % coords.length];
17710             var origin = coords[i];
17711             var b = coords[(i + 1) % coords.length];
17712             var normalizedDotP = geoOrthoNormalizedDotProduct(a, b, origin);
17713             var angle = Math.acos(Math.abs(normalizedDotP)) * 180 / Math.PI;
17714             if (angle > 45) angle = 90 - angle;
17715             if (angle >= lessThan) continue;
17716             if (angle > max) max = angle;
17717           }
17718
17719           if (max === -Infinity) return null;
17720           return max;
17721         } // similar to geoOrthoCalcScore, but returns quickly if there is something to do
17722
17723         function geoOrthoCanOrthogonalize(coords, isClosed, epsilon, threshold, allowStraightAngles) {
17724           var score = null;
17725           var first = isClosed ? 0 : 1;
17726           var last = isClosed ? coords.length : coords.length - 1;
17727           var lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180);
17728           var upperThreshold = Math.cos(threshold * Math.PI / 180);
17729
17730           for (var i = first; i < last; i++) {
17731             var a = coords[(i - 1 + coords.length) % coords.length];
17732             var origin = coords[i];
17733             var b = coords[(i + 1) % coords.length];
17734             var dotp = geoOrthoFilterDotProduct(geoOrthoNormalizedDotProduct(a, b, origin), epsilon, lowerThreshold, upperThreshold, allowStraightAngles);
17735             if (dotp === null) continue; // ignore vertex
17736
17737             if (Math.abs(dotp) > 0) return 1; // something to do
17738
17739             score = 0; // already square
17740           }
17741
17742           return score;
17743         }
17744
17745         var call$2 = functionCall;
17746         var fixRegExpWellKnownSymbolLogic$1 = fixRegexpWellKnownSymbolLogic;
17747         var anObject$1 = anObject$n;
17748         var toLength$3 = toLength$c;
17749         var toString$8 = toString$k;
17750         var requireObjectCoercible$7 = requireObjectCoercible$e;
17751         var getMethod$1 = getMethod$7;
17752         var advanceStringIndex = advanceStringIndex$3;
17753         var regExpExec$1 = regexpExecAbstract;
17754
17755         // @@match logic
17756         fixRegExpWellKnownSymbolLogic$1('match', function (MATCH, nativeMatch, maybeCallNative) {
17757           return [
17758             // `String.prototype.match` method
17759             // https://tc39.es/ecma262/#sec-string.prototype.match
17760             function match(regexp) {
17761               var O = requireObjectCoercible$7(this);
17762               var matcher = regexp == undefined ? undefined : getMethod$1(regexp, MATCH);
17763               return matcher ? call$2(matcher, regexp, O) : new RegExp(regexp)[MATCH](toString$8(O));
17764             },
17765             // `RegExp.prototype[@@match]` method
17766             // https://tc39.es/ecma262/#sec-regexp.prototype-@@match
17767             function (string) {
17768               var rx = anObject$1(this);
17769               var S = toString$8(string);
17770               var res = maybeCallNative(nativeMatch, rx, S);
17771
17772               if (res.done) return res.value;
17773
17774               if (!rx.global) return regExpExec$1(rx, S);
17775
17776               var fullUnicode = rx.unicode;
17777               rx.lastIndex = 0;
17778               var A = [];
17779               var n = 0;
17780               var result;
17781               while ((result = regExpExec$1(rx, S)) !== null) {
17782                 var matchStr = toString$8(result[0]);
17783                 A[n] = matchStr;
17784                 if (matchStr === '') rx.lastIndex = advanceStringIndex(S, toLength$3(rx.lastIndex), fullUnicode);
17785                 n++;
17786               }
17787               return n === 0 ? null : A;
17788             }
17789           ];
17790         });
17791
17792         var $$s = _export;
17793         var FREEZING = freezing;
17794         var fails$9 = fails$V;
17795         var isObject$4 = isObject$s;
17796         var onFreeze = internalMetadata.exports.onFreeze;
17797
17798         // eslint-disable-next-line es/no-object-freeze -- safe
17799         var $freeze = Object.freeze;
17800         var FAILS_ON_PRIMITIVES = fails$9(function () { $freeze(1); });
17801
17802         // `Object.freeze` method
17803         // https://tc39.es/ecma262/#sec-object.freeze
17804         $$s({ target: 'Object', stat: true, forced: FAILS_ON_PRIMITIVES, sham: !FREEZING }, {
17805           freeze: function freeze(it) {
17806             return $freeze && isObject$4(it) ? $freeze(onFreeze(it)) : it;
17807           }
17808         });
17809
17810         // Returns true if a and b have the same elements at the same indices.
17811         function utilArrayIdentical(a, b) {
17812           // an array is always identical to itself
17813           if (a === b) return true;
17814           var i = a.length;
17815           if (i !== b.length) return false;
17816
17817           while (i--) {
17818             if (a[i] !== b[i]) return false;
17819           }
17820
17821           return true;
17822         } // http://2ality.com/2015/01/es6-set-operations.html
17823         // Difference (a \ b): create a set that contains those elements of set a that are not in set b.
17824         // This operation is also sometimes called minus (-).
17825         // var a = [1,2,3];
17826         // var b = [4,3,2];
17827         // utilArrayDifference(a, b)
17828         //   [1]
17829         // utilArrayDifference(b, a)
17830         //   [4]
17831
17832         function utilArrayDifference(a, b) {
17833           var other = new Set(b);
17834           return Array.from(new Set(a)).filter(function (v) {
17835             return !other.has(v);
17836           });
17837         } // Intersection (a ∩ b): create a set that contains those elements of set a that are also in set b.
17838         // var a = [1,2,3];
17839         // var b = [4,3,2];
17840         // utilArrayIntersection(a, b)
17841         //   [2,3]
17842
17843         function utilArrayIntersection(a, b) {
17844           var other = new Set(b);
17845           return Array.from(new Set(a)).filter(function (v) {
17846             return other.has(v);
17847           });
17848         } // Union (a ∪ b): create a set that contains the elements of both set a and set b.
17849         // var a = [1,2,3];
17850         // var b = [4,3,2];
17851         // utilArrayUnion(a, b)
17852         //   [1,2,3,4]
17853
17854         function utilArrayUnion(a, b) {
17855           var result = new Set(a);
17856           b.forEach(function (v) {
17857             result.add(v);
17858           });
17859           return Array.from(result);
17860         } // Returns an Array with all the duplicates removed
17861         // var a = [1,1,2,3,3];
17862         // utilArrayUniq(a)
17863         //   [1,2,3]
17864
17865         function utilArrayUniq(a) {
17866           return Array.from(new Set(a));
17867         } // Splits array into chunks of given chunk size
17868         // var a = [1,2,3,4,5,6,7];
17869         // utilArrayChunk(a, 3);
17870         //   [[1,2,3],[4,5,6],[7]];
17871
17872         function utilArrayChunk(a, chunkSize) {
17873           if (!chunkSize || chunkSize < 0) return [a.slice()];
17874           var result = new Array(Math.ceil(a.length / chunkSize));
17875           return Array.from(result, function (item, i) {
17876             return a.slice(i * chunkSize, i * chunkSize + chunkSize);
17877           });
17878         } // Flattens two level array into a single level
17879         // var a = [[1,2,3],[4,5,6],[7]];
17880         // utilArrayFlatten(a);
17881         //   [1,2,3,4,5,6,7];
17882
17883         function utilArrayFlatten(a) {
17884           return a.reduce(function (acc, val) {
17885             return acc.concat(val);
17886           }, []);
17887         } // Groups the items of the Array according to the given key
17888         // `key` can be passed as a property or as a key function
17889         //
17890         // var pets = [
17891         //     { type: 'Dog', name: 'Spot' },
17892         //     { type: 'Cat', name: 'Tiger' },
17893         //     { type: 'Dog', name: 'Rover' },
17894         //     { type: 'Cat', name: 'Leo' }
17895         // ];
17896         //
17897         // utilArrayGroupBy(pets, 'type')
17898         //   {
17899         //     'Dog': [{type: 'Dog', name: 'Spot'}, {type: 'Dog', name: 'Rover'}],
17900         //     'Cat': [{type: 'Cat', name: 'Tiger'}, {type: 'Cat', name: 'Leo'}]
17901         //   }
17902         //
17903         // utilArrayGroupBy(pets, function(item) { return item.name.length; })
17904         //   {
17905         //     3: [{type: 'Cat', name: 'Leo'}],
17906         //     4: [{type: 'Dog', name: 'Spot'}],
17907         //     5: [{type: 'Cat', name: 'Tiger'}, {type: 'Dog', name: 'Rover'}]
17908         //   }
17909
17910         function utilArrayGroupBy(a, key) {
17911           return a.reduce(function (acc, item) {
17912             var group = typeof key === 'function' ? key(item) : item[key];
17913             (acc[group] = acc[group] || []).push(item);
17914             return acc;
17915           }, {});
17916         } // Returns an Array with all the duplicates removed
17917         // where uniqueness determined by the given key
17918         // `key` can be passed as a property or as a key function
17919         //
17920         // var pets = [
17921         //     { type: 'Dog', name: 'Spot' },
17922         //     { type: 'Cat', name: 'Tiger' },
17923         //     { type: 'Dog', name: 'Rover' },
17924         //     { type: 'Cat', name: 'Leo' }
17925         // ];
17926         //
17927         // utilArrayUniqBy(pets, 'type')
17928         //   [
17929         //     { type: 'Dog', name: 'Spot' },
17930         //     { type: 'Cat', name: 'Tiger' }
17931         //   ]
17932         //
17933         // utilArrayUniqBy(pets, function(item) { return item.name.length; })
17934         //   [
17935         //     { type: 'Dog', name: 'Spot' },
17936         //     { type: 'Cat', name: 'Tiger' },
17937         //     { type: 'Cat', name: 'Leo' }
17938         //   }
17939
17940         function utilArrayUniqBy(a, key) {
17941           var seen = new Set();
17942           return a.reduce(function (acc, item) {
17943             var val = typeof key === 'function' ? key(item) : item[key];
17944
17945             if (val && !seen.has(val)) {
17946               seen.add(val);
17947               acc.push(item);
17948             }
17949
17950             return acc;
17951           }, []);
17952         }
17953
17954         var uncurryThis$d = functionUncurryThis;
17955
17956         // `thisNumberValue` abstract operation
17957         // https://tc39.es/ecma262/#sec-thisnumbervalue
17958         var thisNumberValue$3 = uncurryThis$d(1.0.valueOf);
17959
17960         var DESCRIPTORS$3 = descriptors;
17961         var global$a = global$1o;
17962         var uncurryThis$c = functionUncurryThis;
17963         var isForced = isForced_1;
17964         var redefine$2 = redefine$h.exports;
17965         var hasOwn$1 = hasOwnProperty_1;
17966         var inheritIfRequired = inheritIfRequired$4;
17967         var isPrototypeOf = objectIsPrototypeOf;
17968         var isSymbol$1 = isSymbol$6;
17969         var toPrimitive$1 = toPrimitive$3;
17970         var fails$8 = fails$V;
17971         var getOwnPropertyNames = objectGetOwnPropertyNames.f;
17972         var getOwnPropertyDescriptor$2 = objectGetOwnPropertyDescriptor.f;
17973         var defineProperty = objectDefineProperty.f;
17974         var thisNumberValue$2 = thisNumberValue$3;
17975         var trim$2 = stringTrim.trim;
17976
17977         var NUMBER = 'Number';
17978         var NativeNumber = global$a[NUMBER];
17979         var NumberPrototype = NativeNumber.prototype;
17980         var TypeError$4 = global$a.TypeError;
17981         var arraySlice$1 = uncurryThis$c(''.slice);
17982         var charCodeAt$1 = uncurryThis$c(''.charCodeAt);
17983
17984         // `ToNumeric` abstract operation
17985         // https://tc39.es/ecma262/#sec-tonumeric
17986         var toNumeric = function (value) {
17987           var primValue = toPrimitive$1(value, 'number');
17988           return typeof primValue == 'bigint' ? primValue : toNumber$1(primValue);
17989         };
17990
17991         // `ToNumber` abstract operation
17992         // https://tc39.es/ecma262/#sec-tonumber
17993         var toNumber$1 = function (argument) {
17994           var it = toPrimitive$1(argument, 'number');
17995           var first, third, radix, maxCode, digits, length, index, code;
17996           if (isSymbol$1(it)) throw TypeError$4('Cannot convert a Symbol value to a number');
17997           if (typeof it == 'string' && it.length > 2) {
17998             it = trim$2(it);
17999             first = charCodeAt$1(it, 0);
18000             if (first === 43 || first === 45) {
18001               third = charCodeAt$1(it, 2);
18002               if (third === 88 || third === 120) return NaN; // Number('+0x1') should be NaN, old V8 fix
18003             } else if (first === 48) {
18004               switch (charCodeAt$1(it, 1)) {
18005                 case 66: case 98: radix = 2; maxCode = 49; break; // fast equal of /^0b[01]+$/i
18006                 case 79: case 111: radix = 8; maxCode = 55; break; // fast equal of /^0o[0-7]+$/i
18007                 default: return +it;
18008               }
18009               digits = arraySlice$1(it, 2);
18010               length = digits.length;
18011               for (index = 0; index < length; index++) {
18012                 code = charCodeAt$1(digits, index);
18013                 // parseInt parses a string to a first unavailable symbol
18014                 // but ToNumber should return NaN if a string contains unavailable symbols
18015                 if (code < 48 || code > maxCode) return NaN;
18016               } return parseInt(digits, radix);
18017             }
18018           } return +it;
18019         };
18020
18021         // `Number` constructor
18022         // https://tc39.es/ecma262/#sec-number-constructor
18023         if (isForced(NUMBER, !NativeNumber(' 0o1') || !NativeNumber('0b1') || NativeNumber('+0x1'))) {
18024           var NumberWrapper = function Number(value) {
18025             var n = arguments.length < 1 ? 0 : NativeNumber(toNumeric(value));
18026             var dummy = this;
18027             // check on 1..constructor(foo) case
18028             return isPrototypeOf(NumberPrototype, dummy) && fails$8(function () { thisNumberValue$2(dummy); })
18029               ? inheritIfRequired(Object(n), dummy, NumberWrapper) : n;
18030           };
18031           for (var keys = DESCRIPTORS$3 ? getOwnPropertyNames(NativeNumber) : (
18032             // ES3:
18033             'MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,' +
18034             // ES2015 (in case, if modules with ES2015 Number statics required before):
18035             'EPSILON,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,isFinite,isInteger,isNaN,isSafeInteger,parseFloat,parseInt,' +
18036             // ESNext
18037             'fromString,range'
18038           ).split(','), j$1 = 0, key; keys.length > j$1; j$1++) {
18039             if (hasOwn$1(NativeNumber, key = keys[j$1]) && !hasOwn$1(NumberWrapper, key)) {
18040               defineProperty(NumberWrapper, key, getOwnPropertyDescriptor$2(NativeNumber, key));
18041             }
18042           }
18043           NumberWrapper.prototype = NumberPrototype;
18044           NumberPrototype.constructor = NumberWrapper;
18045           redefine$2(global$a, NUMBER, NumberWrapper);
18046         }
18047
18048         var diacritics = {};
18049
18050         var remove$6 = diacritics.remove = removeDiacritics;
18051         var replacementList = [{
18052           base: ' ',
18053           chars: "\xA0"
18054         }, {
18055           base: '0',
18056           chars: "\u07C0"
18057         }, {
18058           base: 'A',
18059           chars: "\u24B6\uFF21\xC0\xC1\xC2\u1EA6\u1EA4\u1EAA\u1EA8\xC3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\xC4\u01DE\u1EA2\xC5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F"
18060         }, {
18061           base: 'AA',
18062           chars: "\uA732"
18063         }, {
18064           base: 'AE',
18065           chars: "\xC6\u01FC\u01E2"
18066         }, {
18067           base: 'AO',
18068           chars: "\uA734"
18069         }, {
18070           base: 'AU',
18071           chars: "\uA736"
18072         }, {
18073           base: 'AV',
18074           chars: "\uA738\uA73A"
18075         }, {
18076           base: 'AY',
18077           chars: "\uA73C"
18078         }, {
18079           base: 'B',
18080           chars: "\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0181"
18081         }, {
18082           base: 'C',
18083           chars: "\u24B8\uFF23\uA73E\u1E08\u0106C\u0108\u010A\u010C\xC7\u0187\u023B"
18084         }, {
18085           base: 'D',
18086           chars: "\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018A\u0189\u1D05\uA779"
18087         }, {
18088           base: 'Dh',
18089           chars: "\xD0"
18090         }, {
18091           base: 'DZ',
18092           chars: "\u01F1\u01C4"
18093         }, {
18094           base: 'Dz',
18095           chars: "\u01F2\u01C5"
18096         }, {
18097           base: 'E',
18098           chars: "\u025B\u24BA\uFF25\xC8\xC9\xCA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\xCB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E\u1D07"
18099         }, {
18100           base: 'F',
18101           chars: "\uA77C\u24BB\uFF26\u1E1E\u0191\uA77B"
18102         }, {
18103           base: 'G',
18104           chars: "\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E\u0262"
18105         }, {
18106           base: 'H',
18107           chars: "\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D"
18108         }, {
18109           base: 'I',
18110           chars: "\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197"
18111         }, {
18112           base: 'J',
18113           chars: "\u24BF\uFF2A\u0134\u0248\u0237"
18114         }, {
18115           base: 'K',
18116           chars: "\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2"
18117         }, {
18118           base: 'L',
18119           chars: "\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780"
18120         }, {
18121           base: 'LJ',
18122           chars: "\u01C7"
18123         }, {
18124           base: 'Lj',
18125           chars: "\u01C8"
18126         }, {
18127           base: 'M',
18128           chars: "\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C\u03FB"
18129         }, {
18130           base: 'N',
18131           chars: "\uA7A4\u0220\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u019D\uA790\u1D0E"
18132         }, {
18133           base: 'NJ',
18134           chars: "\u01CA"
18135         }, {
18136           base: 'Nj',
18137           chars: "\u01CB"
18138         }, {
18139           base: 'O',
18140           chars: "\u24C4\uFF2F\xD2\xD3\xD4\u1ED2\u1ED0\u1ED6\u1ED4\xD5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\xD6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\xD8\u01FE\u0186\u019F\uA74A\uA74C"
18141         }, {
18142           base: 'OE',
18143           chars: "\u0152"
18144         }, {
18145           base: 'OI',
18146           chars: "\u01A2"
18147         }, {
18148           base: 'OO',
18149           chars: "\uA74E"
18150         }, {
18151           base: 'OU',
18152           chars: "\u0222"
18153         }, {
18154           base: 'P',
18155           chars: "\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754"
18156         }, {
18157           base: 'Q',
18158           chars: "\u24C6\uFF31\uA756\uA758\u024A"
18159         }, {
18160           base: 'R',
18161           chars: "\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782"
18162         }, {
18163           base: 'S',
18164           chars: "\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784"
18165         }, {
18166           base: 'T',
18167           chars: "\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786"
18168         }, {
18169           base: 'Th',
18170           chars: "\xDE"
18171         }, {
18172           base: 'TZ',
18173           chars: "\uA728"
18174         }, {
18175           base: 'U',
18176           chars: "\u24CA\uFF35\xD9\xDA\xDB\u0168\u1E78\u016A\u1E7A\u016C\xDC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244"
18177         }, {
18178           base: 'V',
18179           chars: "\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245"
18180         }, {
18181           base: 'VY',
18182           chars: "\uA760"
18183         }, {
18184           base: 'W',
18185           chars: "\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72"
18186         }, {
18187           base: 'X',
18188           chars: "\u24CD\uFF38\u1E8A\u1E8C"
18189         }, {
18190           base: 'Y',
18191           chars: "\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE"
18192         }, {
18193           base: 'Z',
18194           chars: "\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762"
18195         }, {
18196           base: 'a',
18197           chars: "\u24D0\uFF41\u1E9A\xE0\xE1\xE2\u1EA7\u1EA5\u1EAB\u1EA9\xE3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\xE4\u01DF\u1EA3\xE5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250\u0251"
18198         }, {
18199           base: 'aa',
18200           chars: "\uA733"
18201         }, {
18202           base: 'ae',
18203           chars: "\xE6\u01FD\u01E3"
18204         }, {
18205           base: 'ao',
18206           chars: "\uA735"
18207         }, {
18208           base: 'au',
18209           chars: "\uA737"
18210         }, {
18211           base: 'av',
18212           chars: "\uA739\uA73B"
18213         }, {
18214           base: 'ay',
18215           chars: "\uA73D"
18216         }, {
18217           base: 'b',
18218           chars: "\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0182"
18219         }, {
18220           base: 'c',
18221           chars: "\uFF43\u24D2\u0107\u0109\u010B\u010D\xE7\u1E09\u0188\u023C\uA73F\u2184"
18222         }, {
18223           base: 'd',
18224           chars: "\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\u018B\u13E7\u0501\uA7AA"
18225         }, {
18226           base: 'dh',
18227           chars: "\xF0"
18228         }, {
18229           base: 'dz',
18230           chars: "\u01F3\u01C6"
18231         }, {
18232           base: 'e',
18233           chars: "\u24D4\uFF45\xE8\xE9\xEA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\xEB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u01DD"
18234         }, {
18235           base: 'f',
18236           chars: "\u24D5\uFF46\u1E1F\u0192"
18237         }, {
18238           base: 'ff',
18239           chars: "\uFB00"
18240         }, {
18241           base: 'fi',
18242           chars: "\uFB01"
18243         }, {
18244           base: 'fl',
18245           chars: "\uFB02"
18246         }, {
18247           base: 'ffi',
18248           chars: "\uFB03"
18249         }, {
18250           base: 'ffl',
18251           chars: "\uFB04"
18252         }, {
18253           base: 'g',
18254           chars: "\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\uA77F\u1D79"
18255         }, {
18256           base: 'h',
18257           chars: "\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265"
18258         }, {
18259           base: 'hv',
18260           chars: "\u0195"
18261         }, {
18262           base: 'i',
18263           chars: "\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131"
18264         }, {
18265           base: 'j',
18266           chars: "\u24D9\uFF4A\u0135\u01F0\u0249"
18267         }, {
18268           base: 'k',
18269           chars: "\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3"
18270         }, {
18271           base: 'l',
18272           chars: "\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u026D"
18273         }, {
18274           base: 'lj',
18275           chars: "\u01C9"
18276         }, {
18277           base: 'm',
18278           chars: "\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F"
18279         }, {
18280           base: 'n',
18281           chars: "\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509"
18282         }, {
18283           base: 'nj',
18284           chars: "\u01CC"
18285         }, {
18286           base: 'o',
18287           chars: "\u24DE\uFF4F\xF2\xF3\xF4\u1ED3\u1ED1\u1ED7\u1ED5\xF5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\xF6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\xF8\u01FF\uA74B\uA74D\u0275\u0254\u1D11"
18288         }, {
18289           base: 'oe',
18290           chars: "\u0153"
18291         }, {
18292           base: 'oi',
18293           chars: "\u01A3"
18294         }, {
18295           base: 'oo',
18296           chars: "\uA74F"
18297         }, {
18298           base: 'ou',
18299           chars: "\u0223"
18300         }, {
18301           base: 'p',
18302           chars: "\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u03C1"
18303         }, {
18304           base: 'q',
18305           chars: "\u24E0\uFF51\u024B\uA757\uA759"
18306         }, {
18307           base: 'r',
18308           chars: "\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783"
18309         }, {
18310           base: 's',
18311           chars: "\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0282"
18312         }, {
18313           base: 'ss',
18314           chars: "\xDF"
18315         }, {
18316           base: 't',
18317           chars: "\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787"
18318         }, {
18319           base: 'th',
18320           chars: "\xFE"
18321         }, {
18322           base: 'tz',
18323           chars: "\uA729"
18324         }, {
18325           base: 'u',
18326           chars: "\u24E4\uFF55\xF9\xFA\xFB\u0169\u1E79\u016B\u1E7B\u016D\xFC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289"
18327         }, {
18328           base: 'v',
18329           chars: "\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C"
18330         }, {
18331           base: 'vy',
18332           chars: "\uA761"
18333         }, {
18334           base: 'w',
18335           chars: "\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73"
18336         }, {
18337           base: 'x',
18338           chars: "\u24E7\uFF58\u1E8B\u1E8D"
18339         }, {
18340           base: 'y',
18341           chars: "\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF"
18342         }, {
18343           base: 'z',
18344           chars: "\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763"
18345         }];
18346         var diacriticsMap = {};
18347
18348         for (var i$1 = 0; i$1 < replacementList.length; i$1 += 1) {
18349           var chars = replacementList[i$1].chars;
18350
18351           for (var j = 0; j < chars.length; j += 1) {
18352             diacriticsMap[chars[j]] = replacementList[i$1].base;
18353           }
18354         }
18355
18356         function removeDiacritics(str) {
18357           return str.replace(/[^\u0000-\u007e]/g, function (c) {
18358             return diacriticsMap[c] || c;
18359           });
18360         }
18361
18362         diacritics.replacementList = replacementList;
18363         diacritics.diacriticsMap = diacriticsMap;
18364
18365         var lib = {};
18366
18367         var isArabic$1 = {};
18368
18369         Object.defineProperty(isArabic$1, "__esModule", {
18370           value: true
18371         });
18372         var arabicBlocks = [[0x0600, 0x06FF], [0x0750, 0x077F], [0x08A0, 0x08FF], [0xFB50, 0xFDFF], [0xFE70, 0xFEFF], [0x10E60, 0x10E7F], [0x1EC70, 0x1ECBF], [0x1EE00, 0x1EEFF] // Mathematical Alphabetic symbols https://www.unicode.org/charts/PDF/U1EE00.pdf
18373         ];
18374
18375         function isArabic(_char) {
18376           if (_char.length > 1) {
18377             // allow the newer chars?
18378             throw new Error('isArabic works on only one-character strings');
18379           }
18380
18381           var code = _char.charCodeAt(0);
18382
18383           for (var i = 0; i < arabicBlocks.length; i++) {
18384             var block = arabicBlocks[i];
18385
18386             if (code >= block[0] && code <= block[1]) {
18387               return true;
18388             }
18389           }
18390
18391           return false;
18392         }
18393
18394         isArabic$1.isArabic = isArabic;
18395
18396         function isMath(_char2) {
18397           if (_char2.length > 2) {
18398             // allow the newer chars?
18399             throw new Error('isMath works on only one-character strings');
18400           }
18401
18402           var code = _char2.charCodeAt(0);
18403
18404           return code >= 0x660 && code <= 0x66C || code >= 0x6F0 && code <= 0x6F9;
18405         }
18406
18407         isArabic$1.isMath = isMath;
18408
18409         var GlyphSplitter$1 = {};
18410
18411         var reference = {};
18412
18413         var unicodeArabic = {};
18414
18415         Object.defineProperty(unicodeArabic, "__esModule", {
18416           value: true
18417         });
18418         var arabicReference = {
18419           "alef": {
18420             "normal": ["\u0627"],
18421             "madda_above": {
18422               "normal": ["\u0627\u0653", "\u0622"],
18423               "isolated": "\uFE81",
18424               "final": "\uFE82"
18425             },
18426             "hamza_above": {
18427               "normal": ["\u0627\u0654", "\u0623"],
18428               "isolated": "\uFE83",
18429               "final": "\uFE84"
18430             },
18431             "hamza_below": {
18432               "normal": ["\u0627\u0655", "\u0625"],
18433               "isolated": "\uFE87",
18434               "final": "\uFE88"
18435             },
18436             "wasla": {
18437               "normal": "\u0671",
18438               "isolated": "\uFB50",
18439               "final": "\uFB51"
18440             },
18441             "wavy_hamza_above": ["\u0672"],
18442             "wavy_hamza_below": ["\u0627\u065F", "\u0673"],
18443             "high_hamza": ["\u0675", "\u0627\u0674"],
18444             "indic_two_above": ["\u0773"],
18445             "indic_three_above": ["\u0774"],
18446             "fathatan": {
18447               "normal": ["\u0627\u064B"],
18448               "final": "\uFD3C",
18449               "isolated": "\uFD3D"
18450             },
18451             "isolated": "\uFE8D",
18452             "final": "\uFE8E"
18453           },
18454           "beh": {
18455             "normal": ["\u0628"],
18456             "dotless": ["\u066E"],
18457             "three_dots_horizontally_below": ["\u0750"],
18458             "dot_below_three_dots_above": ["\u0751"],
18459             "three_dots_pointing_upwards_below": ["\u0752"],
18460             "three_dots_pointing_upwards_below_two_dots_above": ["\u0753"],
18461             "two_dots_below_dot_above": ["\u0754"],
18462             "inverted_small_v_below": ["\u0755"],
18463             "small_v": ["\u0756"],
18464             "small_v_below": ["\u08A0"],
18465             "hamza_above": ["\u08A1"],
18466             "small_meem_above": ["\u08B6"],
18467             "isolated": "\uFE8F",
18468             "final": "\uFE90",
18469             "initial": "\uFE91",
18470             "medial": "\uFE92"
18471           },
18472           "teh marbuta": {
18473             "normal": ["\u0629"],
18474             "isolated": "\uFE93",
18475             "final": "\uFE94"
18476           },
18477           "teh": {
18478             "normal": ["\u062A"],
18479             "ring": ["\u067C"],
18480             "three_dots_above_downwards": ["\u067D"],
18481             "small_teh_above": ["\u08B8"],
18482             "isolated": "\uFE95",
18483             "final": "\uFE96",
18484             "initial": "\uFE97",
18485             "medial": "\uFE98"
18486           },
18487           "theh": {
18488             "normal": ["\u062B"],
18489             "isolated": "\uFE99",
18490             "final": "\uFE9A",
18491             "initial": "\uFE9B",
18492             "medial": "\uFE9C"
18493           },
18494           "jeem": {
18495             "normal": ["\u062C"],
18496             "two_dots_above": ["\u08A2"],
18497             "isolated": "\uFE9D",
18498             "final": "\uFE9E",
18499             "initial": "\uFE9F",
18500             "medial": "\uFEA0"
18501           },
18502           "hah": {
18503             "normal": ["\u062D"],
18504             "hamza_above": ["\u0681"],
18505             "two_dots_vertical_above": ["\u0682"],
18506             "three_dots_above": ["\u0685"],
18507             "two_dots_above": ["\u0757"],
18508             "three_dots_pointing_upwards_below": ["\u0758"],
18509             "small_tah_below": ["\u076E"],
18510             "small_tah_two_dots": ["\u076F"],
18511             "small_tah_above": ["\u0772"],
18512             "indic_four_below": ["\u077C"],
18513             "isolated": "\uFEA1",
18514             "final": "\uFEA2",
18515             "initial": "\uFEA3",
18516             "medial": "\uFEA4"
18517           },
18518           "khah": {
18519             "normal": ["\u062E"],
18520             "isolated": "\uFEA5",
18521             "final": "\uFEA6",
18522             "initial": "\uFEA7",
18523             "medial": "\uFEA8"
18524           },
18525           "dal": {
18526             "normal": ["\u062F"],
18527             "ring": ["\u0689"],
18528             "dot_below": ["\u068A"],
18529             "dot_below_small_tah": ["\u068B"],
18530             "three_dots_above_downwards": ["\u068F"],
18531             "four_dots_above": ["\u0690"],
18532             "inverted_v": ["\u06EE"],
18533             "two_dots_vertically_below_small_tah": ["\u0759"],
18534             "inverted_small_v_below": ["\u075A"],
18535             "three_dots_below": ["\u08AE"],
18536             "isolated": "\uFEA9",
18537             "final": "\uFEAA"
18538           },
18539           "thal": {
18540             "normal": ["\u0630"],
18541             "isolated": "\uFEAB",
18542             "final": "\uFEAC"
18543           },
18544           "reh": {
18545             "normal": ["\u0631"],
18546             "small_v": ["\u0692"],
18547             "ring": ["\u0693"],
18548             "dot_below": ["\u0694"],
18549             "small_v_below": ["\u0695"],
18550             "dot_below_dot_above": ["\u0696"],
18551             "two_dots_above": ["\u0697"],
18552             "four_dots_above": ["\u0699"],
18553             "inverted_v": ["\u06EF"],
18554             "stroke": ["\u075B"],
18555             "two_dots_vertically_above": ["\u076B"],
18556             "hamza_above": ["\u076C"],
18557             "small_tah_two_dots": ["\u0771"],
18558             "loop": ["\u08AA"],
18559             "small_noon_above": ["\u08B9"],
18560             "isolated": "\uFEAD",
18561             "final": "\uFEAE"
18562           },
18563           "zain": {
18564             "normal": ["\u0632"],
18565             "inverted_v_above": ["\u08B2"],
18566             "isolated": "\uFEAF",
18567             "final": "\uFEB0"
18568           },
18569           "seen": {
18570             "normal": ["\u0633"],
18571             "dot_below_dot_above": ["\u069A"],
18572             "three_dots_below": ["\u069B"],
18573             "three_dots_below_three_dots_above": ["\u069C"],
18574             "four_dots_above": ["\u075C"],
18575             "two_dots_vertically_above": ["\u076D"],
18576             "small_tah_two_dots": ["\u0770"],
18577             "indic_four_above": ["\u077D"],
18578             "inverted_v": ["\u077E"],
18579             "isolated": "\uFEB1",
18580             "final": "\uFEB2",
18581             "initial": "\uFEB3",
18582             "medial": "\uFEB4"
18583           },
18584           "sheen": {
18585             "normal": ["\u0634"],
18586             "dot_below": ["\u06FA"],
18587             "isolated": "\uFEB5",
18588             "final": "\uFEB6",
18589             "initial": "\uFEB7",
18590             "medial": "\uFEB8"
18591           },
18592           "sad": {
18593             "normal": ["\u0635"],
18594             "two_dots_below": ["\u069D"],
18595             "three_dots_above": ["\u069E"],
18596             "three_dots_below": ["\u08AF"],
18597             "isolated": "\uFEB9",
18598             "final": "\uFEBA",
18599             "initial": "\uFEBB",
18600             "medial": "\uFEBC"
18601           },
18602           "dad": {
18603             "normal": ["\u0636"],
18604             "dot_below": ["\u06FB"],
18605             "isolated": "\uFEBD",
18606             "final": "\uFEBE",
18607             "initial": "\uFEBF",
18608             "medial": "\uFEC0"
18609           },
18610           "tah": {
18611             "normal": ["\u0637"],
18612             "three_dots_above": ["\u069F"],
18613             "two_dots_above": ["\u08A3"],
18614             "isolated": "\uFEC1",
18615             "final": "\uFEC2",
18616             "initial": "\uFEC3",
18617             "medial": "\uFEC4"
18618           },
18619           "zah": {
18620             "normal": ["\u0638"],
18621             "isolated": "\uFEC5",
18622             "final": "\uFEC6",
18623             "initial": "\uFEC7",
18624             "medial": "\uFEC8"
18625           },
18626           "ain": {
18627             "normal": ["\u0639"],
18628             "three_dots_above": ["\u06A0"],
18629             "two_dots_above": ["\u075D"],
18630             "three_dots_pointing_downwards_above": ["\u075E"],
18631             "two_dots_vertically_above": ["\u075F"],
18632             "three_dots_below": ["\u08B3"],
18633             "isolated": "\uFEC9",
18634             "final": "\uFECA",
18635             "initial": "\uFECB",
18636             "medial": "\uFECC"
18637           },
18638           "ghain": {
18639             "normal": ["\u063A"],
18640             "dot_below": ["\u06FC"],
18641             "isolated": "\uFECD",
18642             "final": "\uFECE",
18643             "initial": "\uFECF",
18644             "medial": "\uFED0"
18645           },
18646           "feh": {
18647             "normal": ["\u0641"],
18648             "dotless": ["\u06A1"],
18649             "dot_moved_below": ["\u06A2"],
18650             "dot_below": ["\u06A3"],
18651             "three_dots_below": ["\u06A5"],
18652             "two_dots_below": ["\u0760"],
18653             "three_dots_pointing_upwards_below": ["\u0761"],
18654             "dot_below_three_dots_above": ["\u08A4"],
18655             "isolated": "\uFED1",
18656             "final": "\uFED2",
18657             "initial": "\uFED3",
18658             "medial": "\uFED4"
18659           },
18660           "qaf": {
18661             "normal": ["\u0642"],
18662             "dotless": ["\u066F"],
18663             "dot_above": ["\u06A7"],
18664             "three_dots_above": ["\u06A8"],
18665             "dot_below": ["\u08A5"],
18666             "isolated": "\uFED5",
18667             "final": "\uFED6",
18668             "initial": "\uFED7",
18669             "medial": "\uFED8"
18670           },
18671           "kaf": {
18672             "normal": ["\u0643"],
18673             "swash": ["\u06AA"],
18674             "ring": ["\u06AB"],
18675             "dot_above": ["\u06AC"],
18676             "three_dots_below": ["\u06AE"],
18677             "two_dots_above": ["\u077F"],
18678             "dot_below": ["\u08B4"],
18679             "isolated": "\uFED9",
18680             "final": "\uFEDA",
18681             "initial": "\uFEDB",
18682             "medial": "\uFEDC"
18683           },
18684           "lam": {
18685             "normal": ["\u0644"],
18686             "small_v": ["\u06B5"],
18687             "dot_above": ["\u06B6"],
18688             "three_dots_above": ["\u06B7"],
18689             "three_dots_below": ["\u06B8"],
18690             "bar": ["\u076A"],
18691             "double_bar": ["\u08A6"],
18692             "isolated": "\uFEDD",
18693             "final": "\uFEDE",
18694             "initial": "\uFEDF",
18695             "medial": "\uFEE0"
18696           },
18697           "meem": {
18698             "normal": ["\u0645"],
18699             "dot_above": ["\u0765"],
18700             "dot_below": ["\u0766"],
18701             "three_dots_above": ["\u08A7"],
18702             "isolated": "\uFEE1",
18703             "final": "\uFEE2",
18704             "initial": "\uFEE3",
18705             "medial": "\uFEE4"
18706           },
18707           "noon": {
18708             "normal": ["\u0646"],
18709             "dot_below": ["\u06B9"],
18710             "ring": ["\u06BC"],
18711             "three_dots_above": ["\u06BD"],
18712             "two_dots_below": ["\u0767"],
18713             "small_tah": ["\u0768"],
18714             "small_v": ["\u0769"],
18715             "isolated": "\uFEE5",
18716             "final": "\uFEE6",
18717             "initial": "\uFEE7",
18718             "medial": "\uFEE8"
18719           },
18720           "heh": {
18721             "normal": ["\u0647"],
18722             "isolated": "\uFEE9",
18723             "final": "\uFEEA",
18724             "initial": "\uFEEB",
18725             "medial": "\uFEEC"
18726           },
18727           "waw": {
18728             "normal": ["\u0648"],
18729             "hamza_above": {
18730               "normal": ["\u0624", "\u0648\u0654"],
18731               "isolated": "\uFE85",
18732               "final": "\uFE86"
18733             },
18734             "high_hamza": ["\u0676", "\u0648\u0674"],
18735             "ring": ["\u06C4"],
18736             "two_dots_above": ["\u06CA"],
18737             "dot_above": ["\u06CF"],
18738             "indic_two_above": ["\u0778"],
18739             "indic_three_above": ["\u0779"],
18740             "dot_within": ["\u08AB"],
18741             "isolated": "\uFEED",
18742             "final": "\uFEEE"
18743           },
18744           "alef_maksura": {
18745             "normal": ["\u0649"],
18746             "hamza_above": ["\u0626", "\u064A\u0654"],
18747             "initial": "\uFBE8",
18748             "medial": "\uFBE9",
18749             "isolated": "\uFEEF",
18750             "final": "\uFEF0"
18751           },
18752           "yeh": {
18753             "normal": ["\u064A"],
18754             "hamza_above": {
18755               "normal": ["\u0626", "\u0649\u0654"],
18756               "isolated": "\uFE89",
18757               "final": "\uFE8A",
18758               "initial": "\uFE8B",
18759               "medial": "\uFE8C"
18760             },
18761             "two_dots_below_hamza_above": ["\u08A8"],
18762             "high_hamza": ["\u0678", "\u064A\u0674"],
18763             "tail": ["\u06CD"],
18764             "small_v": ["\u06CE"],
18765             "three_dots_below": ["\u06D1"],
18766             "two_dots_below_dot_above": ["\u08A9"],
18767             "two_dots_below_small_noon_above": ["\u08BA"],
18768             "isolated": "\uFEF1",
18769             "final": "\uFEF2",
18770             "initial": "\uFEF3",
18771             "medial": "\uFEF4"
18772           },
18773           "tteh": {
18774             "normal": ["\u0679"],
18775             "isolated": "\uFB66",
18776             "final": "\uFB67",
18777             "initial": "\uFB68",
18778             "medial": "\uFB69"
18779           },
18780           "tteheh": {
18781             "normal": ["\u067A"],
18782             "isolated": "\uFB5E",
18783             "final": "\uFB5F",
18784             "initial": "\uFB60",
18785             "medial": "\uFB61"
18786           },
18787           "beeh": {
18788             "normal": ["\u067B"],
18789             "isolated": "\uFB52",
18790             "final": "\uFB53",
18791             "initial": "\uFB54",
18792             "medial": "\uFB55"
18793           },
18794           "peh": {
18795             "normal": ["\u067E"],
18796             "small_meem_above": ["\u08B7"],
18797             "isolated": "\uFB56",
18798             "final": "\uFB57",
18799             "initial": "\uFB58",
18800             "medial": "\uFB59"
18801           },
18802           "teheh": {
18803             "normal": ["\u067F"],
18804             "isolated": "\uFB62",
18805             "final": "\uFB63",
18806             "initial": "\uFB64",
18807             "medial": "\uFB65"
18808           },
18809           "beheh": {
18810             "normal": ["\u0680"],
18811             "isolated": "\uFB5A",
18812             "final": "\uFB5B",
18813             "initial": "\uFB5C",
18814             "medial": "\uFB5D"
18815           },
18816           "nyeh": {
18817             "normal": ["\u0683"],
18818             "isolated": "\uFB76",
18819             "final": "\uFB77",
18820             "initial": "\uFB78",
18821             "medial": "\uFB79"
18822           },
18823           "dyeh": {
18824             "normal": ["\u0684"],
18825             "isolated": "\uFB72",
18826             "final": "\uFB73",
18827             "initial": "\uFB74",
18828             "medial": "\uFB75"
18829           },
18830           "tcheh": {
18831             "normal": ["\u0686"],
18832             "dot_above": ["\u06BF"],
18833             "isolated": "\uFB7A",
18834             "final": "\uFB7B",
18835             "initial": "\uFB7C",
18836             "medial": "\uFB7D"
18837           },
18838           "tcheheh": {
18839             "normal": ["\u0687"],
18840             "isolated": "\uFB7E",
18841             "final": "\uFB7F",
18842             "initial": "\uFB80",
18843             "medial": "\uFB81"
18844           },
18845           "ddal": {
18846             "normal": ["\u0688"],
18847             "isolated": "\uFB88",
18848             "final": "\uFB89"
18849           },
18850           "dahal": {
18851             "normal": ["\u068C"],
18852             "isolated": "\uFB84",
18853             "final": "\uFB85"
18854           },
18855           "ddahal": {
18856             "normal": ["\u068D"],
18857             "isolated": "\uFB82",
18858             "final": "\uFB83"
18859           },
18860           "dul": {
18861             "normal": ["\u068F", "\u068E"],
18862             "isolated": "\uFB86",
18863             "final": "\uFB87"
18864           },
18865           "rreh": {
18866             "normal": ["\u0691"],
18867             "isolated": "\uFB8C",
18868             "final": "\uFB8D"
18869           },
18870           "jeh": {
18871             "normal": ["\u0698"],
18872             "isolated": "\uFB8A",
18873             "final": "\uFB8B"
18874           },
18875           "veh": {
18876             "normal": ["\u06A4"],
18877             "isolated": "\uFB6A",
18878             "final": "\uFB6B",
18879             "initial": "\uFB6C",
18880             "medial": "\uFB6D"
18881           },
18882           "peheh": {
18883             "normal": ["\u06A6"],
18884             "isolated": "\uFB6E",
18885             "final": "\uFB6F",
18886             "initial": "\uFB70",
18887             "medial": "\uFB71"
18888           },
18889           "keheh": {
18890             "normal": ["\u06A9"],
18891             "dot_above": ["\u0762"],
18892             "three_dots_above": ["\u0763"],
18893             "three_dots_pointing_upwards_below": ["\u0764"],
18894             "isolated": "\uFB8E",
18895             "final": "\uFB8F",
18896             "initial": "\uFB90",
18897             "medial": "\uFB91"
18898           },
18899           "ng": {
18900             "normal": ["\u06AD"],
18901             "isolated": "\uFBD3",
18902             "final": "\uFBD4",
18903             "initial": "\uFBD5",
18904             "medial": "\uFBD6"
18905           },
18906           "gaf": {
18907             "normal": ["\u06AF"],
18908             "ring": ["\u06B0"],
18909             "two_dots_below": ["\u06B2"],
18910             "three_dots_above": ["\u06B4"],
18911             "inverted_stroke": ["\u08B0"],
18912             "isolated": "\uFB92",
18913             "final": "\uFB93",
18914             "initial": "\uFB94",
18915             "medial": "\uFB95"
18916           },
18917           "ngoeh": {
18918             "normal": ["\u06B1"],
18919             "isolated": "\uFB9A",
18920             "final": "\uFB9B",
18921             "initial": "\uFB9C",
18922             "medial": "\uFB9D"
18923           },
18924           "gueh": {
18925             "normal": ["\u06B3"],
18926             "isolated": "\uFB96",
18927             "final": "\uFB97",
18928             "initial": "\uFB98",
18929             "medial": "\uFB99"
18930           },
18931           "noon ghunna": {
18932             "normal": ["\u06BA"],
18933             "isolated": "\uFB9E",
18934             "final": "\uFB9F"
18935           },
18936           "rnoon": {
18937             "normal": ["\u06BB"],
18938             "isolated": "\uFBA0",
18939             "final": "\uFBA1",
18940             "initial": "\uFBA2",
18941             "medial": "\uFBA3"
18942           },
18943           "heh doachashmee": {
18944             "normal": ["\u06BE"],
18945             "isolated": "\uFBAA",
18946             "final": "\uFBAB",
18947             "initial": "\uFBAC",
18948             "medial": "\uFBAD"
18949           },
18950           "heh goal": {
18951             "normal": ["\u06C1"],
18952             "hamza_above": ["\u06C1\u0654", "\u06C2"],
18953             "isolated": "\uFBA6",
18954             "final": "\uFBA7",
18955             "initial": "\uFBA8",
18956             "medial": "\uFBA9"
18957           },
18958           "teh marbuta goal": {
18959             "normal": ["\u06C3"]
18960           },
18961           "kirghiz oe": {
18962             "normal": ["\u06C5"],
18963             "isolated": "\uFBE0",
18964             "final": "\uFBE1"
18965           },
18966           "oe": {
18967             "normal": ["\u06C6"],
18968             "isolated": "\uFBD9",
18969             "final": "\uFBDA"
18970           },
18971           "u": {
18972             "normal": ["\u06C7"],
18973             "hamza_above": {
18974               "normal": ["\u0677", "\u06C7\u0674"],
18975               "isolated": "\uFBDD"
18976             },
18977             "isolated": "\uFBD7",
18978             "final": "\uFBD8"
18979           },
18980           "yu": {
18981             "normal": ["\u06C8"],
18982             "isolated": "\uFBDB",
18983             "final": "\uFBDC"
18984           },
18985           "kirghiz yu": {
18986             "normal": ["\u06C9"],
18987             "isolated": "\uFBE2",
18988             "final": "\uFBE3"
18989           },
18990           "ve": {
18991             "normal": ["\u06CB"],
18992             "isolated": "\uFBDE",
18993             "final": "\uFBDF"
18994           },
18995           "farsi yeh": {
18996             "normal": ["\u06CC"],
18997             "indic_two_above": ["\u0775"],
18998             "indic_three_above": ["\u0776"],
18999             "indic_four_above": ["\u0777"],
19000             "isolated": "\uFBFC",
19001             "final": "\uFBFD",
19002             "initial": "\uFBFE",
19003             "medial": "\uFBFF"
19004           },
19005           "e": {
19006             "normal": ["\u06D0"],
19007             "isolated": "\uFBE4",
19008             "final": "\uFBE5",
19009             "initial": "\uFBE6",
19010             "medial": "\uFBE7"
19011           },
19012           "yeh barree": {
19013             "normal": ["\u06D2"],
19014             "hamza_above": {
19015               "normal": ["\u06D2\u0654", "\u06D3"],
19016               "isolated": "\uFBB0",
19017               "final": "\uFBB1"
19018             },
19019             "indic_two_above": ["\u077A"],
19020             "indic_three_above": ["\u077B"],
19021             "isolated": "\uFBAE",
19022             "final": "\uFBAF"
19023           },
19024           "ae": {
19025             "normal": ["\u06D5"],
19026             "isolated": "\u06D5",
19027             "final": "\uFEEA",
19028             "yeh_above": {
19029               "normal": ["\u06C0", "\u06D5\u0654"],
19030               "isolated": "\uFBA4",
19031               "final": "\uFBA5"
19032             }
19033           },
19034           "rohingya yeh": {
19035             "normal": ["\u08AC"]
19036           },
19037           "low alef": {
19038             "normal": ["\u08AD"]
19039           },
19040           "straight waw": {
19041             "normal": ["\u08B1"]
19042           },
19043           "african feh": {
19044             "normal": ["\u08BB"]
19045           },
19046           "african qaf": {
19047             "normal": ["\u08BC"]
19048           },
19049           "african noon": {
19050             "normal": ["\u08BD"]
19051           }
19052         };
19053
19054         unicodeArabic["default"] = arabicReference;
19055
19056         var unicodeLigatures = {};
19057
19058         Object.defineProperty(unicodeLigatures, "__esModule", {
19059           value: true
19060         });
19061         var ligatureReference = {
19062           "\u0626\u0627": {
19063             "isolated": "\uFBEA",
19064             "final": "\uFBEB"
19065           },
19066           "\u0626\u06D5": {
19067             "isolated": "\uFBEC",
19068             "final": "\uFBED"
19069           },
19070           "\u0626\u0648": {
19071             "isolated": "\uFBEE",
19072             "final": "\uFBEF"
19073           },
19074           "\u0626\u06C7": {
19075             "isolated": "\uFBF0",
19076             "final": "\uFBF1"
19077           },
19078           "\u0626\u06C6": {
19079             "isolated": "\uFBF2",
19080             "final": "\uFBF3"
19081           },
19082           "\u0626\u06C8": {
19083             "isolated": "\uFBF4",
19084             "final": "\uFBF5"
19085           },
19086           "\u0626\u06D0": {
19087             "isolated": "\uFBF6",
19088             "final": "\uFBF7",
19089             "initial": "\uFBF8"
19090           },
19091           "\u0626\u0649": {
19092             "uighur_kirghiz": {
19093               "isolated": "\uFBF9",
19094               "final": "\uFBFA",
19095               "initial": "\uFBFB"
19096             },
19097             "isolated": "\uFC03",
19098             "final": "\uFC68"
19099           },
19100           "\u0626\u062C": {
19101             "isolated": "\uFC00",
19102             "initial": "\uFC97"
19103           },
19104           "\u0626\u062D": {
19105             "isolated": "\uFC01",
19106             "initial": "\uFC98"
19107           },
19108           "\u0626\u0645": {
19109             "isolated": "\uFC02",
19110             "final": "\uFC66",
19111             "initial": "\uFC9A",
19112             "medial": "\uFCDF"
19113           },
19114           "\u0626\u064A": {
19115             "isolated": "\uFC04",
19116             "final": "\uFC69"
19117           },
19118           "\u0628\u062C": {
19119             "isolated": "\uFC05",
19120             "initial": "\uFC9C"
19121           },
19122           "\u0628\u062D": {
19123             "isolated": "\uFC06",
19124             "initial": "\uFC9D"
19125           },
19126           "\u0628\u062E": {
19127             "isolated": "\uFC07",
19128             "initial": "\uFC9E"
19129           },
19130           "\u0628\u0645": {
19131             "isolated": "\uFC08",
19132             "final": "\uFC6C",
19133             "initial": "\uFC9F",
19134             "medial": "\uFCE1"
19135           },
19136           "\u0628\u0649": {
19137             "isolated": "\uFC09",
19138             "final": "\uFC6E"
19139           },
19140           "\u0628\u064A": {
19141             "isolated": "\uFC0A",
19142             "final": "\uFC6F"
19143           },
19144           "\u062A\u062C": {
19145             "isolated": "\uFC0B",
19146             "initial": "\uFCA1"
19147           },
19148           "\u062A\u062D": {
19149             "isolated": "\uFC0C",
19150             "initial": "\uFCA2"
19151           },
19152           "\u062A\u062E": {
19153             "isolated": "\uFC0D",
19154             "initial": "\uFCA3"
19155           },
19156           "\u062A\u0645": {
19157             "isolated": "\uFC0E",
19158             "final": "\uFC72",
19159             "initial": "\uFCA4",
19160             "medial": "\uFCE3"
19161           },
19162           "\u062A\u0649": {
19163             "isolated": "\uFC0F",
19164             "final": "\uFC74"
19165           },
19166           "\u062A\u064A": {
19167             "isolated": "\uFC10",
19168             "final": "\uFC75"
19169           },
19170           "\u062B\u062C": {
19171             "isolated": "\uFC11"
19172           },
19173           "\u062B\u0645": {
19174             "isolated": "\uFC12",
19175             "final": "\uFC78",
19176             "initial": "\uFCA6",
19177             "medial": "\uFCE5"
19178           },
19179           "\u062B\u0649": {
19180             "isolated": "\uFC13",
19181             "final": "\uFC7A"
19182           },
19183           "\u062B\u0648": {
19184             "isolated": "\uFC14"
19185           },
19186           "\u062C\u062D": {
19187             "isolated": "\uFC15",
19188             "initial": "\uFCA7"
19189           },
19190           "\u062C\u0645": {
19191             "isolated": "\uFC16",
19192             "initial": "\uFCA8"
19193           },
19194           "\u062D\u062C": {
19195             "isolated": "\uFC17",
19196             "initial": "\uFCA9"
19197           },
19198           "\u062D\u0645": {
19199             "isolated": "\uFC18",
19200             "initial": "\uFCAA"
19201           },
19202           "\u062E\u062C": {
19203             "isolated": "\uFC19",
19204             "initial": "\uFCAB"
19205           },
19206           "\u062E\u062D": {
19207             "isolated": "\uFC1A"
19208           },
19209           "\u062E\u0645": {
19210             "isolated": "\uFC1B",
19211             "initial": "\uFCAC"
19212           },
19213           "\u0633\u062C": {
19214             "isolated": "\uFC1C",
19215             "initial": "\uFCAD",
19216             "medial": "\uFD34"
19217           },
19218           "\u0633\u062D": {
19219             "isolated": "\uFC1D",
19220             "initial": "\uFCAE",
19221             "medial": "\uFD35"
19222           },
19223           "\u0633\u062E": {
19224             "isolated": "\uFC1E",
19225             "initial": "\uFCAF",
19226             "medial": "\uFD36"
19227           },
19228           "\u0633\u0645": {
19229             "isolated": "\uFC1F",
19230             "initial": "\uFCB0",
19231             "medial": "\uFCE7"
19232           },
19233           "\u0635\u062D": {
19234             "isolated": "\uFC20",
19235             "initial": "\uFCB1"
19236           },
19237           "\u0635\u0645": {
19238             "isolated": "\uFC21",
19239             "initial": "\uFCB3"
19240           },
19241           "\u0636\u062C": {
19242             "isolated": "\uFC22",
19243             "initial": "\uFCB4"
19244           },
19245           "\u0636\u062D": {
19246             "isolated": "\uFC23",
19247             "initial": "\uFCB5"
19248           },
19249           "\u0636\u062E": {
19250             "isolated": "\uFC24",
19251             "initial": "\uFCB6"
19252           },
19253           "\u0636\u0645": {
19254             "isolated": "\uFC25",
19255             "initial": "\uFCB7"
19256           },
19257           "\u0637\u062D": {
19258             "isolated": "\uFC26",
19259             "initial": "\uFCB8"
19260           },
19261           "\u0637\u0645": {
19262             "isolated": "\uFC27",
19263             "initial": "\uFD33",
19264             "medial": "\uFD3A"
19265           },
19266           "\u0638\u0645": {
19267             "isolated": "\uFC28",
19268             "initial": "\uFCB9",
19269             "medial": "\uFD3B"
19270           },
19271           "\u0639\u062C": {
19272             "isolated": "\uFC29",
19273             "initial": "\uFCBA"
19274           },
19275           "\u0639\u0645": {
19276             "isolated": "\uFC2A",
19277             "initial": "\uFCBB"
19278           },
19279           "\u063A\u062C": {
19280             "isolated": "\uFC2B",
19281             "initial": "\uFCBC"
19282           },
19283           "\u063A\u0645": {
19284             "isolated": "\uFC2C",
19285             "initial": "\uFCBD"
19286           },
19287           "\u0641\u062C": {
19288             "isolated": "\uFC2D",
19289             "initial": "\uFCBE"
19290           },
19291           "\u0641\u062D": {
19292             "isolated": "\uFC2E",
19293             "initial": "\uFCBF"
19294           },
19295           "\u0641\u062E": {
19296             "isolated": "\uFC2F",
19297             "initial": "\uFCC0"
19298           },
19299           "\u0641\u0645": {
19300             "isolated": "\uFC30",
19301             "initial": "\uFCC1"
19302           },
19303           "\u0641\u0649": {
19304             "isolated": "\uFC31",
19305             "final": "\uFC7C"
19306           },
19307           "\u0641\u064A": {
19308             "isolated": "\uFC32",
19309             "final": "\uFC7D"
19310           },
19311           "\u0642\u062D": {
19312             "isolated": "\uFC33",
19313             "initial": "\uFCC2"
19314           },
19315           "\u0642\u0645": {
19316             "isolated": "\uFC34",
19317             "initial": "\uFCC3"
19318           },
19319           "\u0642\u0649": {
19320             "isolated": "\uFC35",
19321             "final": "\uFC7E"
19322           },
19323           "\u0642\u064A": {
19324             "isolated": "\uFC36",
19325             "final": "\uFC7F"
19326           },
19327           "\u0643\u0627": {
19328             "isolated": "\uFC37",
19329             "final": "\uFC80"
19330           },
19331           "\u0643\u062C": {
19332             "isolated": "\uFC38",
19333             "initial": "\uFCC4"
19334           },
19335           "\u0643\u062D": {
19336             "isolated": "\uFC39",
19337             "initial": "\uFCC5"
19338           },
19339           "\u0643\u062E": {
19340             "isolated": "\uFC3A",
19341             "initial": "\uFCC6"
19342           },
19343           "\u0643\u0644": {
19344             "isolated": "\uFC3B",
19345             "final": "\uFC81",
19346             "initial": "\uFCC7",
19347             "medial": "\uFCEB"
19348           },
19349           "\u0643\u0645": {
19350             "isolated": "\uFC3C",
19351             "final": "\uFC82",
19352             "initial": "\uFCC8",
19353             "medial": "\uFCEC"
19354           },
19355           "\u0643\u0649": {
19356             "isolated": "\uFC3D",
19357             "final": "\uFC83"
19358           },
19359           "\u0643\u064A": {
19360             "isolated": "\uFC3E",
19361             "final": "\uFC84"
19362           },
19363           "\u0644\u062C": {
19364             "isolated": "\uFC3F",
19365             "initial": "\uFCC9"
19366           },
19367           "\u0644\u062D": {
19368             "isolated": "\uFC40",
19369             "initial": "\uFCCA"
19370           },
19371           "\u0644\u062E": {
19372             "isolated": "\uFC41",
19373             "initial": "\uFCCB"
19374           },
19375           "\u0644\u0645": {
19376             "isolated": "\uFC42",
19377             "final": "\uFC85",
19378             "initial": "\uFCCC",
19379             "medial": "\uFCED"
19380           },
19381           "\u0644\u0649": {
19382             "isolated": "\uFC43",
19383             "final": "\uFC86"
19384           },
19385           "\u0644\u064A": {
19386             "isolated": "\uFC44",
19387             "final": "\uFC87"
19388           },
19389           "\u0645\u062C": {
19390             "isolated": "\uFC45",
19391             "initial": "\uFCCE"
19392           },
19393           "\u0645\u062D": {
19394             "isolated": "\uFC46",
19395             "initial": "\uFCCF"
19396           },
19397           "\u0645\u062E": {
19398             "isolated": "\uFC47",
19399             "initial": "\uFCD0"
19400           },
19401           "\u0645\u0645": {
19402             "isolated": "\uFC48",
19403             "final": "\uFC89",
19404             "initial": "\uFCD1"
19405           },
19406           "\u0645\u0649": {
19407             "isolated": "\uFC49"
19408           },
19409           "\u0645\u064A": {
19410             "isolated": "\uFC4A"
19411           },
19412           "\u0646\u062C": {
19413             "isolated": "\uFC4B",
19414             "initial": "\uFCD2"
19415           },
19416           "\u0646\u062D": {
19417             "isolated": "\uFC4C",
19418             "initial": "\uFCD3"
19419           },
19420           "\u0646\u062E": {
19421             "isolated": "\uFC4D",
19422             "initial": "\uFCD4"
19423           },
19424           "\u0646\u0645": {
19425             "isolated": "\uFC4E",
19426             "final": "\uFC8C",
19427             "initial": "\uFCD5",
19428             "medial": "\uFCEE"
19429           },
19430           "\u0646\u0649": {
19431             "isolated": "\uFC4F",
19432             "final": "\uFC8E"
19433           },
19434           "\u0646\u064A": {
19435             "isolated": "\uFC50",
19436             "final": "\uFC8F"
19437           },
19438           "\u0647\u062C": {
19439             "isolated": "\uFC51",
19440             "initial": "\uFCD7"
19441           },
19442           "\u0647\u0645": {
19443             "isolated": "\uFC52",
19444             "initial": "\uFCD8"
19445           },
19446           "\u0647\u0649": {
19447             "isolated": "\uFC53"
19448           },
19449           "\u0647\u064A": {
19450             "isolated": "\uFC54"
19451           },
19452           "\u064A\u062C": {
19453             "isolated": "\uFC55",
19454             "initial": "\uFCDA"
19455           },
19456           "\u064A\u062D": {
19457             "isolated": "\uFC56",
19458             "initial": "\uFCDB"
19459           },
19460           "\u064A\u062E": {
19461             "isolated": "\uFC57",
19462             "initial": "\uFCDC"
19463           },
19464           "\u064A\u0645": {
19465             "isolated": "\uFC58",
19466             "final": "\uFC93",
19467             "initial": "\uFCDD",
19468             "medial": "\uFCF0"
19469           },
19470           "\u064A\u0649": {
19471             "isolated": "\uFC59",
19472             "final": "\uFC95"
19473           },
19474           "\u064A\u064A": {
19475             "isolated": "\uFC5A",
19476             "final": "\uFC96"
19477           },
19478           "\u0630\u0670": {
19479             "isolated": "\uFC5B"
19480           },
19481           "\u0631\u0670": {
19482             "isolated": "\uFC5C"
19483           },
19484           "\u0649\u0670": {
19485             "isolated": "\uFC5D",
19486             "final": "\uFC90"
19487           },
19488           "\u064C\u0651": {
19489             "isolated": "\uFC5E"
19490           },
19491           "\u064D\u0651": {
19492             "isolated": "\uFC5F"
19493           },
19494           "\u064E\u0651": {
19495             "isolated": "\uFC60"
19496           },
19497           "\u064F\u0651": {
19498             "isolated": "\uFC61"
19499           },
19500           "\u0650\u0651": {
19501             "isolated": "\uFC62"
19502           },
19503           "\u0651\u0670": {
19504             "isolated": "\uFC63"
19505           },
19506           "\u0626\u0631": {
19507             "final": "\uFC64"
19508           },
19509           "\u0626\u0632": {
19510             "final": "\uFC65"
19511           },
19512           "\u0626\u0646": {
19513             "final": "\uFC67"
19514           },
19515           "\u0628\u0631": {
19516             "final": "\uFC6A"
19517           },
19518           "\u0628\u0632": {
19519             "final": "\uFC6B"
19520           },
19521           "\u0628\u0646": {
19522             "final": "\uFC6D"
19523           },
19524           "\u062A\u0631": {
19525             "final": "\uFC70"
19526           },
19527           "\u062A\u0632": {
19528             "final": "\uFC71"
19529           },
19530           "\u062A\u0646": {
19531             "final": "\uFC73"
19532           },
19533           "\u062B\u0631": {
19534             "final": "\uFC76"
19535           },
19536           "\u062B\u0632": {
19537             "final": "\uFC77"
19538           },
19539           "\u062B\u0646": {
19540             "final": "\uFC79"
19541           },
19542           "\u062B\u064A": {
19543             "final": "\uFC7B"
19544           },
19545           "\u0645\u0627": {
19546             "final": "\uFC88"
19547           },
19548           "\u0646\u0631": {
19549             "final": "\uFC8A"
19550           },
19551           "\u0646\u0632": {
19552             "final": "\uFC8B"
19553           },
19554           "\u0646\u0646": {
19555             "final": "\uFC8D"
19556           },
19557           "\u064A\u0631": {
19558             "final": "\uFC91"
19559           },
19560           "\u064A\u0632": {
19561             "final": "\uFC92"
19562           },
19563           "\u064A\u0646": {
19564             "final": "\uFC94"
19565           },
19566           "\u0626\u062E": {
19567             "initial": "\uFC99"
19568           },
19569           "\u0626\u0647": {
19570             "initial": "\uFC9B",
19571             "medial": "\uFCE0"
19572           },
19573           "\u0628\u0647": {
19574             "initial": "\uFCA0",
19575             "medial": "\uFCE2"
19576           },
19577           "\u062A\u0647": {
19578             "initial": "\uFCA5",
19579             "medial": "\uFCE4"
19580           },
19581           "\u0635\u062E": {
19582             "initial": "\uFCB2"
19583           },
19584           "\u0644\u0647": {
19585             "initial": "\uFCCD"
19586           },
19587           "\u0646\u0647": {
19588             "initial": "\uFCD6",
19589             "medial": "\uFCEF"
19590           },
19591           "\u0647\u0670": {
19592             "initial": "\uFCD9"
19593           },
19594           "\u064A\u0647": {
19595             "initial": "\uFCDE",
19596             "medial": "\uFCF1"
19597           },
19598           "\u062B\u0647": {
19599             "medial": "\uFCE6"
19600           },
19601           "\u0633\u0647": {
19602             "medial": "\uFCE8",
19603             "initial": "\uFD31"
19604           },
19605           "\u0634\u0645": {
19606             "medial": "\uFCE9",
19607             "isolated": "\uFD0C",
19608             "final": "\uFD28",
19609             "initial": "\uFD30"
19610           },
19611           "\u0634\u0647": {
19612             "medial": "\uFCEA",
19613             "initial": "\uFD32"
19614           },
19615           "\u0640\u064E\u0651": {
19616             "medial": "\uFCF2"
19617           },
19618           "\u0640\u064F\u0651": {
19619             "medial": "\uFCF3"
19620           },
19621           "\u0640\u0650\u0651": {
19622             "medial": "\uFCF4"
19623           },
19624           "\u0637\u0649": {
19625             "isolated": "\uFCF5",
19626             "final": "\uFD11"
19627           },
19628           "\u0637\u064A": {
19629             "isolated": "\uFCF6",
19630             "final": "\uFD12"
19631           },
19632           "\u0639\u0649": {
19633             "isolated": "\uFCF7",
19634             "final": "\uFD13"
19635           },
19636           "\u0639\u064A": {
19637             "isolated": "\uFCF8",
19638             "final": "\uFD14"
19639           },
19640           "\u063A\u0649": {
19641             "isolated": "\uFCF9",
19642             "final": "\uFD15"
19643           },
19644           "\u063A\u064A": {
19645             "isolated": "\uFCFA",
19646             "final": "\uFD16"
19647           },
19648           "\u0633\u0649": {
19649             "isolated": "\uFCFB"
19650           },
19651           "\u0633\u064A": {
19652             "isolated": "\uFCFC",
19653             "final": "\uFD18"
19654           },
19655           "\u0634\u0649": {
19656             "isolated": "\uFCFD",
19657             "final": "\uFD19"
19658           },
19659           "\u0634\u064A": {
19660             "isolated": "\uFCFE",
19661             "final": "\uFD1A"
19662           },
19663           "\u062D\u0649": {
19664             "isolated": "\uFCFF",
19665             "final": "\uFD1B"
19666           },
19667           "\u062D\u064A": {
19668             "isolated": "\uFD00",
19669             "final": "\uFD1C"
19670           },
19671           "\u062C\u0649": {
19672             "isolated": "\uFD01",
19673             "final": "\uFD1D"
19674           },
19675           "\u062C\u064A": {
19676             "isolated": "\uFD02",
19677             "final": "\uFD1E"
19678           },
19679           "\u062E\u0649": {
19680             "isolated": "\uFD03",
19681             "final": "\uFD1F"
19682           },
19683           "\u062E\u064A": {
19684             "isolated": "\uFD04",
19685             "final": "\uFD20"
19686           },
19687           "\u0635\u0649": {
19688             "isolated": "\uFD05",
19689             "final": "\uFD21"
19690           },
19691           "\u0635\u064A": {
19692             "isolated": "\uFD06",
19693             "final": "\uFD22"
19694           },
19695           "\u0636\u0649": {
19696             "isolated": "\uFD07",
19697             "final": "\uFD23"
19698           },
19699           "\u0636\u064A": {
19700             "isolated": "\uFD08",
19701             "final": "\uFD24"
19702           },
19703           "\u0634\u062C": {
19704             "isolated": "\uFD09",
19705             "final": "\uFD25",
19706             "initial": "\uFD2D",
19707             "medial": "\uFD37"
19708           },
19709           "\u0634\u062D": {
19710             "isolated": "\uFD0A",
19711             "final": "\uFD26",
19712             "initial": "\uFD2E",
19713             "medial": "\uFD38"
19714           },
19715           "\u0634\u062E": {
19716             "isolated": "\uFD0B",
19717             "final": "\uFD27",
19718             "initial": "\uFD2F",
19719             "medial": "\uFD39"
19720           },
19721           "\u0634\u0631": {
19722             "isolated": "\uFD0D",
19723             "final": "\uFD29"
19724           },
19725           "\u0633\u0631": {
19726             "isolated": "\uFD0E",
19727             "final": "\uFD2A"
19728           },
19729           "\u0635\u0631": {
19730             "isolated": "\uFD0F",
19731             "final": "\uFD2B"
19732           },
19733           "\u0636\u0631": {
19734             "isolated": "\uFD10",
19735             "final": "\uFD2C"
19736           },
19737           "\u0633\u0639": {
19738             "final": "\uFD17"
19739           },
19740           "\u062A\u062C\u0645": {
19741             "initial": "\uFD50"
19742           },
19743           "\u062A\u062D\u062C": {
19744             "final": "\uFD51",
19745             "initial": "\uFD52"
19746           },
19747           "\u062A\u062D\u0645": {
19748             "initial": "\uFD53"
19749           },
19750           "\u062A\u062E\u0645": {
19751             "initial": "\uFD54"
19752           },
19753           "\u062A\u0645\u062C": {
19754             "initial": "\uFD55"
19755           },
19756           "\u062A\u0645\u062D": {
19757             "initial": "\uFD56"
19758           },
19759           "\u062A\u0645\u062E": {
19760             "initial": "\uFD57"
19761           },
19762           "\u062C\u0645\u062D": {
19763             "final": "\uFD58",
19764             "initial": "\uFD59"
19765           },
19766           "\u062D\u0645\u064A": {
19767             "final": "\uFD5A"
19768           },
19769           "\u062D\u0645\u0649": {
19770             "final": "\uFD5B"
19771           },
19772           "\u0633\u062D\u062C": {
19773             "initial": "\uFD5C"
19774           },
19775           "\u0633\u062C\u062D": {
19776             "initial": "\uFD5D"
19777           },
19778           "\u0633\u062C\u0649": {
19779             "final": "\uFD5E"
19780           },
19781           "\u0633\u0645\u062D": {
19782             "final": "\uFD5F",
19783             "initial": "\uFD60"
19784           },
19785           "\u0633\u0645\u062C": {
19786             "initial": "\uFD61"
19787           },
19788           "\u0633\u0645\u0645": {
19789             "final": "\uFD62",
19790             "initial": "\uFD63"
19791           },
19792           "\u0635\u062D\u062D": {
19793             "final": "\uFD64",
19794             "initial": "\uFD65"
19795           },
19796           "\u0635\u0645\u0645": {
19797             "final": "\uFD66",
19798             "initial": "\uFDC5"
19799           },
19800           "\u0634\u062D\u0645": {
19801             "final": "\uFD67",
19802             "initial": "\uFD68"
19803           },
19804           "\u0634\u062C\u064A": {
19805             "final": "\uFD69"
19806           },
19807           "\u0634\u0645\u062E": {
19808             "final": "\uFD6A",
19809             "initial": "\uFD6B"
19810           },
19811           "\u0634\u0645\u0645": {
19812             "final": "\uFD6C",
19813             "initial": "\uFD6D"
19814           },
19815           "\u0636\u062D\u0649": {
19816             "final": "\uFD6E"
19817           },
19818           "\u0636\u062E\u0645": {
19819             "final": "\uFD6F",
19820             "initial": "\uFD70"
19821           },
19822           "\u0636\u0645\u062D": {
19823             "final": "\uFD71"
19824           },
19825           "\u0637\u0645\u062D": {
19826             "initial": "\uFD72"
19827           },
19828           "\u0637\u0645\u0645": {
19829             "initial": "\uFD73"
19830           },
19831           "\u0637\u0645\u064A": {
19832             "final": "\uFD74"
19833           },
19834           "\u0639\u062C\u0645": {
19835             "final": "\uFD75",
19836             "initial": "\uFDC4"
19837           },
19838           "\u0639\u0645\u0645": {
19839             "final": "\uFD76",
19840             "initial": "\uFD77"
19841           },
19842           "\u0639\u0645\u0649": {
19843             "final": "\uFD78"
19844           },
19845           "\u063A\u0645\u0645": {
19846             "final": "\uFD79"
19847           },
19848           "\u063A\u0645\u064A": {
19849             "final": "\uFD7A"
19850           },
19851           "\u063A\u0645\u0649": {
19852             "final": "\uFD7B"
19853           },
19854           "\u0641\u062E\u0645": {
19855             "final": "\uFD7C",
19856             "initial": "\uFD7D"
19857           },
19858           "\u0642\u0645\u062D": {
19859             "final": "\uFD7E",
19860             "initial": "\uFDB4"
19861           },
19862           "\u0642\u0645\u0645": {
19863             "final": "\uFD7F"
19864           },
19865           "\u0644\u062D\u0645": {
19866             "final": "\uFD80",
19867             "initial": "\uFDB5"
19868           },
19869           "\u0644\u062D\u064A": {
19870             "final": "\uFD81"
19871           },
19872           "\u0644\u062D\u0649": {
19873             "final": "\uFD82"
19874           },
19875           "\u0644\u062C\u062C": {
19876             "initial": "\uFD83",
19877             "final": "\uFD84"
19878           },
19879           "\u0644\u062E\u0645": {
19880             "final": "\uFD85",
19881             "initial": "\uFD86"
19882           },
19883           "\u0644\u0645\u062D": {
19884             "final": "\uFD87",
19885             "initial": "\uFD88"
19886           },
19887           "\u0645\u062D\u062C": {
19888             "initial": "\uFD89"
19889           },
19890           "\u0645\u062D\u0645": {
19891             "initial": "\uFD8A"
19892           },
19893           "\u0645\u062D\u064A": {
19894             "final": "\uFD8B"
19895           },
19896           "\u0645\u062C\u062D": {
19897             "initial": "\uFD8C"
19898           },
19899           "\u0645\u062C\u0645": {
19900             "initial": "\uFD8D"
19901           },
19902           "\u0645\u062E\u062C": {
19903             "initial": "\uFD8E"
19904           },
19905           "\u0645\u062E\u0645": {
19906             "initial": "\uFD8F"
19907           },
19908           "\u0645\u062C\u062E": {
19909             "initial": "\uFD92"
19910           },
19911           "\u0647\u0645\u062C": {
19912             "initial": "\uFD93"
19913           },
19914           "\u0647\u0645\u0645": {
19915             "initial": "\uFD94"
19916           },
19917           "\u0646\u062D\u0645": {
19918             "initial": "\uFD95"
19919           },
19920           "\u0646\u062D\u0649": {
19921             "final": "\uFD96"
19922           },
19923           "\u0646\u062C\u0645": {
19924             "final": "\uFD97",
19925             "initial": "\uFD98"
19926           },
19927           "\u0646\u062C\u0649": {
19928             "final": "\uFD99"
19929           },
19930           "\u0646\u0645\u064A": {
19931             "final": "\uFD9A"
19932           },
19933           "\u0646\u0645\u0649": {
19934             "final": "\uFD9B"
19935           },
19936           "\u064A\u0645\u0645": {
19937             "final": "\uFD9C",
19938             "initial": "\uFD9D"
19939           },
19940           "\u0628\u062E\u064A": {
19941             "final": "\uFD9E"
19942           },
19943           "\u062A\u062C\u064A": {
19944             "final": "\uFD9F"
19945           },
19946           "\u062A\u062C\u0649": {
19947             "final": "\uFDA0"
19948           },
19949           "\u062A\u062E\u064A": {
19950             "final": "\uFDA1"
19951           },
19952           "\u062A\u062E\u0649": {
19953             "final": "\uFDA2"
19954           },
19955           "\u062A\u0645\u064A": {
19956             "final": "\uFDA3"
19957           },
19958           "\u062A\u0645\u0649": {
19959             "final": "\uFDA4"
19960           },
19961           "\u062C\u0645\u064A": {
19962             "final": "\uFDA5"
19963           },
19964           "\u062C\u062D\u0649": {
19965             "final": "\uFDA6"
19966           },
19967           "\u062C\u0645\u0649": {
19968             "final": "\uFDA7"
19969           },
19970           "\u0633\u062E\u0649": {
19971             "final": "\uFDA8"
19972           },
19973           "\u0635\u062D\u064A": {
19974             "final": "\uFDA9"
19975           },
19976           "\u0634\u062D\u064A": {
19977             "final": "\uFDAA"
19978           },
19979           "\u0636\u062D\u064A": {
19980             "final": "\uFDAB"
19981           },
19982           "\u0644\u062C\u064A": {
19983             "final": "\uFDAC"
19984           },
19985           "\u0644\u0645\u064A": {
19986             "final": "\uFDAD"
19987           },
19988           "\u064A\u062D\u064A": {
19989             "final": "\uFDAE"
19990           },
19991           "\u064A\u062C\u064A": {
19992             "final": "\uFDAF"
19993           },
19994           "\u064A\u0645\u064A": {
19995             "final": "\uFDB0"
19996           },
19997           "\u0645\u0645\u064A": {
19998             "final": "\uFDB1"
19999           },
20000           "\u0642\u0645\u064A": {
20001             "final": "\uFDB2"
20002           },
20003           "\u0646\u062D\u064A": {
20004             "final": "\uFDB3"
20005           },
20006           "\u0639\u0645\u064A": {
20007             "final": "\uFDB6"
20008           },
20009           "\u0643\u0645\u064A": {
20010             "final": "\uFDB7"
20011           },
20012           "\u0646\u062C\u062D": {
20013             "initial": "\uFDB8",
20014             "final": "\uFDBD"
20015           },
20016           "\u0645\u062E\u064A": {
20017             "final": "\uFDB9"
20018           },
20019           "\u0644\u062C\u0645": {
20020             "initial": "\uFDBA",
20021             "final": "\uFDBC"
20022           },
20023           "\u0643\u0645\u0645": {
20024             "final": "\uFDBB",
20025             "initial": "\uFDC3"
20026           },
20027           "\u062C\u062D\u064A": {
20028             "final": "\uFDBE"
20029           },
20030           "\u062D\u062C\u064A": {
20031             "final": "\uFDBF"
20032           },
20033           "\u0645\u062C\u064A": {
20034             "final": "\uFDC0"
20035           },
20036           "\u0641\u0645\u064A": {
20037             "final": "\uFDC1"
20038           },
20039           "\u0628\u062D\u064A": {
20040             "final": "\uFDC2"
20041           },
20042           "\u0633\u062E\u064A": {
20043             "final": "\uFDC6"
20044           },
20045           "\u0646\u062C\u064A": {
20046             "final": "\uFDC7"
20047           },
20048           "\u0644\u0622": {
20049             "isolated": "\uFEF5",
20050             "final": "\uFEF6"
20051           },
20052           "\u0644\u0623": {
20053             "isolated": "\uFEF7",
20054             "final": "\uFEF8"
20055           },
20056           "\u0644\u0625": {
20057             "isolated": "\uFEF9",
20058             "final": "\uFEFA"
20059           },
20060           "\u0644\u0627": {
20061             "isolated": "\uFEFB",
20062             "final": "\uFEFC"
20063           },
20064           "words": {
20065             "\u0635\u0644\u06D2": "\uFDF0",
20066             "\u0642\u0644\u06D2": "\uFDF1",
20067             "\u0627\u0644\u0644\u0647": "\uFDF2",
20068             "\u0627\u0643\u0628\u0631": "\uFDF3",
20069             "\u0645\u062D\u0645\u062F": "\uFDF4",
20070             "\u0635\u0644\u0639\u0645": "\uFDF5",
20071             "\u0631\u0633\u0648\u0644": "\uFDF6",
20072             "\u0639\u0644\u064A\u0647": "\uFDF7",
20073             "\u0648\u0633\u0644\u0645": "\uFDF8",
20074             "\u0635\u0644\u0649": "\uFDF9",
20075             "\u0635\u0644\u0649\u0627\u0644\u0644\u0647\u0639\u0644\u064A\u0647\u0648\u0633\u0644\u0645": "\uFDFA",
20076             "\u062C\u0644\u062C\u0644\u0627\u0644\u0647": "\uFDFB",
20077             "\u0631\u06CC\u0627\u0644": "\uFDFC"
20078           }
20079         };
20080
20081         unicodeLigatures["default"] = ligatureReference;
20082
20083         Object.defineProperty(reference, "__esModule", {
20084           value: true
20085         });
20086         var unicode_arabic_1$3 = unicodeArabic;
20087         var unicode_ligatures_1$2 = unicodeLigatures;
20088         var letterList = Object.keys(unicode_arabic_1$3["default"]);
20089         reference.letterList = letterList;
20090         var ligatureList = Object.keys(unicode_ligatures_1$2["default"]);
20091         reference.ligatureList = ligatureList;
20092         var ligatureWordList = Object.keys(unicode_ligatures_1$2["default"].words);
20093         reference.ligatureWordList = ligatureWordList;
20094         var lams = "\u0644\u06B5\u06B6\u06B7\u06B8";
20095         reference.lams = lams;
20096         var alefs = "\u0627\u0622\u0623\u0625\u0671\u0672\u0673\u0675\u0773\u0774";
20097         reference.alefs = alefs; // for (var l = 1; l < lams.length; l++) {
20098         //   console.log('-');
20099         //   for (var a = 0; a < alefs.length; a++) {
20100         //     console.log(a + ': ' + lams[l] + alefs[a]);
20101         //   }
20102         // }
20103
20104         var tashkeel = "\u0605\u0640\u0670\u0674\u06DF\u06E7\u06E8";
20105         reference.tashkeel = tashkeel;
20106
20107         function addToTashkeel(start, finish) {
20108           for (var i = start; i <= finish; i++) {
20109             reference.tashkeel = tashkeel += String.fromCharCode(i);
20110           }
20111         }
20112
20113         addToTashkeel(0x0610, 0x061A);
20114         addToTashkeel(0x064B, 0x065F);
20115         addToTashkeel(0x06D6, 0x06DC);
20116         addToTashkeel(0x06E0, 0x06E4);
20117         addToTashkeel(0x06EA, 0x06ED);
20118         addToTashkeel(0x08D3, 0x08E1);
20119         addToTashkeel(0x08E3, 0x08FF);
20120         addToTashkeel(0xFE70, 0xFE7F);
20121         var lineBreakers = "\u0627\u0629\u0648\u06C0\u06CF\u06FD\u06FE\u076B\u076C\u0771\u0773\u0774\u0778\u0779\u08E2\u08B1\u08B2\u08B9";
20122         reference.lineBreakers = lineBreakers;
20123
20124         function addToLineBreakers(start, finish) {
20125           for (var i = start; i <= finish; i++) {
20126             reference.lineBreakers = lineBreakers += String.fromCharCode(i);
20127           }
20128         }
20129
20130         addToLineBreakers(0x0600, 0x061F); // it's OK to include tashkeel in this range as it is ignored
20131
20132         addToLineBreakers(0x0621, 0x0625);
20133         addToLineBreakers(0x062F, 0x0632);
20134         addToLineBreakers(0x0660, 0x066D); // numerals, math
20135
20136         addToLineBreakers(0x0671, 0x0677);
20137         addToLineBreakers(0x0688, 0x0699);
20138         addToLineBreakers(0x06C3, 0x06CB);
20139         addToLineBreakers(0x06D2, 0x06F9);
20140         addToLineBreakers(0x0759, 0x075B);
20141         addToLineBreakers(0x08AA, 0x08AE);
20142         addToLineBreakers(0xFB50, 0xFDFD); // presentation forms look like they could connect, but never do
20143         // Presentation Forms A includes diacritics but they are meant to stand alone
20144
20145         addToLineBreakers(0xFE80, 0xFEFC); // presentation forms look like they could connect, but never do
20146         // numerals, math
20147
20148         addToLineBreakers(0x10E60, 0x10E7F);
20149         addToLineBreakers(0x1EC70, 0x1ECBF);
20150         addToLineBreakers(0x1EE00, 0x1EEFF);
20151
20152         Object.defineProperty(GlyphSplitter$1, "__esModule", {
20153           value: true
20154         });
20155         var isArabic_1$6 = isArabic$1;
20156         var reference_1$5 = reference;
20157
20158         function GlyphSplitter(word) {
20159           var letters = [];
20160           var lastLetter = '';
20161           word.split('').forEach(function (letter) {
20162             if (isArabic_1$6.isArabic(letter)) {
20163               if (reference_1$5.tashkeel.indexOf(letter) > -1) {
20164                 letters[letters.length - 1] += letter;
20165               } else if (lastLetter.length && (reference_1$5.lams.indexOf(lastLetter) === 0 && reference_1$5.alefs.indexOf(letter) > -1 || reference_1$5.lams.indexOf(lastLetter) > 0 && reference_1$5.alefs.indexOf(letter) === 0)) {
20166                 // valid LA forms
20167                 letters[letters.length - 1] += letter;
20168               } else {
20169                 letters.push(letter);
20170               }
20171             } else {
20172               letters.push(letter);
20173             }
20174
20175             if (reference_1$5.tashkeel.indexOf(letter) === -1) {
20176               lastLetter = letter;
20177             }
20178           });
20179           return letters;
20180         }
20181
20182         GlyphSplitter$1.GlyphSplitter = GlyphSplitter;
20183
20184         var BaselineSplitter$1 = {};
20185
20186         Object.defineProperty(BaselineSplitter$1, "__esModule", {
20187           value: true
20188         });
20189         var isArabic_1$5 = isArabic$1;
20190         var reference_1$4 = reference;
20191
20192         function BaselineSplitter(word) {
20193           var letters = [];
20194           var lastLetter = '';
20195           word.split('').forEach(function (letter) {
20196             if (isArabic_1$5.isArabic(letter) && isArabic_1$5.isArabic(lastLetter)) {
20197               if (lastLetter.length && reference_1$4.tashkeel.indexOf(letter) > -1) {
20198                 letters[letters.length - 1] += letter;
20199               } else if (reference_1$4.lineBreakers.indexOf(lastLetter) > -1) {
20200                 letters.push(letter);
20201               } else {
20202                 letters[letters.length - 1] += letter;
20203               }
20204             } else {
20205               letters.push(letter);
20206             }
20207
20208             if (reference_1$4.tashkeel.indexOf(letter) === -1) {
20209               // don't allow tashkeel to hide line break
20210               lastLetter = letter;
20211             }
20212           });
20213           return letters;
20214         }
20215
20216         BaselineSplitter$1.BaselineSplitter = BaselineSplitter;
20217
20218         var Normalization = {};
20219
20220         Object.defineProperty(Normalization, "__esModule", {
20221           value: true
20222         });
20223         var unicode_arabic_1$2 = unicodeArabic;
20224         var unicode_ligatures_1$1 = unicodeLigatures;
20225         var isArabic_1$4 = isArabic$1;
20226         var reference_1$3 = reference;
20227
20228         function Normal(word, breakPresentationForm) {
20229           // default is to turn initial/isolated/medial/final presentation form to generic
20230           if (typeof breakPresentationForm === 'undefined') {
20231             breakPresentationForm = true;
20232           }
20233
20234           var returnable = '';
20235           word.split('').forEach(function (letter) {
20236             if (!isArabic_1$4.isArabic(letter)) {
20237               returnable += letter;
20238               return;
20239             }
20240
20241             for (var w = 0; w < reference_1$3.letterList.length; w++) {
20242               // ok so we are checking this potential lettertron
20243               var letterForms = unicode_arabic_1$2["default"][reference_1$3.letterList[w]];
20244               var versions = Object.keys(letterForms);
20245
20246               for (var v = 0; v < versions.length; v++) {
20247                 var localVersion = letterForms[versions[v]];
20248
20249                 if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20250                   // look at this embedded object
20251                   var embeddedForms = Object.keys(localVersion);
20252
20253                   for (var ef = 0; ef < embeddedForms.length; ef++) {
20254                     var form = localVersion[embeddedForms[ef]];
20255
20256                     if (form === letter || _typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20257                       // match
20258                       // console.log('embedded match');
20259                       if (form === letter) {
20260                         // match exact
20261                         if (breakPresentationForm && localVersion['normal'] && ['isolated', 'initial', 'medial', 'final'].indexOf(embeddedForms[ef]) > -1) {
20262                           // replace presentation form
20263                           // console.log('keeping normal form of the letter');
20264                           if (_typeof(localVersion['normal']) === 'object') {
20265                             returnable += localVersion['normal'][0];
20266                           } else {
20267                             returnable += localVersion['normal'];
20268                           }
20269
20270                           return;
20271                         } // console.log('keeping this letter');
20272
20273
20274                         returnable += letter;
20275                         return;
20276                       } else if (_typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20277                         // match
20278                         returnable += form[0]; // console.log('added the first letter from the same array');
20279
20280                         return;
20281                       }
20282                     }
20283                   }
20284                 } else if (localVersion === letter) {
20285                   // match exact
20286                   if (breakPresentationForm && letterForms['normal'] && ['isolated', 'initial', 'medial', 'final'].indexOf(versions[v]) > -1) {
20287                     // replace presentation form
20288                     // console.log('keeping normal form of the letter');
20289                     if (_typeof(letterForms['normal']) === 'object') {
20290                       returnable += letterForms['normal'][0];
20291                     } else {
20292                       returnable += letterForms['normal'];
20293                     }
20294
20295                     return;
20296                   } // console.log('keeping this letter');
20297
20298
20299                   returnable += letter;
20300                   return;
20301                 } else if (_typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20302                   // match
20303                   returnable += localVersion[0]; // console.log('added the first letter from the same array');
20304
20305                   return;
20306                 }
20307               }
20308             } // try ligatures
20309
20310
20311             for (var v2 = 0; v2 < reference_1$3.ligatureList.length; v2++) {
20312               var normalForm = reference_1$3.ligatureList[v2];
20313
20314               if (normalForm !== 'words') {
20315                 var ligForms = Object.keys(unicode_ligatures_1$1["default"][normalForm]);
20316
20317                 for (var f = 0; f < ligForms.length; f++) {
20318                   if (unicode_ligatures_1$1["default"][normalForm][ligForms[f]] === letter) {
20319                     returnable += normalForm;
20320                     return;
20321                   }
20322                 }
20323               }
20324             } // try words ligatures
20325
20326
20327             for (var v3 = 0; v3 < reference_1$3.ligatureWordList.length; v3++) {
20328               var _normalForm = reference_1$3.ligatureWordList[v3];
20329
20330               if (unicode_ligatures_1$1["default"].words[_normalForm] === letter) {
20331                 returnable += _normalForm;
20332                 return;
20333               }
20334             }
20335
20336             returnable += letter; // console.log('kept the letter')
20337           });
20338           return returnable;
20339         }
20340
20341         Normalization.Normal = Normal;
20342
20343         var CharShaper$1 = {};
20344
20345         Object.defineProperty(CharShaper$1, "__esModule", {
20346           value: true
20347         });
20348         var unicode_arabic_1$1 = unicodeArabic;
20349         var isArabic_1$3 = isArabic$1;
20350         var reference_1$2 = reference;
20351
20352         function CharShaper(letter, form) {
20353           if (!isArabic_1$3.isArabic(letter)) {
20354             // fail not Arabic
20355             throw new Error('Not Arabic');
20356           }
20357
20358           if (letter === "\u0621") {
20359             // hamza alone
20360             return "\u0621";
20361           }
20362
20363           for (var w = 0; w < reference_1$2.letterList.length; w++) {
20364             // ok so we are checking this potential lettertron
20365             var letterForms = unicode_arabic_1$1["default"][reference_1$2.letterList[w]];
20366             var versions = Object.keys(letterForms);
20367
20368             for (var v = 0; v < versions.length; v++) {
20369               var localVersion = letterForms[versions[v]];
20370
20371               if (localVersion === letter || _typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20372                 if (versions.indexOf(form) > -1) {
20373                   return letterForms[form];
20374                 }
20375               } else if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20376                 // check embedded
20377                 var embeddedVersions = Object.keys(localVersion);
20378
20379                 for (var ev = 0; ev < embeddedVersions.length; ev++) {
20380                   if (localVersion[embeddedVersions[ev]] === letter || _typeof(localVersion[embeddedVersions[ev]]) === 'object' && localVersion[embeddedVersions[ev]].indexOf && localVersion[embeddedVersions[ev]].indexOf(letter) > -1) {
20381                     if (embeddedVersions.indexOf(form) > -1) {
20382                       return localVersion[form];
20383                     }
20384                   }
20385                 }
20386               }
20387             }
20388           }
20389         }
20390
20391         CharShaper$1.CharShaper = CharShaper;
20392
20393         var WordShaper$2 = {};
20394
20395         Object.defineProperty(WordShaper$2, "__esModule", {
20396           value: true
20397         });
20398         var isArabic_1$2 = isArabic$1;
20399         var reference_1$1 = reference;
20400         var CharShaper_1$1 = CharShaper$1;
20401         var unicode_ligatures_1 = unicodeLigatures;
20402
20403         function WordShaper$1(word) {
20404           var state = 'initial';
20405           var output = '';
20406
20407           for (var w = 0; w < word.length; w++) {
20408             var nextLetter = ' ';
20409
20410             for (var nxw = w + 1; nxw < word.length; nxw++) {
20411               if (!isArabic_1$2.isArabic(word[nxw])) {
20412                 break;
20413               }
20414
20415               if (reference_1$1.tashkeel.indexOf(word[nxw]) === -1) {
20416                 nextLetter = word[nxw];
20417                 break;
20418               }
20419             }
20420
20421             if (!isArabic_1$2.isArabic(word[w]) || isArabic_1$2.isMath(word[w])) {
20422               // space or other non-Arabic
20423               output += word[w];
20424               state = 'initial';
20425             } else if (reference_1$1.tashkeel.indexOf(word[w]) > -1) {
20426               // tashkeel - add without changing state
20427               output += word[w];
20428             } else if (nextLetter === ' ' // last Arabic letter in this word
20429             || reference_1$1.lineBreakers.indexOf(word[w]) > -1) {
20430               // the current letter is known to break lines
20431               output += CharShaper_1$1.CharShaper(word[w], state === 'initial' ? 'isolated' : 'final');
20432               state = 'initial';
20433             } else if (reference_1$1.lams.indexOf(word[w]) > -1 && reference_1$1.alefs.indexOf(nextLetter) > -1) {
20434               // LA letters - advance an additional letter after this
20435               output += unicode_ligatures_1["default"][word[w] + nextLetter][state === 'initial' ? 'isolated' : 'final'];
20436
20437               while (word[w] !== nextLetter) {
20438                 w++;
20439               }
20440
20441               state = 'initial';
20442             } else {
20443               output += CharShaper_1$1.CharShaper(word[w], state);
20444               state = 'medial';
20445             }
20446           }
20447
20448           return output;
20449         }
20450
20451         WordShaper$2.WordShaper = WordShaper$1;
20452
20453         var ParentLetter$1 = {};
20454
20455         Object.defineProperty(ParentLetter$1, "__esModule", {
20456           value: true
20457         });
20458         var unicode_arabic_1 = unicodeArabic;
20459         var isArabic_1$1 = isArabic$1;
20460         var reference_1 = reference;
20461
20462         function ParentLetter(letter) {
20463           if (!isArabic_1$1.isArabic(letter)) {
20464             throw new Error('Not an Arabic letter');
20465           }
20466
20467           for (var w = 0; w < reference_1.letterList.length; w++) {
20468             // ok so we are checking this potential lettertron
20469             var letterForms = unicode_arabic_1["default"][reference_1.letterList[w]];
20470             var versions = Object.keys(letterForms);
20471
20472             for (var v = 0; v < versions.length; v++) {
20473               var localVersion = letterForms[versions[v]];
20474
20475               if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20476                 // look at this embedded object
20477                 var embeddedForms = Object.keys(localVersion);
20478
20479                 for (var ef = 0; ef < embeddedForms.length; ef++) {
20480                   var form = localVersion[embeddedForms[ef]];
20481
20482                   if (form === letter || _typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20483                     // match
20484                     return localVersion;
20485                   }
20486                 }
20487               } else if (localVersion === letter || _typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20488                 // match
20489                 return letterForms;
20490               }
20491             }
20492
20493             return null;
20494           }
20495         }
20496
20497         ParentLetter$1.ParentLetter = ParentLetter;
20498
20499         function GrandparentLetter(letter) {
20500           if (!isArabic_1$1.isArabic(letter)) {
20501             throw new Error('Not an Arabic letter');
20502           }
20503
20504           for (var w = 0; w < reference_1.letterList.length; w++) {
20505             // ok so we are checking this potential lettertron
20506             var letterForms = unicode_arabic_1["default"][reference_1.letterList[w]];
20507             var versions = Object.keys(letterForms);
20508
20509             for (var v = 0; v < versions.length; v++) {
20510               var localVersion = letterForms[versions[v]];
20511
20512               if (_typeof(localVersion) === 'object' && typeof localVersion.indexOf === 'undefined') {
20513                 // look at this embedded object
20514                 var embeddedForms = Object.keys(localVersion);
20515
20516                 for (var ef = 0; ef < embeddedForms.length; ef++) {
20517                   var form = localVersion[embeddedForms[ef]];
20518
20519                   if (form === letter || _typeof(form) === 'object' && form.indexOf && form.indexOf(letter) > -1) {
20520                     // match
20521                     return letterForms;
20522                   }
20523                 }
20524               } else if (localVersion === letter || _typeof(localVersion) === 'object' && localVersion.indexOf && localVersion.indexOf(letter) > -1) {
20525                 // match
20526                 return letterForms;
20527               }
20528             }
20529
20530             return null;
20531           }
20532         }
20533
20534         ParentLetter$1.GrandparentLetter = GrandparentLetter;
20535
20536         Object.defineProperty(lib, "__esModule", {
20537           value: true
20538         });
20539         var isArabic_1 = isArabic$1;
20540         lib.isArabic = isArabic_1.isArabic;
20541         var GlyphSplitter_1 = GlyphSplitter$1;
20542         lib.GlyphSplitter = GlyphSplitter_1.GlyphSplitter;
20543         var BaselineSplitter_1 = BaselineSplitter$1;
20544         lib.BaselineSplitter = BaselineSplitter_1.BaselineSplitter;
20545         var Normalization_1 = Normalization;
20546         lib.Normal = Normalization_1.Normal;
20547         var CharShaper_1 = CharShaper$1;
20548         lib.CharShaper = CharShaper_1.CharShaper;
20549         var WordShaper_1 = WordShaper$2;
20550         var WordShaper = lib.WordShaper = WordShaper_1.WordShaper;
20551         var ParentLetter_1 = ParentLetter$1;
20552         lib.ParentLetter = ParentLetter_1.ParentLetter;
20553         lib.GrandparentLetter = ParentLetter_1.GrandparentLetter;
20554
20555         var rtlRegex = /[\u0590-\u05FF\u0600-\u06FF\u0750-\u07BF\u08A0–\u08BF]/;
20556         function fixRTLTextForSvg(inputText) {
20557           var ret = '',
20558               rtlBuffer = [];
20559           var arabicRegex = /[\u0600-\u06FF]/g;
20560           var arabicDiacritics = /[\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06ED]/g;
20561           var arabicMath = /[\u0660-\u066C\u06F0-\u06F9]+/g;
20562           var thaanaVowel = /[\u07A6-\u07B0]/;
20563           var hebrewSign = /[\u0591-\u05bd\u05bf\u05c1-\u05c5\u05c7]/; // Arabic word shaping
20564
20565           if (arabicRegex.test(inputText)) {
20566             inputText = WordShaper(inputText);
20567           }
20568
20569           for (var n = 0; n < inputText.length; n++) {
20570             var c = inputText[n];
20571
20572             if (arabicMath.test(c)) {
20573               // Arabic numbers go LTR
20574               ret += rtlBuffer.reverse().join('');
20575               rtlBuffer = [c];
20576             } else {
20577               if (rtlBuffer.length && arabicMath.test(rtlBuffer[rtlBuffer.length - 1])) {
20578                 ret += rtlBuffer.reverse().join('');
20579                 rtlBuffer = [];
20580               }
20581
20582               if ((thaanaVowel.test(c) || hebrewSign.test(c) || arabicDiacritics.test(c)) && rtlBuffer.length) {
20583                 rtlBuffer[rtlBuffer.length - 1] += c;
20584               } else if (rtlRegex.test(c) // include Arabic presentation forms
20585               || c.charCodeAt(0) >= 64336 && c.charCodeAt(0) <= 65023 || c.charCodeAt(0) >= 65136 && c.charCodeAt(0) <= 65279) {
20586                 rtlBuffer.push(c);
20587               } else if (c === ' ' && rtlBuffer.length) {
20588                 // whitespace within RTL text
20589                 rtlBuffer = [rtlBuffer.reverse().join('') + ' '];
20590               } else {
20591                 // non-RTL character
20592                 ret += rtlBuffer.reverse().join('') + c;
20593                 rtlBuffer = [];
20594               }
20595             }
20596           }
20597
20598           ret += rtlBuffer.reverse().join('');
20599           return ret;
20600         }
20601
20602         var DESCRIPTORS$2 = descriptors;
20603         var uncurryThis$b = functionUncurryThis;
20604         var objectKeys = objectKeys$4;
20605         var toIndexedObject = toIndexedObject$d;
20606         var $propertyIsEnumerable = objectPropertyIsEnumerable.f;
20607
20608         var propertyIsEnumerable = uncurryThis$b($propertyIsEnumerable);
20609         var push$2 = uncurryThis$b([].push);
20610
20611         // `Object.{ entries, values }` methods implementation
20612         var createMethod$1 = function (TO_ENTRIES) {
20613           return function (it) {
20614             var O = toIndexedObject(it);
20615             var keys = objectKeys(O);
20616             var length = keys.length;
20617             var i = 0;
20618             var result = [];
20619             var key;
20620             while (length > i) {
20621               key = keys[i++];
20622               if (!DESCRIPTORS$2 || propertyIsEnumerable(O, key)) {
20623                 push$2(result, TO_ENTRIES ? [key, O[key]] : O[key]);
20624               }
20625             }
20626             return result;
20627           };
20628         };
20629
20630         var objectToArray = {
20631           // `Object.entries` method
20632           // https://tc39.es/ecma262/#sec-object.entries
20633           entries: createMethod$1(true),
20634           // `Object.values` method
20635           // https://tc39.es/ecma262/#sec-object.values
20636           values: createMethod$1(false)
20637         };
20638
20639         var $$r = _export;
20640         var $values = objectToArray.values;
20641
20642         // `Object.values` method
20643         // https://tc39.es/ecma262/#sec-object.values
20644         $$r({ target: 'Object', stat: true }, {
20645           values: function values(O) {
20646             return $values(O);
20647           }
20648         });
20649
20650         // https://github.com/openstreetmap/iD/issues/772
20651         // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
20652         var _storage;
20653
20654         try {
20655           _storage = localStorage;
20656         } catch (e) {} // eslint-disable-line no-empty
20657
20658
20659         _storage = _storage || function () {
20660           var s = {};
20661           return {
20662             getItem: function getItem(k) {
20663               return s[k];
20664             },
20665             setItem: function setItem(k, v) {
20666               return s[k] = v;
20667             },
20668             removeItem: function removeItem(k) {
20669               return delete s[k];
20670             }
20671           };
20672         }();
20673
20674         var _listeners = {}; //
20675         // corePreferences is an interface for persisting basic key-value strings
20676         // within and between iD sessions on the same site.
20677         //
20678
20679         /**
20680          * @param {string} k
20681          * @param {string?} v
20682          * @returns {boolean} true if the action succeeded
20683          */
20684
20685         function corePreferences(k, v) {
20686           try {
20687             if (v === undefined) return _storage.getItem(k);else if (v === null) _storage.removeItem(k);else _storage.setItem(k, v);
20688
20689             if (_listeners[k]) {
20690               _listeners[k].forEach(function (handler) {
20691                 return handler(v);
20692               });
20693             }
20694
20695             return true;
20696           } catch (e) {
20697             /* eslint-disable no-console */
20698             if (typeof console !== 'undefined') {
20699               console.error('localStorage quota exceeded');
20700             }
20701             /* eslint-enable no-console */
20702
20703
20704             return false;
20705           }
20706         } // adds an event listener which is triggered whenever
20707
20708
20709         corePreferences.onChange = function (k, handler) {
20710           _listeners[k] = _listeners[k] || [];
20711
20712           _listeners[k].push(handler);
20713         };
20714
20715         var vparse = {exports: {}};
20716
20717         (function (module) {
20718           (function (window) {
20719
20720             function parseVersion(v) {
20721               var m = v.replace(/[^0-9.]/g, '').match(/[0-9]*\.|[0-9]+/g) || [];
20722               v = {
20723                 major: +m[0] || 0,
20724                 minor: +m[1] || 0,
20725                 patch: +m[2] || 0,
20726                 build: +m[3] || 0
20727               };
20728               v.isEmpty = !v.major && !v.minor && !v.patch && !v.build;
20729               v.parsed = [v.major, v.minor, v.patch, v.build];
20730               v.text = v.parsed.join('.');
20731               v.compare = compare;
20732               return v;
20733             }
20734
20735             function compare(v) {
20736               if (typeof v === 'string') {
20737                 v = parseVersion(v);
20738               }
20739
20740               for (var i = 0; i < 4; i++) {
20741                 if (this.parsed[i] !== v.parsed[i]) {
20742                   return this.parsed[i] > v.parsed[i] ? 1 : -1;
20743                 }
20744               }
20745
20746               return 0;
20747             }
20748             /* istanbul ignore next */
20749
20750
20751             if (module && 'object' === 'object') {
20752               module.exports = parseVersion;
20753             } else {
20754               window.parseVersion = parseVersion;
20755             }
20756           })(commonjsGlobal);
20757         })(vparse);
20758
20759         var parseVersion = vparse.exports;
20760
20761         var name = "iD";
20762         var version = "2.20.4";
20763         var description = "A friendly editor for OpenStreetMap";
20764         var main = "dist/iD.min.js";
20765         var repository = "github:openstreetmap/iD";
20766         var homepage = "https://github.com/openstreetmap/iD";
20767         var bugs = "https://github.com/openstreetmap/iD/issues";
20768         var keywords = ["editor","openstreetmap"];
20769         var license = "ISC";
20770         var scripts = {all:"npm-run-all -s clean build build:legacy dist",build:"npm-run-all -s build:css build:data build:dev","build:css":"node scripts/build_css.js","build:data":"shx mkdir -p dist/data && node scripts/build_data.js","build:dev":"rollup --config config/rollup.config.dev.js","build:legacy":"rollup --config config/rollup.config.legacy.js","build:stats":"rollup --config config/rollup.config.stats.js",clean:"shx rm -f dist/*.js dist/*.map dist/*.css dist/img/*.svg",dist:"npm-run-all -p dist:**","dist:mapillary":"shx mkdir -p dist/mapillary-js && shx cp -R node_modules/mapillary-js/dist/* dist/mapillary-js/","dist:pannellum":"shx mkdir -p dist/pannellum-streetside && shx cp -R node_modules/pannellum/build/* dist/pannellum-streetside/","dist:min:iD":"uglifyjs dist/iD.legacy.js --compress --mangle --output dist/iD.min.js","dist:svg:iD":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"iD-%s\" --symbol-sprite dist/img/iD-sprite.svg \"svg/iD-sprite/**/*.svg\"","dist:svg:community":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"community-%s\" --symbol-sprite dist/img/community-sprite.svg node_modules/osm-community-index/dist/img/*.svg","dist:svg:fa":"svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/fa-sprite.svg svg/fontawesome/*.svg","dist:svg:maki":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"maki-%s\" --symbol-sprite dist/img/maki-sprite.svg node_modules/@mapbox/maki/icons/*.svg","dist:svg:mapillary:signs":"svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/mapillary-sprite.svg node_modules/mapillary_sprite_source/package_signs/*.svg","dist:svg:mapillary:objects":"svg-sprite --symbol --symbol-dest . --symbol-sprite dist/img/mapillary-object-sprite.svg node_modules/mapillary_sprite_source/package_objects/*.svg","dist:svg:temaki":"svg-sprite --symbol --symbol-dest . --shape-id-generator \"temaki-%s\" --symbol-sprite dist/img/temaki-sprite.svg node_modules/@ideditor/temaki/icons/*.svg",imagery:"node scripts/update_imagery.js",lint:"eslint scripts test/spec modules","lint:fix":"eslint scripts test/spec modules --fix",start:"npm-run-all -s build start:server",quickstart:"npm-run-all -s build:dev start:server","start:server":"node scripts/server.js",test:"npm-run-all -s lint build test:spec","test:spec":"karma start karma.conf.js",translations:"node scripts/update_locales.js"};
20771         var dependencies = {"@ideditor/country-coder":"~5.0.3","@ideditor/location-conflation":"~1.0.2","@mapbox/geojson-area":"^0.2.2","@mapbox/sexagesimal":"1.2.0","@mapbox/vector-tile":"^1.3.1","@tmcw/togeojson":"^4.5.0","@turf/bbox-clip":"^6.0.0","abortcontroller-polyfill":"^1.4.0","aes-js":"^3.1.2","alif-toolkit":"^1.2.9","core-js":"^3.6.5",diacritics:"1.3.0","fast-deep-equal":"~3.1.1","fast-json-stable-stringify":"2.1.0","lodash-es":"~4.17.15",marked:"~2.0.0","node-diff3":"2.1.0","osm-auth":"1.1.0",pannellum:"2.5.6",pbf:"^3.2.1","polygon-clipping":"~0.15.1",rbush:"3.0.1","whatwg-fetch":"^3.4.1","which-polygon":"2.2.0"};
20772         var devDependencies = {"@babel/core":"^7.11.6","@babel/preset-env":"^7.11.5","@fortawesome/fontawesome-svg-core":"^1.2.32","@fortawesome/free-brands-svg-icons":"~5.15.1","@fortawesome/free-regular-svg-icons":"~5.15.1","@fortawesome/free-solid-svg-icons":"~5.15.1","@ideditor/temaki":"~5.0.0","@mapbox/maki":"^6.0.0","@rollup/plugin-babel":"^5.2.1","@rollup/plugin-commonjs":"^21.0.0","@rollup/plugin-json":"^4.0.1","@rollup/plugin-node-resolve":"~13.0.5",autoprefixer:"^10.0.1",btoa:"^1.2.1",chai:"^4.3.4","cldr-core":"37.0.0","cldr-localenames-full":"37.0.0",chalk:"^4.1.2","concat-files":"^0.1.1",d3:"~6.6.0","editor-layer-index":"github:osmlab/editor-layer-index#gh-pages",eslint:"^7.1.0","fetch-mock":"^9.11.0",gaze:"^1.1.3",glob:"^7.1.0",happen:"^0.3.2","js-yaml":"^4.0.0","json-stringify-pretty-compact":"^3.0.0",karma:"^6.3.5","karma-chrome-launcher":"^3.1.0","karma-coverage":"^2.0.3","karma-mocha":"^2.0.1","karma-remap-istanbul":"^0.6.0",mapillary_sprite_source:"^1.8.0","mapillary-js":"4.0.0",minimist:"^1.2.3",mocha:"^8.4.0","name-suggestion-index":"~6.0","node-fetch":"^2.6.1","npm-run-all":"^4.0.0","object-inspect":"1.10.3","osm-community-index":"~5.1.0",postcss:"^8.1.1","postcss-selector-prepend":"^0.5.0",rollup:"~2.52.8","rollup-plugin-includepaths":"~0.2.3","rollup-plugin-progress":"^1.1.1","rollup-plugin-visualizer":"~4.2.0",shelljs:"^0.8.0",shx:"^0.3.0",sinon:"^11.1.2","sinon-chai":"^3.7.0",smash:"0.0","static-server":"^2.2.1","svg-sprite":"1.5.1","uglify-js":"~3.13.0",vparse:"~1.1.0"};
20773         var engines = {node:">=10"};
20774         var browserslist = ["> 0.2%, last 6 major versions, Firefox ESR, IE 11, maintained node versions"];
20775         var packageJSON = {
20776         name: name,
20777         version: version,
20778         description: description,
20779         main: main,
20780         repository: repository,
20781         homepage: homepage,
20782         bugs: bugs,
20783         keywords: keywords,
20784         license: license,
20785         scripts: scripts,
20786         dependencies: dependencies,
20787         devDependencies: devDependencies,
20788         engines: engines,
20789         browserslist: browserslist
20790         };
20791
20792         var _mainFileFetcher = coreFileFetcher(); // singleton
20793         // coreFileFetcher asynchronously fetches data from JSON files
20794         //
20795
20796         function coreFileFetcher() {
20797           var ociVersion = packageJSON.devDependencies['osm-community-index'];
20798           var v = parseVersion(ociVersion);
20799           var vMinor = "".concat(v.major, ".").concat(v.minor);
20800           var _this = {};
20801           var _inflight = {};
20802           var _fileMap = {
20803             'address_formats': 'data/address_formats.min.json',
20804             'deprecated': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/deprecated.min.json',
20805             'discarded': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/discarded.min.json',
20806             'imagery': 'data/imagery.min.json',
20807             'intro_graph': 'data/intro_graph.min.json',
20808             'keepRight': 'data/keepRight.min.json',
20809             'languages': 'data/languages.min.json',
20810             'locales': 'locales/index.min.json',
20811             'oci_defaults': "https://cdn.jsdelivr.net/npm/osm-community-index@".concat(vMinor, "/dist/defaults.min.json"),
20812             'oci_features': "https://cdn.jsdelivr.net/npm/osm-community-index@".concat(vMinor, "/dist/featureCollection.min.json"),
20813             'oci_resources': "https://cdn.jsdelivr.net/npm/osm-community-index@".concat(vMinor, "/dist/resources.min.json"),
20814             'preset_categories': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/preset_categories.min.json',
20815             'preset_defaults': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/preset_defaults.min.json',
20816             'preset_fields': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/fields.min.json',
20817             'preset_presets': 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/presets.min.json',
20818             'phone_formats': 'data/phone_formats.min.json',
20819             'qa_data': 'data/qa_data.min.json',
20820             'shortcuts': 'data/shortcuts.min.json',
20821             'territory_languages': 'data/territory_languages.min.json',
20822             'wmf_sitematrix': 'https://cdn.jsdelivr.net/npm/wmf-sitematrix@0.1/wikipedia.min.json'
20823           };
20824           var _cachedData = {}; // expose the cache; useful for tests
20825
20826           _this.cache = function () {
20827             return _cachedData;
20828           }; // Returns a Promise to fetch data
20829           // (resolved with the data if we have it already)
20830
20831
20832           _this.get = function (which) {
20833             if (_cachedData[which]) {
20834               return Promise.resolve(_cachedData[which]);
20835             }
20836
20837             var file = _fileMap[which];
20838
20839             var url = file && _this.asset(file);
20840
20841             if (!url) {
20842               return Promise.reject("Unknown data file for \"".concat(which, "\""));
20843             }
20844
20845             var prom = _inflight[url];
20846
20847             if (!prom) {
20848               _inflight[url] = prom = fetch(url).then(function (response) {
20849                 // fetch in PhantomJS tests may return ok=false and status=0 even if it's okay
20850                 if (!response.ok && response.status !== 0 || !response.json) {
20851                   throw new Error(response.status + ' ' + response.statusText);
20852                 }
20853
20854                 if (response.status === 204 || response.status === 205) return; // No Content, Reset Content
20855
20856                 return response.json();
20857               }).then(function (result) {
20858                 delete _inflight[url];
20859
20860                 if (!result) {
20861                   throw new Error("No data loaded for \"".concat(which, "\""));
20862                 }
20863
20864                 _cachedData[which] = result;
20865                 return result;
20866               })["catch"](function (err) {
20867                 delete _inflight[url];
20868                 throw err;
20869               });
20870             }
20871
20872             return prom;
20873           }; // Accessor for the file map
20874
20875
20876           _this.fileMap = function (val) {
20877             if (!arguments.length) return _fileMap;
20878             _fileMap = val;
20879             return _this;
20880           };
20881
20882           var _assetPath = '';
20883
20884           _this.assetPath = function (val) {
20885             if (!arguments.length) return _assetPath;
20886             _assetPath = val;
20887             return _this;
20888           };
20889
20890           var _assetMap = {};
20891
20892           _this.assetMap = function (val) {
20893             if (!arguments.length) return _assetMap;
20894             _assetMap = val;
20895             return _this;
20896           };
20897
20898           _this.asset = function (val) {
20899             if (/^http(s)?:\/\//i.test(val)) return val;
20900             var filename = _assetPath + val;
20901             return _assetMap[filename] || filename;
20902           };
20903
20904           return _this;
20905         }
20906
20907         var global$9 = global$1o;
20908         var toIntegerOrInfinity$1 = toIntegerOrInfinity$b;
20909         var toString$7 = toString$k;
20910         var requireObjectCoercible$6 = requireObjectCoercible$e;
20911
20912         var RangeError$5 = global$9.RangeError;
20913
20914         // `String.prototype.repeat` method implementation
20915         // https://tc39.es/ecma262/#sec-string.prototype.repeat
20916         var stringRepeat = function repeat(count) {
20917           var str = toString$7(requireObjectCoercible$6(this));
20918           var result = '';
20919           var n = toIntegerOrInfinity$1(count);
20920           if (n < 0 || n == Infinity) throw RangeError$5('Wrong number of repetitions');
20921           for (;n > 0; (n >>>= 1) && (str += str)) if (n & 1) result += str;
20922           return result;
20923         };
20924
20925         var $$q = _export;
20926         var global$8 = global$1o;
20927         var uncurryThis$a = functionUncurryThis;
20928         var toIntegerOrInfinity = toIntegerOrInfinity$b;
20929         var thisNumberValue$1 = thisNumberValue$3;
20930         var $repeat$1 = stringRepeat;
20931         var fails$7 = fails$V;
20932
20933         var RangeError$4 = global$8.RangeError;
20934         var String$1 = global$8.String;
20935         var floor$2 = Math.floor;
20936         var repeat$2 = uncurryThis$a($repeat$1);
20937         var stringSlice$3 = uncurryThis$a(''.slice);
20938         var un$ToFixed = uncurryThis$a(1.0.toFixed);
20939
20940         var pow$1 = function (x, n, acc) {
20941           return n === 0 ? acc : n % 2 === 1 ? pow$1(x, n - 1, acc * x) : pow$1(x * x, n / 2, acc);
20942         };
20943
20944         var log = function (x) {
20945           var n = 0;
20946           var x2 = x;
20947           while (x2 >= 4096) {
20948             n += 12;
20949             x2 /= 4096;
20950           }
20951           while (x2 >= 2) {
20952             n += 1;
20953             x2 /= 2;
20954           } return n;
20955         };
20956
20957         var multiply = function (data, n, c) {
20958           var index = -1;
20959           var c2 = c;
20960           while (++index < 6) {
20961             c2 += n * data[index];
20962             data[index] = c2 % 1e7;
20963             c2 = floor$2(c2 / 1e7);
20964           }
20965         };
20966
20967         var divide = function (data, n) {
20968           var index = 6;
20969           var c = 0;
20970           while (--index >= 0) {
20971             c += data[index];
20972             data[index] = floor$2(c / n);
20973             c = (c % n) * 1e7;
20974           }
20975         };
20976
20977         var dataToString = function (data) {
20978           var index = 6;
20979           var s = '';
20980           while (--index >= 0) {
20981             if (s !== '' || index === 0 || data[index] !== 0) {
20982               var t = String$1(data[index]);
20983               s = s === '' ? t : s + repeat$2('0', 7 - t.length) + t;
20984             }
20985           } return s;
20986         };
20987
20988         var FORCED$6 = fails$7(function () {
20989           return un$ToFixed(0.00008, 3) !== '0.000' ||
20990             un$ToFixed(0.9, 0) !== '1' ||
20991             un$ToFixed(1.255, 2) !== '1.25' ||
20992             un$ToFixed(1000000000000000128.0, 0) !== '1000000000000000128';
20993         }) || !fails$7(function () {
20994           // V8 ~ Android 4.3-
20995           un$ToFixed({});
20996         });
20997
20998         // `Number.prototype.toFixed` method
20999         // https://tc39.es/ecma262/#sec-number.prototype.tofixed
21000         $$q({ target: 'Number', proto: true, forced: FORCED$6 }, {
21001           toFixed: function toFixed(fractionDigits) {
21002             var number = thisNumberValue$1(this);
21003             var fractDigits = toIntegerOrInfinity(fractionDigits);
21004             var data = [0, 0, 0, 0, 0, 0];
21005             var sign = '';
21006             var result = '0';
21007             var e, z, j, k;
21008
21009             // TODO: ES2018 increased the maximum number of fraction digits to 100, need to improve the implementation
21010             if (fractDigits < 0 || fractDigits > 20) throw RangeError$4('Incorrect fraction digits');
21011             // eslint-disable-next-line no-self-compare -- NaN check
21012             if (number != number) return 'NaN';
21013             if (number <= -1e21 || number >= 1e21) return String$1(number);
21014             if (number < 0) {
21015               sign = '-';
21016               number = -number;
21017             }
21018             if (number > 1e-21) {
21019               e = log(number * pow$1(2, 69, 1)) - 69;
21020               z = e < 0 ? number * pow$1(2, -e, 1) : number / pow$1(2, e, 1);
21021               z *= 0x10000000000000;
21022               e = 52 - e;
21023               if (e > 0) {
21024                 multiply(data, 0, z);
21025                 j = fractDigits;
21026                 while (j >= 7) {
21027                   multiply(data, 1e7, 0);
21028                   j -= 7;
21029                 }
21030                 multiply(data, pow$1(10, j, 1), 0);
21031                 j = e - 1;
21032                 while (j >= 23) {
21033                   divide(data, 1 << 23);
21034                   j -= 23;
21035                 }
21036                 divide(data, 1 << j);
21037                 multiply(data, 1, 1);
21038                 divide(data, 2);
21039                 result = dataToString(data);
21040               } else {
21041                 multiply(data, 0, z);
21042                 multiply(data, 1 << -e, 0);
21043                 result = dataToString(data) + repeat$2('0', fractDigits);
21044               }
21045             }
21046             if (fractDigits > 0) {
21047               k = result.length;
21048               result = sign + (k <= fractDigits
21049                 ? '0.' + repeat$2('0', fractDigits - k) + result
21050                 : stringSlice$3(result, 0, k - fractDigits) + '.' + stringSlice$3(result, k - fractDigits));
21051             } else {
21052               result = sign + result;
21053             } return result;
21054           }
21055         });
21056
21057         var global$7 = global$1o;
21058
21059         var globalIsFinite = global$7.isFinite;
21060
21061         // `Number.isFinite` method
21062         // https://tc39.es/ecma262/#sec-number.isfinite
21063         // eslint-disable-next-line es/no-number-isfinite -- safe
21064         var numberIsFinite$1 = Number.isFinite || function isFinite(it) {
21065           return typeof it == 'number' && globalIsFinite(it);
21066         };
21067
21068         var $$p = _export;
21069         var numberIsFinite = numberIsFinite$1;
21070
21071         // `Number.isFinite` method
21072         // https://tc39.es/ecma262/#sec-number.isfinite
21073         $$p({ target: 'Number', stat: true }, { isFinite: numberIsFinite });
21074
21075         var $$o = _export;
21076         var global$6 = global$1o;
21077         var uncurryThis$9 = functionUncurryThis;
21078         var toAbsoluteIndex = toAbsoluteIndex$9;
21079
21080         var RangeError$3 = global$6.RangeError;
21081         var fromCharCode$1 = String.fromCharCode;
21082         // eslint-disable-next-line es/no-string-fromcodepoint -- required for testing
21083         var $fromCodePoint = String.fromCodePoint;
21084         var join$2 = uncurryThis$9([].join);
21085
21086         // length should be 1, old FF problem
21087         var INCORRECT_LENGTH = !!$fromCodePoint && $fromCodePoint.length != 1;
21088
21089         // `String.fromCodePoint` method
21090         // https://tc39.es/ecma262/#sec-string.fromcodepoint
21091         $$o({ target: 'String', stat: true, forced: INCORRECT_LENGTH }, {
21092           // eslint-disable-next-line no-unused-vars -- required for `.length`
21093           fromCodePoint: function fromCodePoint(x) {
21094             var elements = [];
21095             var length = arguments.length;
21096             var i = 0;
21097             var code;
21098             while (length > i) {
21099               code = +arguments[i++];
21100               if (toAbsoluteIndex(code, 0x10FFFF) !== code) throw RangeError$3(code + ' is not a valid code point');
21101               elements[i] = code < 0x10000
21102                 ? fromCharCode$1(code)
21103                 : fromCharCode$1(((code -= 0x10000) >> 10) + 0xD800, code % 0x400 + 0xDC00);
21104             } return join$2(elements, '');
21105           }
21106         });
21107
21108         var call$1 = functionCall;
21109         var fixRegExpWellKnownSymbolLogic = fixRegexpWellKnownSymbolLogic;
21110         var anObject = anObject$n;
21111         var requireObjectCoercible$5 = requireObjectCoercible$e;
21112         var sameValue = sameValue$1;
21113         var toString$6 = toString$k;
21114         var getMethod = getMethod$7;
21115         var regExpExec = regexpExecAbstract;
21116
21117         // @@search logic
21118         fixRegExpWellKnownSymbolLogic('search', function (SEARCH, nativeSearch, maybeCallNative) {
21119           return [
21120             // `String.prototype.search` method
21121             // https://tc39.es/ecma262/#sec-string.prototype.search
21122             function search(regexp) {
21123               var O = requireObjectCoercible$5(this);
21124               var searcher = regexp == undefined ? undefined : getMethod(regexp, SEARCH);
21125               return searcher ? call$1(searcher, regexp, O) : new RegExp(regexp)[SEARCH](toString$6(O));
21126             },
21127             // `RegExp.prototype[@@search]` method
21128             // https://tc39.es/ecma262/#sec-regexp.prototype-@@search
21129             function (string) {
21130               var rx = anObject(this);
21131               var S = toString$6(string);
21132               var res = maybeCallNative(nativeSearch, rx, S);
21133
21134               if (res.done) return res.value;
21135
21136               var previousLastIndex = rx.lastIndex;
21137               if (!sameValue(previousLastIndex, 0)) rx.lastIndex = 0;
21138               var result = regExpExec(rx, S);
21139               if (!sameValue(rx.lastIndex, previousLastIndex)) rx.lastIndex = previousLastIndex;
21140               return result === null ? -1 : result.index;
21141             }
21142           ];
21143         });
21144
21145         var rbush$2 = {exports: {}};
21146
21147         var quickselect$2 = {exports: {}};
21148
21149         (function (module, exports) {
21150           (function (global, factory) {
21151             module.exports = factory() ;
21152           })(commonjsGlobal, function () {
21153
21154             function quickselect(arr, k, left, right, compare) {
21155               quickselectStep(arr, k, left || 0, right || arr.length - 1, compare || defaultCompare);
21156             }
21157
21158             function quickselectStep(arr, k, left, right, compare) {
21159               while (right > left) {
21160                 if (right - left > 600) {
21161                   var n = right - left + 1;
21162                   var m = k - left + 1;
21163                   var z = Math.log(n);
21164                   var s = 0.5 * Math.exp(2 * z / 3);
21165                   var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
21166                   var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
21167                   var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
21168                   quickselectStep(arr, k, newLeft, newRight, compare);
21169                 }
21170
21171                 var t = arr[k];
21172                 var i = left;
21173                 var j = right;
21174                 swap(arr, left, k);
21175                 if (compare(arr[right], t) > 0) swap(arr, left, right);
21176
21177                 while (i < j) {
21178                   swap(arr, i, j);
21179                   i++;
21180                   j--;
21181
21182                   while (compare(arr[i], t) < 0) {
21183                     i++;
21184                   }
21185
21186                   while (compare(arr[j], t) > 0) {
21187                     j--;
21188                   }
21189                 }
21190
21191                 if (compare(arr[left], t) === 0) swap(arr, left, j);else {
21192                   j++;
21193                   swap(arr, j, right);
21194                 }
21195                 if (j <= k) left = j + 1;
21196                 if (k <= j) right = j - 1;
21197               }
21198             }
21199
21200             function swap(arr, i, j) {
21201               var tmp = arr[i];
21202               arr[i] = arr[j];
21203               arr[j] = tmp;
21204             }
21205
21206             function defaultCompare(a, b) {
21207               return a < b ? -1 : a > b ? 1 : 0;
21208             }
21209
21210             return quickselect;
21211           });
21212         })(quickselect$2);
21213
21214         rbush$2.exports = rbush$1;
21215
21216         rbush$2.exports["default"] = rbush$1;
21217
21218         var quickselect$1 = quickselect$2.exports;
21219
21220         function rbush$1(maxEntries, format) {
21221           if (!(this instanceof rbush$1)) return new rbush$1(maxEntries, format); // max entries in a node is 9 by default; min node fill is 40% for best performance
21222
21223           this._maxEntries = Math.max(4, maxEntries || 9);
21224           this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
21225
21226           if (format) {
21227             this._initFormat(format);
21228           }
21229
21230           this.clear();
21231         }
21232
21233         rbush$1.prototype = {
21234           all: function all() {
21235             return this._all(this.data, []);
21236           },
21237           search: function search(bbox) {
21238             var node = this.data,
21239                 result = [],
21240                 toBBox = this.toBBox;
21241             if (!intersects$1(bbox, node)) return result;
21242             var nodesToSearch = [],
21243                 i,
21244                 len,
21245                 child,
21246                 childBBox;
21247
21248             while (node) {
21249               for (i = 0, len = node.children.length; i < len; i++) {
21250                 child = node.children[i];
21251                 childBBox = node.leaf ? toBBox(child) : child;
21252
21253                 if (intersects$1(bbox, childBBox)) {
21254                   if (node.leaf) result.push(child);else if (contains$1(bbox, childBBox)) this._all(child, result);else nodesToSearch.push(child);
21255                 }
21256               }
21257
21258               node = nodesToSearch.pop();
21259             }
21260
21261             return result;
21262           },
21263           collides: function collides(bbox) {
21264             var node = this.data,
21265                 toBBox = this.toBBox;
21266             if (!intersects$1(bbox, node)) return false;
21267             var nodesToSearch = [],
21268                 i,
21269                 len,
21270                 child,
21271                 childBBox;
21272
21273             while (node) {
21274               for (i = 0, len = node.children.length; i < len; i++) {
21275                 child = node.children[i];
21276                 childBBox = node.leaf ? toBBox(child) : child;
21277
21278                 if (intersects$1(bbox, childBBox)) {
21279                   if (node.leaf || contains$1(bbox, childBBox)) return true;
21280                   nodesToSearch.push(child);
21281                 }
21282               }
21283
21284               node = nodesToSearch.pop();
21285             }
21286
21287             return false;
21288           },
21289           load: function load(data) {
21290             if (!(data && data.length)) return this;
21291
21292             if (data.length < this._minEntries) {
21293               for (var i = 0, len = data.length; i < len; i++) {
21294                 this.insert(data[i]);
21295               }
21296
21297               return this;
21298             } // recursively build the tree with the given data from scratch using OMT algorithm
21299
21300
21301             var node = this._build(data.slice(), 0, data.length - 1, 0);
21302
21303             if (!this.data.children.length) {
21304               // save as is if tree is empty
21305               this.data = node;
21306             } else if (this.data.height === node.height) {
21307               // split root if trees have the same height
21308               this._splitRoot(this.data, node);
21309             } else {
21310               if (this.data.height < node.height) {
21311                 // swap trees if inserted one is bigger
21312                 var tmpNode = this.data;
21313                 this.data = node;
21314                 node = tmpNode;
21315               } // insert the small tree into the large tree at appropriate level
21316
21317
21318               this._insert(node, this.data.height - node.height - 1, true);
21319             }
21320
21321             return this;
21322           },
21323           insert: function insert(item) {
21324             if (item) this._insert(item, this.data.height - 1);
21325             return this;
21326           },
21327           clear: function clear() {
21328             this.data = createNode$1([]);
21329             return this;
21330           },
21331           remove: function remove(item, equalsFn) {
21332             if (!item) return this;
21333             var node = this.data,
21334                 bbox = this.toBBox(item),
21335                 path = [],
21336                 indexes = [],
21337                 i,
21338                 parent,
21339                 index,
21340                 goingUp; // depth-first iterative tree traversal
21341
21342             while (node || path.length) {
21343               if (!node) {
21344                 // go up
21345                 node = path.pop();
21346                 parent = path[path.length - 1];
21347                 i = indexes.pop();
21348                 goingUp = true;
21349               }
21350
21351               if (node.leaf) {
21352                 // check current node
21353                 index = findItem$1(item, node.children, equalsFn);
21354
21355                 if (index !== -1) {
21356                   // item found, remove the item and condense tree upwards
21357                   node.children.splice(index, 1);
21358                   path.push(node);
21359
21360                   this._condense(path);
21361
21362                   return this;
21363                 }
21364               }
21365
21366               if (!goingUp && !node.leaf && contains$1(node, bbox)) {
21367                 // go down
21368                 path.push(node);
21369                 indexes.push(i);
21370                 i = 0;
21371                 parent = node;
21372                 node = node.children[0];
21373               } else if (parent) {
21374                 // go right
21375                 i++;
21376                 node = parent.children[i];
21377                 goingUp = false;
21378               } else node = null; // nothing found
21379
21380             }
21381
21382             return this;
21383           },
21384           toBBox: function toBBox(item) {
21385             return item;
21386           },
21387           compareMinX: compareNodeMinX$1,
21388           compareMinY: compareNodeMinY$1,
21389           toJSON: function toJSON() {
21390             return this.data;
21391           },
21392           fromJSON: function fromJSON(data) {
21393             this.data = data;
21394             return this;
21395           },
21396           _all: function _all(node, result) {
21397             var nodesToSearch = [];
21398
21399             while (node) {
21400               if (node.leaf) result.push.apply(result, node.children);else nodesToSearch.push.apply(nodesToSearch, node.children);
21401               node = nodesToSearch.pop();
21402             }
21403
21404             return result;
21405           },
21406           _build: function _build(items, left, right, height) {
21407             var N = right - left + 1,
21408                 M = this._maxEntries,
21409                 node;
21410
21411             if (N <= M) {
21412               // reached leaf level; return leaf
21413               node = createNode$1(items.slice(left, right + 1));
21414               calcBBox$1(node, this.toBBox);
21415               return node;
21416             }
21417
21418             if (!height) {
21419               // target height of the bulk-loaded tree
21420               height = Math.ceil(Math.log(N) / Math.log(M)); // target number of root entries to maximize storage utilization
21421
21422               M = Math.ceil(N / Math.pow(M, height - 1));
21423             }
21424
21425             node = createNode$1([]);
21426             node.leaf = false;
21427             node.height = height; // split the items into M mostly square tiles
21428
21429             var N2 = Math.ceil(N / M),
21430                 N1 = N2 * Math.ceil(Math.sqrt(M)),
21431                 i,
21432                 j,
21433                 right2,
21434                 right3;
21435             multiSelect$1(items, left, right, N1, this.compareMinX);
21436
21437             for (i = left; i <= right; i += N1) {
21438               right2 = Math.min(i + N1 - 1, right);
21439               multiSelect$1(items, i, right2, N2, this.compareMinY);
21440
21441               for (j = i; j <= right2; j += N2) {
21442                 right3 = Math.min(j + N2 - 1, right2); // pack each entry recursively
21443
21444                 node.children.push(this._build(items, j, right3, height - 1));
21445               }
21446             }
21447
21448             calcBBox$1(node, this.toBBox);
21449             return node;
21450           },
21451           _chooseSubtree: function _chooseSubtree(bbox, node, level, path) {
21452             var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
21453
21454             while (true) {
21455               path.push(node);
21456               if (node.leaf || path.length - 1 === level) break;
21457               minArea = minEnlargement = Infinity;
21458
21459               for (i = 0, len = node.children.length; i < len; i++) {
21460                 child = node.children[i];
21461                 area = bboxArea$1(child);
21462                 enlargement = enlargedArea$1(bbox, child) - area; // choose entry with the least area enlargement
21463
21464                 if (enlargement < minEnlargement) {
21465                   minEnlargement = enlargement;
21466                   minArea = area < minArea ? area : minArea;
21467                   targetNode = child;
21468                 } else if (enlargement === minEnlargement) {
21469                   // otherwise choose one with the smallest area
21470                   if (area < minArea) {
21471                     minArea = area;
21472                     targetNode = child;
21473                   }
21474                 }
21475               }
21476
21477               node = targetNode || node.children[0];
21478             }
21479
21480             return node;
21481           },
21482           _insert: function _insert(item, level, isNode) {
21483             var toBBox = this.toBBox,
21484                 bbox = isNode ? item : toBBox(item),
21485                 insertPath = []; // find the best node for accommodating the item, saving all nodes along the path too
21486
21487             var node = this._chooseSubtree(bbox, this.data, level, insertPath); // put the item into the node
21488
21489
21490             node.children.push(item);
21491             extend$2(node, bbox); // split on node overflow; propagate upwards if necessary
21492
21493             while (level >= 0) {
21494               if (insertPath[level].children.length > this._maxEntries) {
21495                 this._split(insertPath, level);
21496
21497                 level--;
21498               } else break;
21499             } // adjust bboxes along the insertion path
21500
21501
21502             this._adjustParentBBoxes(bbox, insertPath, level);
21503           },
21504           // split overflowed node into two
21505           _split: function _split(insertPath, level) {
21506             var node = insertPath[level],
21507                 M = node.children.length,
21508                 m = this._minEntries;
21509
21510             this._chooseSplitAxis(node, m, M);
21511
21512             var splitIndex = this._chooseSplitIndex(node, m, M);
21513
21514             var newNode = createNode$1(node.children.splice(splitIndex, node.children.length - splitIndex));
21515             newNode.height = node.height;
21516             newNode.leaf = node.leaf;
21517             calcBBox$1(node, this.toBBox);
21518             calcBBox$1(newNode, this.toBBox);
21519             if (level) insertPath[level - 1].children.push(newNode);else this._splitRoot(node, newNode);
21520           },
21521           _splitRoot: function _splitRoot(node, newNode) {
21522             // split root node
21523             this.data = createNode$1([node, newNode]);
21524             this.data.height = node.height + 1;
21525             this.data.leaf = false;
21526             calcBBox$1(this.data, this.toBBox);
21527           },
21528           _chooseSplitIndex: function _chooseSplitIndex(node, m, M) {
21529             var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
21530             minOverlap = minArea = Infinity;
21531
21532             for (i = m; i <= M - m; i++) {
21533               bbox1 = distBBox$1(node, 0, i, this.toBBox);
21534               bbox2 = distBBox$1(node, i, M, this.toBBox);
21535               overlap = intersectionArea$1(bbox1, bbox2);
21536               area = bboxArea$1(bbox1) + bboxArea$1(bbox2); // choose distribution with minimum overlap
21537
21538               if (overlap < minOverlap) {
21539                 minOverlap = overlap;
21540                 index = i;
21541                 minArea = area < minArea ? area : minArea;
21542               } else if (overlap === minOverlap) {
21543                 // otherwise choose distribution with minimum area
21544                 if (area < minArea) {
21545                   minArea = area;
21546                   index = i;
21547                 }
21548               }
21549             }
21550
21551             return index;
21552           },
21553           // sorts node children by the best axis for split
21554           _chooseSplitAxis: function _chooseSplitAxis(node, m, M) {
21555             var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX$1,
21556                 compareMinY = node.leaf ? this.compareMinY : compareNodeMinY$1,
21557                 xMargin = this._allDistMargin(node, m, M, compareMinX),
21558                 yMargin = this._allDistMargin(node, m, M, compareMinY); // if total distributions margin value is minimal for x, sort by minX,
21559             // otherwise it's already sorted by minY
21560
21561
21562             if (xMargin < yMargin) node.children.sort(compareMinX);
21563           },
21564           // total margin of all possible split distributions where each node is at least m full
21565           _allDistMargin: function _allDistMargin(node, m, M, compare) {
21566             node.children.sort(compare);
21567             var toBBox = this.toBBox,
21568                 leftBBox = distBBox$1(node, 0, m, toBBox),
21569                 rightBBox = distBBox$1(node, M - m, M, toBBox),
21570                 margin = bboxMargin$1(leftBBox) + bboxMargin$1(rightBBox),
21571                 i,
21572                 child;
21573
21574             for (i = m; i < M - m; i++) {
21575               child = node.children[i];
21576               extend$2(leftBBox, node.leaf ? toBBox(child) : child);
21577               margin += bboxMargin$1(leftBBox);
21578             }
21579
21580             for (i = M - m - 1; i >= m; i--) {
21581               child = node.children[i];
21582               extend$2(rightBBox, node.leaf ? toBBox(child) : child);
21583               margin += bboxMargin$1(rightBBox);
21584             }
21585
21586             return margin;
21587           },
21588           _adjustParentBBoxes: function _adjustParentBBoxes(bbox, path, level) {
21589             // adjust bboxes along the given tree path
21590             for (var i = level; i >= 0; i--) {
21591               extend$2(path[i], bbox);
21592             }
21593           },
21594           _condense: function _condense(path) {
21595             // go through the path, removing empty nodes and updating bboxes
21596             for (var i = path.length - 1, siblings; i >= 0; i--) {
21597               if (path[i].children.length === 0) {
21598                 if (i > 0) {
21599                   siblings = path[i - 1].children;
21600                   siblings.splice(siblings.indexOf(path[i]), 1);
21601                 } else this.clear();
21602               } else calcBBox$1(path[i], this.toBBox);
21603             }
21604           },
21605           _initFormat: function _initFormat(format) {
21606             // data format (minX, minY, maxX, maxY accessors)
21607             // uses eval-type function compilation instead of just accepting a toBBox function
21608             // because the algorithms are very sensitive to sorting functions performance,
21609             // so they should be dead simple and without inner calls
21610             var compareArr = ['return a', ' - b', ';'];
21611             this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
21612             this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
21613             this.toBBox = new Function('a', 'return {minX: a' + format[0] + ', minY: a' + format[1] + ', maxX: a' + format[2] + ', maxY: a' + format[3] + '};');
21614           }
21615         };
21616
21617         function findItem$1(item, items, equalsFn) {
21618           if (!equalsFn) return items.indexOf(item);
21619
21620           for (var i = 0; i < items.length; i++) {
21621             if (equalsFn(item, items[i])) return i;
21622           }
21623
21624           return -1;
21625         } // calculate node's bbox from bboxes of its children
21626
21627
21628         function calcBBox$1(node, toBBox) {
21629           distBBox$1(node, 0, node.children.length, toBBox, node);
21630         } // min bounding rectangle of node children from k to p-1
21631
21632
21633         function distBBox$1(node, k, p, toBBox, destNode) {
21634           if (!destNode) destNode = createNode$1(null);
21635           destNode.minX = Infinity;
21636           destNode.minY = Infinity;
21637           destNode.maxX = -Infinity;
21638           destNode.maxY = -Infinity;
21639
21640           for (var i = k, child; i < p; i++) {
21641             child = node.children[i];
21642             extend$2(destNode, node.leaf ? toBBox(child) : child);
21643           }
21644
21645           return destNode;
21646         }
21647
21648         function extend$2(a, b) {
21649           a.minX = Math.min(a.minX, b.minX);
21650           a.minY = Math.min(a.minY, b.minY);
21651           a.maxX = Math.max(a.maxX, b.maxX);
21652           a.maxY = Math.max(a.maxY, b.maxY);
21653           return a;
21654         }
21655
21656         function compareNodeMinX$1(a, b) {
21657           return a.minX - b.minX;
21658         }
21659
21660         function compareNodeMinY$1(a, b) {
21661           return a.minY - b.minY;
21662         }
21663
21664         function bboxArea$1(a) {
21665           return (a.maxX - a.minX) * (a.maxY - a.minY);
21666         }
21667
21668         function bboxMargin$1(a) {
21669           return a.maxX - a.minX + (a.maxY - a.minY);
21670         }
21671
21672         function enlargedArea$1(a, b) {
21673           return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) * (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
21674         }
21675
21676         function intersectionArea$1(a, b) {
21677           var minX = Math.max(a.minX, b.minX),
21678               minY = Math.max(a.minY, b.minY),
21679               maxX = Math.min(a.maxX, b.maxX),
21680               maxY = Math.min(a.maxY, b.maxY);
21681           return Math.max(0, maxX - minX) * Math.max(0, maxY - minY);
21682         }
21683
21684         function contains$1(a, b) {
21685           return a.minX <= b.minX && a.minY <= b.minY && b.maxX <= a.maxX && b.maxY <= a.maxY;
21686         }
21687
21688         function intersects$1(a, b) {
21689           return b.minX <= a.maxX && b.minY <= a.maxY && b.maxX >= a.minX && b.maxY >= a.minY;
21690         }
21691
21692         function createNode$1(children) {
21693           return {
21694             children: children,
21695             height: 1,
21696             leaf: true,
21697             minX: Infinity,
21698             minY: Infinity,
21699             maxX: -Infinity,
21700             maxY: -Infinity
21701           };
21702         } // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
21703         // combines selection algorithm with binary divide & conquer approach
21704
21705
21706         function multiSelect$1(arr, left, right, n, compare) {
21707           var stack = [left, right],
21708               mid;
21709
21710           while (stack.length) {
21711             right = stack.pop();
21712             left = stack.pop();
21713             if (right - left <= n) continue;
21714             mid = left + Math.ceil((right - left) / n / 2) * n;
21715             quickselect$1(arr, mid, left, right, compare);
21716             stack.push(left, mid, mid, right);
21717           }
21718         }
21719
21720         var lineclip_1 = lineclip$2;
21721         lineclip$2.polyline = lineclip$2;
21722         lineclip$2.polygon = polygonclip$1; // Cohen-Sutherland line clippign algorithm, adapted to efficiently
21723         // handle polylines rather than just segments
21724
21725         function lineclip$2(points, bbox, result) {
21726           var len = points.length,
21727               codeA = bitCode$1(points[0], bbox),
21728               part = [],
21729               i,
21730               a,
21731               b,
21732               codeB,
21733               lastCode;
21734           if (!result) result = [];
21735
21736           for (i = 1; i < len; i++) {
21737             a = points[i - 1];
21738             b = points[i];
21739             codeB = lastCode = bitCode$1(b, bbox);
21740
21741             while (true) {
21742               if (!(codeA | codeB)) {
21743                 // accept
21744                 part.push(a);
21745
21746                 if (codeB !== lastCode) {
21747                   // segment went outside
21748                   part.push(b);
21749
21750                   if (i < len - 1) {
21751                     // start a new line
21752                     result.push(part);
21753                     part = [];
21754                   }
21755                 } else if (i === len - 1) {
21756                   part.push(b);
21757                 }
21758
21759                 break;
21760               } else if (codeA & codeB) {
21761                 // trivial reject
21762                 break;
21763               } else if (codeA) {
21764                 // a outside, intersect with clip edge
21765                 a = intersect$1(a, b, codeA, bbox);
21766                 codeA = bitCode$1(a, bbox);
21767               } else {
21768                 // b outside
21769                 b = intersect$1(a, b, codeB, bbox);
21770                 codeB = bitCode$1(b, bbox);
21771               }
21772             }
21773
21774             codeA = lastCode;
21775           }
21776
21777           if (part.length) result.push(part);
21778           return result;
21779         } // Sutherland-Hodgeman polygon clipping algorithm
21780
21781
21782         function polygonclip$1(points, bbox) {
21783           var result, edge, prev, prevInside, i, p, inside; // clip against each side of the clip rectangle
21784
21785           for (edge = 1; edge <= 8; edge *= 2) {
21786             result = [];
21787             prev = points[points.length - 1];
21788             prevInside = !(bitCode$1(prev, bbox) & edge);
21789
21790             for (i = 0; i < points.length; i++) {
21791               p = points[i];
21792               inside = !(bitCode$1(p, bbox) & edge); // if segment goes through the clip window, add an intersection
21793
21794               if (inside !== prevInside) result.push(intersect$1(prev, p, edge, bbox));
21795               if (inside) result.push(p); // add a point if it's inside
21796
21797               prev = p;
21798               prevInside = inside;
21799             }
21800
21801             points = result;
21802             if (!points.length) break;
21803           }
21804
21805           return result;
21806         } // intersect a segment against one of the 4 lines that make up the bbox
21807
21808
21809         function intersect$1(a, b, edge, bbox) {
21810           return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox[3] - a[1]) / (b[1] - a[1]), bbox[3]] : // top
21811           edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox[1] - a[1]) / (b[1] - a[1]), bbox[1]] : // bottom
21812           edge & 2 ? [bbox[2], a[1] + (b[1] - a[1]) * (bbox[2] - a[0]) / (b[0] - a[0])] : // right
21813           edge & 1 ? [bbox[0], a[1] + (b[1] - a[1]) * (bbox[0] - a[0]) / (b[0] - a[0])] : // left
21814           null;
21815         } // bit code reflects the point position relative to the bbox:
21816         //         left  mid  right
21817         //    top  1001  1000  1010
21818         //    mid  0001  0000  0010
21819         // bottom  0101  0100  0110
21820
21821
21822         function bitCode$1(p, bbox) {
21823           var code = 0;
21824           if (p[0] < bbox[0]) code |= 1; // left
21825           else if (p[0] > bbox[2]) code |= 2; // right
21826
21827           if (p[1] < bbox[1]) code |= 4; // bottom
21828           else if (p[1] > bbox[3]) code |= 8; // top
21829
21830           return code;
21831         }
21832
21833         var rbush = rbush$2.exports;
21834         var lineclip$1 = lineclip_1;
21835         var whichPolygon_1 = whichPolygon;
21836
21837         function whichPolygon(data) {
21838           var bboxes = [];
21839
21840           for (var i = 0; i < data.features.length; i++) {
21841             var feature = data.features[i];
21842             var coords = feature.geometry.coordinates;
21843
21844             if (feature.geometry.type === 'Polygon') {
21845               bboxes.push(treeItem(coords, feature.properties));
21846             } else if (feature.geometry.type === 'MultiPolygon') {
21847               for (var j = 0; j < coords.length; j++) {
21848                 bboxes.push(treeItem(coords[j], feature.properties));
21849               }
21850             }
21851           }
21852
21853           var tree = rbush().load(bboxes);
21854
21855           function query(p, multi) {
21856             var output = [],
21857                 result = tree.search({
21858               minX: p[0],
21859               minY: p[1],
21860               maxX: p[0],
21861               maxY: p[1]
21862             });
21863
21864             for (var i = 0; i < result.length; i++) {
21865               if (insidePolygon(result[i].coords, p)) {
21866                 if (multi) output.push(result[i].props);else return result[i].props;
21867               }
21868             }
21869
21870             return multi && output.length ? output : null;
21871           }
21872
21873           query.tree = tree;
21874
21875           query.bbox = function queryBBox(bbox) {
21876             var output = [];
21877             var result = tree.search({
21878               minX: bbox[0],
21879               minY: bbox[1],
21880               maxX: bbox[2],
21881               maxY: bbox[3]
21882             });
21883
21884             for (var i = 0; i < result.length; i++) {
21885               if (polygonIntersectsBBox(result[i].coords, bbox)) {
21886                 output.push(result[i].props);
21887               }
21888             }
21889
21890             return output;
21891           };
21892
21893           return query;
21894         }
21895
21896         function polygonIntersectsBBox(polygon, bbox) {
21897           var bboxCenter = [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2];
21898           if (insidePolygon(polygon, bboxCenter)) return true;
21899
21900           for (var i = 0; i < polygon.length; i++) {
21901             if (lineclip$1(polygon[i], bbox).length > 0) return true;
21902           }
21903
21904           return false;
21905         } // ray casting algorithm for detecting if point is in polygon
21906
21907
21908         function insidePolygon(rings, p) {
21909           var inside = false;
21910
21911           for (var i = 0, len = rings.length; i < len; i++) {
21912             var ring = rings[i];
21913
21914             for (var j = 0, len2 = ring.length, k = len2 - 1; j < len2; k = j++) {
21915               if (rayIntersect(p, ring[j], ring[k])) inside = !inside;
21916             }
21917           }
21918
21919           return inside;
21920         }
21921
21922         function rayIntersect(p, p1, p2) {
21923           return p1[1] > p[1] !== p2[1] > p[1] && p[0] < (p2[0] - p1[0]) * (p[1] - p1[1]) / (p2[1] - p1[1]) + p1[0];
21924         }
21925
21926         function treeItem(coords, props) {
21927           var item = {
21928             minX: Infinity,
21929             minY: Infinity,
21930             maxX: -Infinity,
21931             maxY: -Infinity,
21932             coords: coords,
21933             props: props
21934           };
21935
21936           for (var i = 0; i < coords[0].length; i++) {
21937             var p = coords[0][i];
21938             item.minX = Math.min(item.minX, p[0]);
21939             item.minY = Math.min(item.minY, p[1]);
21940             item.maxX = Math.max(item.maxX, p[0]);
21941             item.maxY = Math.max(item.maxY, p[1]);
21942           }
21943
21944           return item;
21945         }
21946
21947         var type = "FeatureCollection";
21948         var features = [{
21949           type: "Feature",
21950           properties: {
21951             wikidata: "Q21",
21952             nameEn: "England",
21953             aliases: ["GB-ENG"],
21954             country: "GB",
21955             groups: ["Q23666", "Q3336843", "154", "150", "UN"],
21956             driveSide: "left",
21957             roadSpeedUnit: "mph",
21958             roadHeightUnit: "ft",
21959             callingCodes: ["44"]
21960           },
21961           geometry: {
21962             type: "MultiPolygon",
21963             coordinates: [[[[-6.03913, 51.13217], [-7.74976, 48.64773], [1.17405, 50.74239], [2.18458, 51.52087], [2.56575, 51.85301], [0.792, 57.56437], [-2.30613, 55.62698], [-2.17058, 55.45916], [-2.6095, 55.28488], [-2.63532, 55.19452], [-3.02906, 55.04606], [-3.09361, 54.94924], [-3.38407, 54.94278], [-4.1819, 54.57861], [-3.5082, 53.54318], [-3.08228, 53.25526], [-3.03675, 53.25092], [-2.92329, 53.19383], [-2.92022, 53.17685], [-2.98598, 53.15589], [-2.90649, 53.10964], [-2.87469, 53.12337], [-2.89131, 53.09374], [-2.83133, 52.99184], [-2.7251, 52.98389], [-2.72221, 52.92969], [-2.80549, 52.89428], [-2.85897, 52.94487], [-2.92401, 52.93836], [-2.97243, 52.9651], [-3.13576, 52.895], [-3.15744, 52.84947], [-3.16105, 52.79599], [-3.08734, 52.77504], [-3.01001, 52.76636], [-2.95581, 52.71794], [-3.01724, 52.72083], [-3.04398, 52.65435], [-3.13648, 52.58208], [-3.12926, 52.5286], [-3.09746, 52.53077], [-3.08662, 52.54811], [-3.00929, 52.57774], [-2.99701, 52.551], [-3.03603, 52.49969], [-3.13359, 52.49174], [-3.22971, 52.45344], [-3.22754, 52.42526], [-3.04687, 52.34504], [-2.95364, 52.3501], [-2.99701, 52.323], [-3.00785, 52.2753], [-3.09289, 52.20546], [-3.12638, 52.08114], [-2.97111, 51.90456], [-2.8818, 51.93196], [-2.78742, 51.88833], [-2.74277, 51.84367], [-2.66234, 51.83555], [-2.66336, 51.59504], [-3.20563, 51.31615], [-6.03913, 51.13217]]]]
21964           }
21965         }, {
21966           type: "Feature",
21967           properties: {
21968             wikidata: "Q22",
21969             nameEn: "Scotland",
21970             aliases: ["GB-SCT"],
21971             country: "GB",
21972             groups: ["Q23666", "Q3336843", "154", "150", "UN"],
21973             driveSide: "left",
21974             roadSpeedUnit: "mph",
21975             roadHeightUnit: "ft",
21976             callingCodes: ["44"]
21977           },
21978           geometry: {
21979             type: "MultiPolygon",
21980             coordinates: [[[[0.792, 57.56437], [-0.3751, 61.32236], [-14.78497, 57.60709], [-6.82333, 55.83103], [-4.69044, 54.3629], [-3.38407, 54.94278], [-3.09361, 54.94924], [-3.02906, 55.04606], [-2.63532, 55.19452], [-2.6095, 55.28488], [-2.17058, 55.45916], [-2.30613, 55.62698], [0.792, 57.56437]]]]
21981           }
21982         }, {
21983           type: "Feature",
21984           properties: {
21985             wikidata: "Q25",
21986             nameEn: "Wales",
21987             aliases: ["GB-WLS"],
21988             country: "GB",
21989             groups: ["Q23666", "Q3336843", "154", "150", "UN"],
21990             driveSide: "left",
21991             roadSpeedUnit: "mph",
21992             roadHeightUnit: "ft",
21993             callingCodes: ["44"]
21994           },
21995           geometry: {
21996             type: "MultiPolygon",
21997             coordinates: [[[[-3.5082, 53.54318], [-5.37267, 53.63269], [-6.03913, 51.13217], [-3.20563, 51.31615], [-2.66336, 51.59504], [-2.66234, 51.83555], [-2.74277, 51.84367], [-2.78742, 51.88833], [-2.8818, 51.93196], [-2.97111, 51.90456], [-3.12638, 52.08114], [-3.09289, 52.20546], [-3.00785, 52.2753], [-2.99701, 52.323], [-2.95364, 52.3501], [-3.04687, 52.34504], [-3.22754, 52.42526], [-3.22971, 52.45344], [-3.13359, 52.49174], [-3.03603, 52.49969], [-2.99701, 52.551], [-3.00929, 52.57774], [-3.08662, 52.54811], [-3.09746, 52.53077], [-3.12926, 52.5286], [-3.13648, 52.58208], [-3.04398, 52.65435], [-3.01724, 52.72083], [-2.95581, 52.71794], [-3.01001, 52.76636], [-3.08734, 52.77504], [-3.16105, 52.79599], [-3.15744, 52.84947], [-3.13576, 52.895], [-2.97243, 52.9651], [-2.92401, 52.93836], [-2.85897, 52.94487], [-2.80549, 52.89428], [-2.72221, 52.92969], [-2.7251, 52.98389], [-2.83133, 52.99184], [-2.89131, 53.09374], [-2.87469, 53.12337], [-2.90649, 53.10964], [-2.98598, 53.15589], [-2.92022, 53.17685], [-2.92329, 53.19383], [-3.03675, 53.25092], [-3.08228, 53.25526], [-3.5082, 53.54318]]]]
21998           }
21999         }, {
22000           type: "Feature",
22001           properties: {
22002             wikidata: "Q26",
22003             nameEn: "Northern Ireland",
22004             aliases: ["GB-NIR"],
22005             country: "GB",
22006             groups: ["Q22890", "Q3336843", "154", "150", "UN"],
22007             driveSide: "left",
22008             roadSpeedUnit: "mph",
22009             roadHeightUnit: "ft",
22010             callingCodes: ["44"]
22011           },
22012           geometry: {
22013             type: "MultiPolygon",
22014             coordinates: [[[[-6.34755, 55.49206], [-7.2471, 55.06933], [-7.34464, 55.04688], [-7.4033, 55.00391], [-7.40004, 54.94498], [-7.44404, 54.9403], [-7.4473, 54.87003], [-7.47626, 54.83084], [-7.54508, 54.79401], [-7.54671, 54.74606], [-7.64449, 54.75265], [-7.75041, 54.7103], [-7.83352, 54.73854], [-7.93293, 54.66603], [-7.70315, 54.62077], [-7.8596, 54.53671], [-7.99812, 54.54427], [-8.04538, 54.48941], [-8.179, 54.46763], [-8.04555, 54.36292], [-7.87101, 54.29299], [-7.8596, 54.21779], [-7.81397, 54.20159], [-7.69501, 54.20731], [-7.55812, 54.12239], [-7.4799, 54.12239], [-7.44567, 54.1539], [-7.32834, 54.11475], [-7.30553, 54.11869], [-7.34005, 54.14698], [-7.29157, 54.17191], [-7.28017, 54.16714], [-7.29687, 54.1354], [-7.29493, 54.12013], [-7.26316, 54.13863], [-7.25012, 54.20063], [-7.14908, 54.22732], [-7.19145, 54.31296], [-7.02034, 54.4212], [-6.87775, 54.34682], [-6.85179, 54.29176], [-6.81583, 54.22791], [-6.74575, 54.18788], [-6.70175, 54.20218], [-6.6382, 54.17071], [-6.66264, 54.0666], [-6.62842, 54.03503], [-6.47849, 54.06947], [-6.36605, 54.07234], [-6.36279, 54.11248], [-6.32694, 54.09337], [-6.29003, 54.11278], [-6.26218, 54.09785], [-5.83481, 53.87749], [-4.69044, 54.3629], [-6.34755, 55.49206]]]]
22015           }
22016         }, {
22017           type: "Feature",
22018           properties: {
22019             wikidata: "Q35",
22020             nameEn: "Denmark",
22021             country: "DK",
22022             groups: ["EU", "154", "150", "UN"],
22023             callingCodes: ["45"]
22024           },
22025           geometry: {
22026             type: "MultiPolygon",
22027             coordinates: [[[[12.16597, 56.60205], [10.40861, 58.38489], [7.28637, 57.35913], [8.02459, 55.09613], [8.45719, 55.06747], [8.55769, 54.91837], [8.63979, 54.91069], [8.76387, 54.8948], [8.81178, 54.90518], [8.92795, 54.90452], [9.04629, 54.87249], [9.14275, 54.87421], [9.20571, 54.85841], [9.24631, 54.84726], [9.23445, 54.83432], [9.2474, 54.8112], [9.32771, 54.80602], [9.33849, 54.80233], [9.36496, 54.81749], [9.38532, 54.83968], [9.41213, 54.84254], [9.43155, 54.82586], [9.4659, 54.83131], [9.58937, 54.88785], [9.62734, 54.88057], [9.61187, 54.85548], [9.73563, 54.8247], [9.89314, 54.84171], [10.16755, 54.73883], [10.31111, 54.65968], [11.00303, 54.63689], [11.90309, 54.38543], [12.85844, 54.82438], [13.93395, 54.84044], [15.36991, 54.73263], [15.79951, 55.54655], [14.89259, 55.5623], [14.28399, 55.1553], [12.84405, 55.13257], [12.60345, 55.42675], [12.88472, 55.63369], [12.6372, 55.91371], [12.65312, 56.04345], [12.07466, 56.29488], [12.16597, 56.60205]]]]
22028           }
22029         }, {
22030           type: "Feature",
22031           properties: {
22032             wikidata: "Q55",
22033             nameEn: "Netherlands",
22034             country: "NL",
22035             groups: ["EU", "155", "150", "UN"],
22036             callingCodes: ["31"]
22037           },
22038           geometry: {
22039             type: "MultiPolygon",
22040             coordinates: [[[[5.45168, 54.20039], [2.56575, 51.85301], [3.36263, 51.37112], [3.38696, 51.33436], [3.35847, 51.31572], [3.38289, 51.27331], [3.41704, 51.25933], [3.43488, 51.24135], [3.52698, 51.2458], [3.51502, 51.28697], [3.58939, 51.30064], [3.78999, 51.25766], [3.78783, 51.2151], [3.90125, 51.20371], [3.97889, 51.22537], [4.01957, 51.24504], [4.05165, 51.24171], [4.16721, 51.29348], [4.24024, 51.35371], [4.21923, 51.37443], [4.33265, 51.37687], [4.34086, 51.35738], [4.39292, 51.35547], [4.43777, 51.36989], [4.38064, 51.41965], [4.39747, 51.43316], [4.38122, 51.44905], [4.47736, 51.4778], [4.5388, 51.48184], [4.54675, 51.47265], [4.52846, 51.45002], [4.53521, 51.4243], [4.57489, 51.4324], [4.65442, 51.42352], [4.72935, 51.48424], [4.74578, 51.48937], [4.77321, 51.50529], [4.78803, 51.50284], [4.84139, 51.4799], [4.82409, 51.44736], [4.82946, 51.4213], [4.78314, 51.43319], [4.76577, 51.43046], [4.77229, 51.41337], [4.78941, 51.41102], [4.84988, 51.41502], [4.90016, 51.41404], [4.92152, 51.39487], [5.00393, 51.44406], [5.0106, 51.47167], [5.03281, 51.48679], [5.04774, 51.47022], [5.07891, 51.4715], [5.10456, 51.43163], [5.07102, 51.39469], [5.13105, 51.34791], [5.13377, 51.31592], [5.16222, 51.31035], [5.2002, 51.32243], [5.24244, 51.30495], [5.22542, 51.26888], [5.23814, 51.26064], [5.26461, 51.26693], [5.29716, 51.26104], [5.33886, 51.26314], [5.347, 51.27502], [5.41672, 51.26248], [5.4407, 51.28169], [5.46519, 51.2849], [5.48476, 51.30053], [5.515, 51.29462], [5.5569, 51.26544], [5.5603, 51.22249], [5.65145, 51.19788], [5.65528, 51.18736], [5.70344, 51.1829], [5.74617, 51.18928], [5.77735, 51.17845], [5.77697, 51.1522], [5.82564, 51.16753], [5.85508, 51.14445], [5.80798, 51.11661], [5.8109, 51.10861], [5.83226, 51.10585], [5.82921, 51.09328], [5.79903, 51.09371], [5.79835, 51.05834], [5.77258, 51.06196], [5.75961, 51.03113], [5.77688, 51.02483], [5.76242, 50.99703], [5.71864, 50.96092], [5.72875, 50.95428], [5.74752, 50.96202], [5.75927, 50.95601], [5.74644, 50.94723], [5.72545, 50.92312], [5.72644, 50.91167], [5.71626, 50.90796], [5.69858, 50.91046], [5.67886, 50.88142], [5.64504, 50.87107], [5.64009, 50.84742], [5.65259, 50.82309], [5.70118, 50.80764], [5.68995, 50.79641], [5.70107, 50.7827], [5.68091, 50.75804], [5.69469, 50.75529], [5.72216, 50.76398], [5.73904, 50.75674], [5.74356, 50.7691], [5.76533, 50.78159], [5.77513, 50.78308], [5.80673, 50.7558], [5.84548, 50.76542], [5.84888, 50.75448], [5.88734, 50.77092], [5.89129, 50.75125], [5.89132, 50.75124], [5.95942, 50.7622], [5.97545, 50.75441], [6.01976, 50.75398], [6.02624, 50.77453], [5.97497, 50.79992], [5.98404, 50.80988], [6.00462, 50.80065], [6.02328, 50.81694], [6.01921, 50.84435], [6.05623, 50.8572], [6.05702, 50.85179], [6.07431, 50.84674], [6.07693, 50.86025], [6.08805, 50.87223], [6.07486, 50.89307], [6.09297, 50.92066], [6.01615, 50.93367], [6.02697, 50.98303], [5.95282, 50.98728], [5.90296, 50.97356], [5.90493, 51.00198], [5.87849, 51.01969], [5.86735, 51.05182], [5.9134, 51.06736], [5.9541, 51.03496], [5.98292, 51.07469], [6.16706, 51.15677], [6.17384, 51.19589], [6.07889, 51.17038], [6.07889, 51.24432], [6.16977, 51.33169], [6.22674, 51.36135], [6.22641, 51.39948], [6.20654, 51.40049], [6.21724, 51.48568], [6.18017, 51.54096], [6.09055, 51.60564], [6.11759, 51.65609], [6.02767, 51.6742], [6.04091, 51.71821], [5.95003, 51.7493], [5.98665, 51.76944], [5.94568, 51.82786], [5.99848, 51.83195], [6.06705, 51.86136], [6.10337, 51.84829], [6.16902, 51.84094], [6.11551, 51.89769], [6.15349, 51.90439], [6.21443, 51.86801], [6.29872, 51.86801], [6.30593, 51.84998], [6.40704, 51.82771], [6.38815, 51.87257], [6.47179, 51.85395], [6.50231, 51.86313], [6.58556, 51.89386], [6.68386, 51.91861], [6.72319, 51.89518], [6.82357, 51.96711], [6.83035, 51.9905], [6.68128, 52.05052], [6.76117, 52.11895], [6.83984, 52.11728], [6.97189, 52.20329], [6.9897, 52.2271], [7.03729, 52.22695], [7.06365, 52.23789], [7.02703, 52.27941], [7.07044, 52.37805], [7.03417, 52.40237], [6.99041, 52.47235], [6.94293, 52.43597], [6.69507, 52.488], [6.71641, 52.62905], [6.77307, 52.65375], [7.04557, 52.63318], [7.07253, 52.81083], [7.21694, 53.00742], [7.17898, 53.13817], [7.22681, 53.18165], [7.21679, 53.20058], [7.19052, 53.31866], [7.00198, 53.32672], [6.91025, 53.44221], [5.45168, 54.20039]], [[4.93295, 51.44945], [4.95244, 51.45207], [4.9524, 51.45014], [4.93909, 51.44632], [4.93295, 51.44945]], [[4.91493, 51.4353], [4.91935, 51.43634], [4.92227, 51.44252], [4.91811, 51.44621], [4.92287, 51.44741], [4.92811, 51.4437], [4.92566, 51.44273], [4.92815, 51.43856], [4.92879, 51.44161], [4.93544, 51.44634], [4.94025, 51.44193], [4.93416, 51.44185], [4.93471, 51.43861], [4.94265, 51.44003], [4.93986, 51.43064], [4.92952, 51.42984], [4.92652, 51.43329], [4.91493, 51.4353]]]]
22041           }
22042         }, {
22043           type: "Feature",
22044           properties: {
22045             wikidata: "Q782",
22046             nameEn: "Hawaii",
22047             aliases: ["US-HI"],
22048             country: "US",
22049             groups: ["Q35657", "061", "009", "UN"],
22050             roadSpeedUnit: "mph",
22051             roadHeightUnit: "ft",
22052             callingCodes: ["1"]
22053           },
22054           geometry: {
22055             type: "MultiPolygon",
22056             coordinates: [[[[-177.8563, 29.18961], [-179.49839, 27.86265], [-151.6784, 9.55515], [-154.05867, 45.51124], [-177.5224, 27.7635], [-177.8563, 29.18961]]]]
22057           }
22058         }, {
22059           type: "Feature",
22060           properties: {
22061             wikidata: "Q797",
22062             nameEn: "Alaska",
22063             aliases: ["US-AK"],
22064             country: "US",
22065             groups: ["Q35657", "021", "003", "019", "UN"],
22066             roadSpeedUnit: "mph",
22067             roadHeightUnit: "ft",
22068             callingCodes: ["1"]
22069           },
22070           geometry: {
22071             type: "MultiPolygon",
22072             coordinates: [[[[169.34848, 52.47228], [180, 51.0171], [179.84401, 55.10087], [169.34848, 52.47228]]], [[[-168.95635, 65.98512], [-169.03888, 65.48473], [-172.76104, 63.77445], [-179.55295, 57.62081], [-179.55295, 50.81807], [-133.92876, 54.62289], [-130.61931, 54.70835], [-130.64499, 54.76912], [-130.44184, 54.85377], [-130.27203, 54.97174], [-130.18765, 55.07744], [-130.08035, 55.21556], [-129.97513, 55.28029], [-130.15373, 55.74895], [-130.00857, 55.91344], [-130.00093, 56.00325], [-130.10173, 56.12178], [-130.33965, 56.10849], [-130.77769, 56.36185], [-131.8271, 56.62247], [-133.38523, 58.42773], [-133.84645, 58.73543], [-134.27175, 58.8634], [-134.48059, 59.13231], [-134.55699, 59.1297], [-134.7047, 59.2458], [-135.00267, 59.28745], [-135.03069, 59.56208], [-135.48007, 59.79937], [-136.31566, 59.59083], [-136.22381, 59.55526], [-136.33727, 59.44466], [-136.47323, 59.46617], [-136.52365, 59.16752], [-136.82619, 59.16198], [-137.4925, 58.89415], [-137.60623, 59.24465], [-138.62145, 59.76431], [-138.71149, 59.90728], [-139.05365, 59.99655], [-139.20603, 60.08896], [-139.05831, 60.35205], [-139.68991, 60.33693], [-139.98024, 60.18027], [-140.45648, 60.30919], [-140.5227, 60.22077], [-141.00116, 60.30648], [-140.97446, 84.39275], [-168.25765, 71.99091], [-168.95635, 65.98512]]]]
22073           }
22074         }, {
22075           type: "Feature",
22076           properties: {
22077             wikidata: "Q3492",
22078             nameEn: "Sumatra",
22079             aliases: ["ID-SM"],
22080             country: "ID",
22081             groups: ["035", "142", "UN"],
22082             driveSide: "left",
22083             callingCodes: ["62"]
22084           },
22085           geometry: {
22086             type: "MultiPolygon",
22087             coordinates: [[[[109.82788, 2.86812], [110.90339, 7.52694], [105.01437, 3.24936], [104.56723, 1.44271], [104.34728, 1.33529], [104.12282, 1.27714], [104.03085, 1.26954], [103.74084, 1.12902], [103.66049, 1.18825], [103.56591, 1.19719], [103.03657, 1.30383], [96.11174, 6.69841], [74.28481, -3.17525], [102.92489, -8.17146], [106.32259, -5.50116], [106.38511, -5.16715], [109.17017, -4.07401], [109.3962, -2.07276], [108.50935, -2.01066], [107.94791, 1.06924], [109.82788, 2.86812]]]]
22088           }
22089         }, {
22090           type: "Feature",
22091           properties: {
22092             wikidata: "Q3757",
22093             nameEn: "Java",
22094             aliases: ["ID-JW"],
22095             country: "ID",
22096             groups: ["035", "142", "UN"],
22097             driveSide: "left",
22098             callingCodes: ["62"]
22099           },
22100           geometry: {
22101             type: "MultiPolygon",
22102             coordinates: [[[[109.17017, -4.07401], [106.38511, -5.16715], [106.32259, -5.50116], [102.92489, -8.17146], [116.22542, -10.49172], [114.39575, -8.2889], [114.42235, -8.09762], [114.92859, -7.49253], [116.33992, -7.56171], [116.58433, -5.30385], [109.17017, -4.07401]]]]
22103           }
22104         }, {
22105           type: "Feature",
22106           properties: {
22107             wikidata: "Q3795",
22108             nameEn: "Kalimantan",
22109             aliases: ["ID-KA"],
22110             country: "ID",
22111             groups: ["Q36117", "035", "142", "UN"],
22112             driveSide: "left",
22113             callingCodes: ["62"]
22114           },
22115           geometry: {
22116             type: "MultiPolygon",
22117             coordinates: [[[[120.02464, 2.83703], [118.06469, 4.16638], [117.67641, 4.16535], [117.47313, 4.18857], [117.25801, 4.35108], [115.90217, 4.37708], [115.58276, 3.93499], [115.53713, 3.14776], [115.11343, 2.82879], [115.1721, 2.49671], [114.80706, 2.21665], [114.80706, 1.92351], [114.57892, 1.5], [114.03788, 1.44787], [113.64677, 1.23933], [113.01448, 1.42832], [113.021, 1.57819], [112.48648, 1.56516], [112.2127, 1.44135], [112.15679, 1.17004], [111.94553, 1.12016], [111.82846, 0.99349], [111.55434, 0.97864], [111.22979, 1.08326], [110.62374, 0.873], [110.49182, 0.88088], [110.35354, 0.98869], [109.66397, 1.60425], [109.66397, 1.79972], [109.57923, 1.80624], [109.53794, 1.91771], [109.62558, 1.99182], [109.82788, 2.86812], [107.94791, 1.06924], [108.50935, -2.01066], [109.3962, -2.07276], [109.17017, -4.07401], [116.58433, -5.30385], [120.02464, 2.83703]]]]
22118           }
22119         }, {
22120           type: "Feature",
22121           properties: {
22122             wikidata: "Q3803",
22123             nameEn: "Lesser Sunda Islands",
22124             aliases: ["ID-NU"],
22125             country: "ID",
22126             groups: ["035", "142", "UN"],
22127             driveSide: "left",
22128             callingCodes: ["62"]
22129           },
22130           geometry: {
22131             type: "MultiPolygon",
22132             coordinates: [[[[116.96967, -8.01483], [114.92859, -7.49253], [114.42235, -8.09762], [114.39575, -8.2889], [116.22542, -10.49172], [122.14954, -11.52517], [125.68138, -9.85176], [125.09025, -9.46406], [124.97892, -9.19281], [125.04044, -9.17093], [125.09434, -9.19669], [125.18907, -9.16434], [125.18632, -9.03142], [125.11764, -8.96359], [124.97742, -9.08128], [124.94011, -8.85617], [124.46701, -9.13002], [124.45971, -9.30263], [124.38554, -9.3582], [124.35258, -9.43002], [124.3535, -9.48493], [124.28115, -9.50453], [124.28115, -9.42189], [124.21247, -9.36904], [124.14517, -9.42324], [124.10539, -9.41206], [124.04286, -9.34243], [124.04628, -9.22671], [124.33472, -9.11416], [124.92337, -8.75859], [125.87688, -7.49892], [116.96967, -8.01483]]]]
22133           }
22134         }, {
22135           type: "Feature",
22136           properties: {
22137             wikidata: "Q3812",
22138             nameEn: "Sulawesi",
22139             aliases: ["ID-SL"],
22140             country: "ID",
22141             groups: ["035", "142", "UN"],
22142             driveSide: "left",
22143             callingCodes: ["62"]
22144           },
22145           geometry: {
22146             type: "MultiPolygon",
22147             coordinates: [[[[128.34321, 3.90322], [126.69413, 6.02692], [119.56457, 0.90759], [116.58433, -5.30385], [116.33992, -7.56171], [116.96967, -8.01483], [125.87688, -7.49892], [123.78965, -0.86805], [128.34321, 3.90322]]]]
22148           }
22149         }, {
22150           type: "Feature",
22151           properties: {
22152             wikidata: "Q3827",
22153             nameEn: "Maluku Islands",
22154             aliases: ["ID-ML"],
22155             country: "ID",
22156             groups: ["035", "142", "UN"],
22157             driveSide: "left",
22158             callingCodes: ["62"]
22159           },
22160           geometry: {
22161             type: "MultiPolygon",
22162             coordinates: [[[[129.63187, 2.21409], [128.34321, 3.90322], [123.78965, -0.86805], [125.87688, -7.49892], [125.58506, -7.95311], [125.87691, -8.31789], [127.42116, -8.22471], [127.55165, -9.05052], [135.49042, -9.2276], [135.35517, -5.01442], [132.8312, -4.70282], [130.8468, -2.61103], [128.40647, -2.30349], [129.71519, -0.24692], [129.63187, 2.21409]]]]
22163           }
22164         }, {
22165           type: "Feature",
22166           properties: {
22167             wikidata: "Q3845",
22168             nameEn: "Western New Guinea",
22169             aliases: ["ID-PP"],
22170             country: "ID",
22171             groups: ["035", "142", "UN"],
22172             driveSide: "left",
22173             callingCodes: ["62"]
22174           },
22175           geometry: {
22176             type: "MultiPolygon",
22177             coordinates: [[[[135.49042, -9.2276], [141.01842, -9.35091], [141.01763, -6.90181], [140.90448, -6.85033], [140.85295, -6.72996], [140.99813, -6.3233], [141.02352, 0.08993], [129.63187, 2.21409], [129.71519, -0.24692], [128.40647, -2.30349], [130.8468, -2.61103], [132.8312, -4.70282], [135.35517, -5.01442], [135.49042, -9.2276]]]]
22178           }
22179         }, {
22180           type: "Feature",
22181           properties: {
22182             wikidata: "Q5765",
22183             nameEn: "Balearic Islands",
22184             aliases: ["ES-IB"],
22185             country: "ES",
22186             groups: ["EU", "039", "150", "UN"],
22187             callingCodes: ["34 971"]
22188           },
22189           geometry: {
22190             type: "MultiPolygon",
22191             coordinates: [[[[-2.27707, 35.35051], [5.10072, 39.89531], [3.75438, 42.33445], [-2.27707, 35.35051]]]]
22192           }
22193         }, {
22194           type: "Feature",
22195           properties: {
22196             wikidata: "Q5823",
22197             nameEn: "Ceuta",
22198             aliases: ["ES-CE"],
22199             country: "ES",
22200             groups: ["EA", "EU", "015", "002", "UN"],
22201             level: "subterritory",
22202             callingCodes: ["34"]
22203           },
22204           geometry: {
22205             type: "MultiPolygon",
22206             coordinates: [[[[-5.38491, 35.92591], [-5.37338, 35.88417], [-5.35844, 35.87375], [-5.34379, 35.8711], [-5.21179, 35.90091], [-5.38491, 35.92591]]]]
22207           }
22208         }, {
22209           type: "Feature",
22210           properties: {
22211             wikidata: "Q5831",
22212             nameEn: "Melilla",
22213             aliases: ["ES-ML"],
22214             country: "ES",
22215             groups: ["EA", "EU", "015", "002", "UN"],
22216             level: "subterritory",
22217             callingCodes: ["34"]
22218           },
22219           geometry: {
22220             type: "MultiPolygon",
22221             coordinates: [[[[-2.91909, 35.33927], [-2.96038, 35.31609], [-2.96648, 35.30475], [-2.96978, 35.29459], [-2.97035, 35.28852], [-2.96507, 35.28801], [-2.96826, 35.28296], [-2.96516, 35.27967], [-2.95431, 35.2728], [-2.95065, 35.26576], [-2.93893, 35.26737], [-2.92272, 35.27509], [-2.91909, 35.33927]]]]
22222           }
22223         }, {
22224           type: "Feature",
22225           properties: {
22226             wikidata: "Q7835",
22227             nameEn: "Crimea",
22228             country: "RU",
22229             groups: ["151", "150", "UN"],
22230             level: "subterritory",
22231             callingCodes: ["7"]
22232           },
22233           geometry: {
22234             type: "MultiPolygon",
22235             coordinates: [[[[33.5, 44], [36.4883, 45.0488], [36.475, 45.2411], [36.5049, 45.3136], [36.6545, 45.3417], [36.6645, 45.4514], [35.0498, 45.7683], [34.9601, 45.7563], [34.7991, 45.8101], [34.8015, 45.9005], [34.7548, 45.907], [34.6668, 45.9714], [34.6086, 45.9935], [34.5589, 45.9935], [34.5201, 45.951], [34.4873, 45.9427], [34.4415, 45.9599], [34.4122, 46.0025], [34.3391, 46.0611], [34.2511, 46.0532], [34.181, 46.068], [34.1293, 46.1049], [34.0731, 46.1177], [34.0527, 46.1084], [33.9155, 46.1594], [33.8523, 46.1986], [33.7972, 46.2048], [33.7405, 46.1855], [33.646, 46.2303], [33.6152, 46.2261], [33.6385, 46.1415], [33.6147, 46.1356], [33.5732, 46.1032], [33.5909, 46.0601], [33.5597, 46.0307], [31.5, 45.5], [33.5, 44]]]]
22236           }
22237         }, {
22238           type: "Feature",
22239           properties: {
22240             wikidata: "Q12837",
22241             nameEn: "Iberia",
22242             level: "sharedLandform"
22243           },
22244           geometry: null
22245         }, {
22246           type: "Feature",
22247           properties: {
22248             wikidata: "Q14056",
22249             nameEn: "Jan Mayen",
22250             aliases: ["NO-22"],
22251             country: "NO",
22252             groups: ["SJ", "154", "150", "UN"],
22253             level: "subterritory"
22254           },
22255           geometry: {
22256             type: "MultiPolygon",
22257             coordinates: [[[[-9.18243, 72.23144], [-10.71459, 70.09565], [-5.93364, 70.76368], [-9.18243, 72.23144]]]]
22258           }
22259         }, {
22260           type: "Feature",
22261           properties: {
22262             wikidata: "Q19188",
22263             nameEn: "Mainland China",
22264             country: "CN",
22265             groups: ["030", "142", "UN"],
22266             callingCodes: ["86"]
22267           },
22268           geometry: {
22269             type: "MultiPolygon",
22270             coordinates: [[[[125.6131, 53.07229], [125.17522, 53.20225], [124.46078, 53.21881], [123.86158, 53.49391], [123.26989, 53.54843], [122.85966, 53.47395], [122.35063, 53.49565], [121.39213, 53.31888], [120.85633, 53.28499], [120.0451, 52.7359], [120.04049, 52.58773], [120.46454, 52.63811], [120.71673, 52.54099], [120.61346, 52.32447], [120.77337, 52.20805], [120.65907, 51.93544], [120.10963, 51.671], [119.13553, 50.37412], [119.38598, 50.35162], [119.27996, 50.13348], [119.11003, 50.00276], [118.61623, 49.93809], [117.82343, 49.52696], [117.48208, 49.62324], [117.27597, 49.62544], [116.71193, 49.83813], [116.03781, 48.87014], [116.06565, 48.81716], [115.78876, 48.51781], [115.811, 48.25699], [115.52082, 48.15367], [115.57128, 47.91988], [115.94296, 47.67741], [116.21879, 47.88505], [116.4465, 47.83662], [116.67405, 47.89039], [116.9723, 47.87285], [117.37875, 47.63627], [117.50181, 47.77216], [117.80196, 48.01661], [118.03676, 48.00982], [118.11009, 48.04], [118.22677, 48.03853], [118.29654, 48.00246], [118.55766, 47.99277], [118.7564, 47.76947], [119.12343, 47.66458], [119.13995, 47.53997], [119.35892, 47.48104], [119.31964, 47.42617], [119.54918, 47.29505], [119.56019, 47.24874], [119.62403, 47.24575], [119.71209, 47.19192], [119.85518, 46.92196], [119.91242, 46.90091], [119.89261, 46.66423], [119.80455, 46.67631], [119.77373, 46.62947], [119.68127, 46.59015], [119.65265, 46.62342], [119.42827, 46.63783], [119.32827, 46.61433], [119.24978, 46.64761], [119.10448, 46.65516], [119.00541, 46.74273], [118.92616, 46.72765], [118.89974, 46.77139], [118.8337, 46.77742], [118.78747, 46.68689], [118.30534, 46.73519], [117.69554, 46.50991], [117.60748, 46.59771], [117.41782, 46.57862], [117.36609, 46.36335], [116.83166, 46.38637], [116.75551, 46.33083], [116.58612, 46.30211], [116.26678, 45.96479], [116.24012, 45.8778], [116.27366, 45.78637], [116.16989, 45.68603], [115.60329, 45.44717], [114.94546, 45.37377], [114.74612, 45.43585], [114.54801, 45.38337], [114.5166, 45.27189], [113.70918, 44.72891], [112.74662, 44.86297], [112.4164, 45.06858], [111.98695, 45.09074], [111.76275, 44.98032], [111.40498, 44.3461], [111.96289, 43.81596], [111.93776, 43.68709], [111.79758, 43.6637], [111.59087, 43.51207], [111.0149, 43.3289], [110.4327, 42.78293], [110.08401, 42.6411], [109.89402, 42.63111], [109.452, 42.44842], [109.00679, 42.45302], [108.84489, 42.40246], [107.57258, 42.40898], [107.49681, 42.46221], [107.29755, 42.41395], [107.24774, 42.36107], [106.76517, 42.28741], [105.0123, 41.63188], [104.51667, 41.66113], [104.52258, 41.8706], [103.92804, 41.78246], [102.72403, 42.14675], [102.07645, 42.22519], [101.80515, 42.50074], [100.84979, 42.67087], [100.33297, 42.68231], [99.50671, 42.56535], [97.1777, 42.7964], [96.37926, 42.72055], [96.35658, 42.90363], [95.89543, 43.2528], [95.52594, 43.99353], [95.32891, 44.02407], [95.39772, 44.2805], [95.01191, 44.25274], [94.71959, 44.35284], [94.10003, 44.71016], [93.51161, 44.95964], [91.64048, 45.07408], [90.89169, 45.19667], [90.65114, 45.49314], [90.70907, 45.73437], [91.03026, 46.04194], [90.99672, 46.14207], [90.89639, 46.30711], [91.07696, 46.57315], [91.0147, 46.58171], [91.03649, 46.72916], [90.84035, 46.99525], [90.76108, 46.99399], [90.48542, 47.30438], [90.48854, 47.41826], [90.33598, 47.68303], [90.10871, 47.7375], [90.06512, 47.88177], [89.76624, 47.82745], [89.55453, 48.0423], [89.0711, 47.98528], [88.93186, 48.10263], [88.8011, 48.11302], [88.58316, 48.21893], [88.58939, 48.34531], [87.96361, 48.58478], [88.0788, 48.71436], [87.73822, 48.89582], [87.88171, 48.95853], [87.81333, 49.17354], [87.48983, 49.13794], [87.478, 49.07403], [87.28386, 49.11626], [86.87238, 49.12432], [86.73568, 48.99918], [86.75343, 48.70331], [86.38069, 48.46064], [85.73581, 48.3939], [85.5169, 48.05493], [85.61067, 47.49753], [85.69696, 47.2898], [85.54294, 47.06171], [85.22443, 47.04816], [84.93995, 46.87399], [84.73077, 47.01394], [83.92184, 46.98912], [83.04622, 47.19053], [82.21792, 45.56619], [82.58474, 45.40027], [82.51374, 45.1755], [81.73278, 45.3504], [80.11169, 45.03352], [79.8987, 44.89957], [80.38384, 44.63073], [80.40229, 44.23319], [80.40031, 44.10986], [80.75156, 43.44948], [80.69718, 43.32589], [80.77771, 43.30065], [80.78817, 43.14235], [80.62913, 43.141], [80.3735, 43.01557], [80.58999, 42.9011], [80.38169, 42.83142], [80.26886, 42.8366], [80.16892, 42.61137], [80.26841, 42.23797], [80.17807, 42.21166], [80.17842, 42.03211], [79.92977, 42.04113], [78.3732, 41.39603], [78.15757, 41.38565], [78.12873, 41.23091], [77.81287, 41.14307], [77.76206, 41.01574], [77.52723, 41.00227], [77.3693, 41.0375], [77.28004, 41.0033], [76.99302, 41.0696], [76.75681, 40.95354], [76.5261, 40.46114], [76.33659, 40.3482], [75.96168, 40.38064], [75.91361, 40.2948], [75.69663, 40.28642], [75.5854, 40.66874], [75.22834, 40.45382], [75.08243, 40.43945], [74.82013, 40.52197], [74.78168, 40.44886], [74.85996, 40.32857], [74.69875, 40.34668], [74.35063, 40.09742], [74.25533, 40.13191], [73.97049, 40.04378], [73.83006, 39.76136], [73.9051, 39.75073], [73.92354, 39.69565], [73.94683, 39.60733], [73.87018, 39.47879], [73.59831, 39.46425], [73.59241, 39.40843], [73.5004, 39.38402], [73.55396, 39.3543], [73.54572, 39.27567], [73.60638, 39.24534], [73.75823, 39.023], [73.81728, 39.04007], [73.82964, 38.91517], [73.7445, 38.93867], [73.7033, 38.84782], [73.80656, 38.66449], [73.79806, 38.61106], [73.97933, 38.52945], [74.17022, 38.65504], [74.51217, 38.47034], [74.69619, 38.42947], [74.69894, 38.22155], [74.80331, 38.19889], [74.82665, 38.07359], [74.9063, 38.03033], [74.92416, 37.83428], [75.00935, 37.77486], [74.8912, 37.67576], [74.94338, 37.55501], [75.06011, 37.52779], [75.15899, 37.41443], [75.09719, 37.37297], [75.12328, 37.31839], [74.88887, 37.23275], [74.80605, 37.21565], [74.49981, 37.24518], [74.56453, 37.03023], [75.13839, 37.02622], [75.40481, 36.95382], [75.45562, 36.71971], [75.72737, 36.7529], [75.92391, 36.56986], [76.0324, 36.41198], [76.00906, 36.17511], [75.93028, 36.13136], [76.15325, 35.9264], [76.14913, 35.82848], [76.33453, 35.84296], [76.50961, 35.8908], [76.77323, 35.66062], [76.84539, 35.67356], [76.96624, 35.5932], [77.44277, 35.46132], [77.70232, 35.46244], [77.80532, 35.52058], [78.11664, 35.48022], [78.03466, 35.3785], [78.00033, 35.23954], [78.22692, 34.88771], [78.18435, 34.7998], [78.27781, 34.61484], [78.54964, 34.57283], [78.56475, 34.50835], [78.74465, 34.45174], [79.05364, 34.32482], [78.99802, 34.3027], [78.91769, 34.15452], [78.66225, 34.08858], [78.65657, 34.03195], [78.73367, 34.01121], [78.77349, 33.73871], [78.67599, 33.66445], [78.73636, 33.56521], [79.15252, 33.17156], [79.14016, 33.02545], [79.46562, 32.69668], [79.26768, 32.53277], [79.13174, 32.47766], [79.0979, 32.38051], [78.99322, 32.37948], [78.96713, 32.33655], [78.7831, 32.46873], [78.73916, 32.69438], [78.38897, 32.53938], [78.4645, 32.45367], [78.49609, 32.2762], [78.68754, 32.10256], [78.74404, 32.00384], [78.78036, 31.99478], [78.69933, 31.78723], [78.84516, 31.60631], [78.71032, 31.50197], [78.77898, 31.31209], [78.89344, 31.30481], [79.01931, 31.42817], [79.14016, 31.43403], [79.30694, 31.17357], [79.59884, 30.93943], [79.93255, 30.88288], [80.20721, 30.58541], [80.54504, 30.44936], [80.83343, 30.32023], [81.03953, 30.20059], [81.12842, 30.01395], [81.24362, 30.0126], [81.29032, 30.08806], [81.2623, 30.14596], [81.33355, 30.15303], [81.39928, 30.21862], [81.41018, 30.42153], [81.5459, 30.37688], [81.62033, 30.44703], [81.99082, 30.33423], [82.10135, 30.35439], [82.10757, 30.23745], [82.19475, 30.16884], [82.16984, 30.0692], [82.38622, 30.02608], [82.5341, 29.9735], [82.73024, 29.81695], [83.07116, 29.61957], [83.28131, 29.56813], [83.44787, 29.30513], [83.63156, 29.16249], [83.82303, 29.30513], [83.97559, 29.33091], [84.18107, 29.23451], [84.24801, 29.02783], [84.2231, 28.89571], [84.47528, 28.74023], [84.62317, 28.73887], [84.85511, 28.58041], [85.06059, 28.68562], [85.19135, 28.62825], [85.18668, 28.54076], [85.10729, 28.34092], [85.38127, 28.28336], [85.4233, 28.32996], [85.59765, 28.30529], [85.60854, 28.25045], [85.69105, 28.38475], [85.71907, 28.38064], [85.74864, 28.23126], [85.84672, 28.18187], [85.90743, 28.05144], [85.97813, 27.99023], [85.94946, 27.9401], [86.06309, 27.90021], [86.12069, 27.93047], [86.08333, 28.02121], [86.088, 28.09264], [86.18607, 28.17364], [86.22966, 27.9786], [86.42736, 27.91122], [86.51609, 27.96623], [86.56265, 28.09569], [86.74181, 28.10638], [86.75582, 28.04182], [87.03757, 27.94835], [87.11696, 27.84104], [87.56996, 27.84517], [87.72718, 27.80938], [87.82681, 27.95248], [88.13378, 27.88015], [88.1278, 27.95417], [88.25332, 27.9478], [88.54858, 28.06057], [88.63235, 28.12356], [88.83559, 28.01936], [88.88091, 27.85192], [88.77517, 27.45415], [88.82981, 27.38814], [88.91901, 27.32483], [88.93678, 27.33777], [88.96947, 27.30319], [89.00216, 27.32532], [88.95355, 27.4106], [88.97213, 27.51671], [89.0582, 27.60985], [89.12825, 27.62502], [89.59525, 28.16433], [89.79762, 28.23979], [90.13387, 28.19178], [90.58842, 28.02838], [90.69894, 28.07784], [91.20019, 27.98715], [91.25779, 28.07509], [91.46327, 28.0064], [91.48973, 27.93903], [91.5629, 27.84823], [91.6469, 27.76358], [91.84722, 27.76325], [91.87057, 27.7195], [92.27432, 27.89077], [92.32101, 27.79363], [92.42538, 27.80092], [92.7275, 27.98662], [92.73025, 28.05814], [92.65472, 28.07632], [92.67486, 28.15018], [92.93075, 28.25671], [93.14635, 28.37035], [93.18069, 28.50319], [93.44621, 28.67189], [93.72797, 28.68821], [94.35897, 29.01965], [94.2752, 29.11687], [94.69318, 29.31739], [94.81353, 29.17804], [95.0978, 29.14446], [95.11291, 29.09527], [95.2214, 29.10727], [95.26122, 29.07727], [95.3038, 29.13847], [95.41091, 29.13007], [95.50842, 29.13487], [95.72086, 29.20797], [95.75149, 29.32063], [95.84899, 29.31464], [96.05361, 29.38167], [96.31316, 29.18643], [96.18682, 29.11087], [96.20467, 29.02325], [96.3626, 29.10607], [96.61391, 28.72742], [96.40929, 28.51526], [96.48895, 28.42955], [96.6455, 28.61657], [96.85561, 28.4875], [96.88445, 28.39452], [96.98882, 28.32564], [97.1289, 28.3619], [97.34547, 28.21385], [97.41729, 28.29783], [97.47085, 28.2688], [97.50518, 28.49716], [97.56835, 28.55628], [97.70705, 28.5056], [97.79632, 28.33168], [97.90069, 28.3776], [98.15337, 28.12114], [98.13964, 27.9478], [98.32641, 27.51385], [98.42529, 27.55404], [98.43353, 27.67086], [98.69582, 27.56499], [98.7333, 26.85615], [98.77547, 26.61994], [98.72741, 26.36183], [98.67797, 26.24487], [98.7329, 26.17218], [98.66884, 26.09165], [98.63128, 26.15492], [98.57085, 26.11547], [98.60763, 26.01512], [98.70818, 25.86241], [98.63128, 25.79937], [98.54064, 25.85129], [98.40606, 25.61129], [98.31268, 25.55307], [98.25774, 25.6051], [98.16848, 25.62739], [98.18084, 25.56298], [98.12591, 25.50722], [98.14925, 25.41547], [97.92541, 25.20815], [97.83614, 25.2715], [97.77023, 25.11492], [97.72216, 25.08508], [97.72903, 24.91332], [97.79949, 24.85655], [97.76481, 24.8289], [97.73127, 24.83015], [97.70181, 24.84557], [97.64354, 24.79171], [97.56648, 24.76475], [97.56383, 24.75535], [97.5542, 24.74943], [97.54675, 24.74202], [97.56525, 24.72838], [97.56286, 24.54535], [97.52757, 24.43748], [97.60029, 24.4401], [97.66998, 24.45288], [97.7098, 24.35658], [97.65624, 24.33781], [97.66723, 24.30027], [97.71941, 24.29652], [97.76799, 24.26365], [97.72998, 24.2302], [97.72799, 24.18883], [97.75305, 24.16902], [97.72903, 24.12606], [97.62363, 24.00506], [97.5247, 23.94032], [97.64667, 23.84574], [97.72302, 23.89288], [97.79456, 23.94836], [97.79416, 23.95663], [97.84328, 23.97603], [97.86545, 23.97723], [97.88811, 23.97446], [97.8955, 23.97758], [97.89676, 23.97931], [97.89683, 23.98389], [97.88814, 23.98605], [97.88414, 23.99405], [97.88616, 24.00463], [97.90998, 24.02094], [97.93951, 24.01953], [97.98691, 24.03897], [97.99583, 24.04932], [98.04709, 24.07616], [98.05302, 24.07408], [98.05671, 24.07961], [98.0607, 24.07812], [98.06703, 24.08028], [98.07806, 24.07988], [98.20666, 24.11406], [98.54476, 24.13119], [98.59256, 24.08371], [98.85319, 24.13042], [98.87998, 24.15624], [98.89632, 24.10612], [98.67797, 23.9644], [98.68209, 23.80492], [98.79607, 23.77947], [98.82933, 23.72921], [98.81775, 23.694], [98.88396, 23.59555], [98.80294, 23.5345], [98.82877, 23.47908], [98.87683, 23.48995], [98.92104, 23.36946], [98.87573, 23.33038], [98.93958, 23.31414], [98.92515, 23.29535], [98.88597, 23.18656], [99.05975, 23.16382], [99.04601, 23.12215], [99.25741, 23.09025], [99.34127, 23.13099], [99.52214, 23.08218], [99.54218, 22.90014], [99.43537, 22.94086], [99.45654, 22.85726], [99.31243, 22.73893], [99.38247, 22.57544], [99.37972, 22.50188], [99.28771, 22.4105], [99.17318, 22.18025], [99.19176, 22.16983], [99.1552, 22.15874], [99.33166, 22.09656], [99.47585, 22.13345], [99.85351, 22.04183], [99.96612, 22.05965], [99.99084, 21.97053], [99.94003, 21.82782], [99.98654, 21.71064], [100.04956, 21.66843], [100.12679, 21.70539], [100.17486, 21.65306], [100.10757, 21.59945], [100.12542, 21.50365], [100.1625, 21.48704], [100.18447, 21.51898], [100.25863, 21.47043], [100.35201, 21.53176], [100.42892, 21.54325], [100.4811, 21.46148], [100.57861, 21.45637], [100.72143, 21.51898], [100.87265, 21.67396], [101.11744, 21.77659], [101.15156, 21.56129], [101.2124, 21.56422], [101.19349, 21.41959], [101.26912, 21.36482], [101.2229, 21.23271], [101.29326, 21.17254], [101.54563, 21.25668], [101.6068, 21.23329], [101.59491, 21.18621], [101.60886, 21.17947], [101.66977, 21.20004], [101.70548, 21.14911], [101.7622, 21.14813], [101.79266, 21.19025], [101.76745, 21.21571], [101.83887, 21.20983], [101.84412, 21.25291], [101.74014, 21.30967], [101.74224, 21.48276], [101.7727, 21.51794], [101.7475, 21.5873], [101.80001, 21.57461], [101.83257, 21.61562], [101.74555, 21.72852], [101.7791, 21.83019], [101.62566, 21.96574], [101.57525, 22.13026], [101.60675, 22.13513], [101.53638, 22.24794], [101.56789, 22.28876], [101.61306, 22.27515], [101.68973, 22.46843], [101.7685, 22.50337], [101.86828, 22.38397], [101.90714, 22.38688], [101.91344, 22.44417], [101.98487, 22.42766], [102.03633, 22.46164], [102.1245, 22.43372], [102.14099, 22.40092], [102.16621, 22.43336], [102.26428, 22.41321], [102.25339, 22.4607], [102.41061, 22.64184], [102.38415, 22.67919], [102.42618, 22.69212], [102.46665, 22.77108], [102.51802, 22.77969], [102.57095, 22.7036], [102.60675, 22.73376], [102.8636, 22.60735], [102.9321, 22.48659], [103.0722, 22.44775], [103.07843, 22.50097], [103.17961, 22.55705], [103.15782, 22.59873], [103.18895, 22.64471], [103.28079, 22.68063], [103.32282, 22.8127], [103.43179, 22.75816], [103.43646, 22.70648], [103.52675, 22.59155], [103.57812, 22.65764], [103.56255, 22.69499], [103.64506, 22.79979], [103.87904, 22.56683], [103.93286, 22.52703], [103.94513, 22.52553], [103.95191, 22.5134], [103.96352, 22.50584], [103.96783, 22.51173], [103.97384, 22.50634], [103.99247, 22.51958], [104.01088, 22.51823], [104.03734, 22.72945], [104.11384, 22.80363], [104.27084, 22.8457], [104.25683, 22.76534], [104.35593, 22.69353], [104.47225, 22.75813], [104.58122, 22.85571], [104.60457, 22.81841], [104.65283, 22.83419], [104.72755, 22.81984], [104.77114, 22.90017], [104.84942, 22.93631], [104.86765, 22.95178], [104.8334, 23.01484], [104.79478, 23.12934], [104.87382, 23.12854], [104.87992, 23.17141], [104.91435, 23.18666], [104.9486, 23.17235], [104.96532, 23.20463], [104.98712, 23.19176], [105.07002, 23.26248], [105.11672, 23.25247], [105.17276, 23.28679], [105.22569, 23.27249], [105.32376, 23.39684], [105.40782, 23.28107], [105.42805, 23.30824], [105.49966, 23.20669], [105.56037, 23.16806], [105.57594, 23.075], [105.72382, 23.06641], [105.8726, 22.92756], [105.90119, 22.94168], [105.99568, 22.94178], [106.00179, 22.99049], [106.19705, 22.98475], [106.27022, 22.87722], [106.34961, 22.86718], [106.49749, 22.91164], [106.51306, 22.94891], [106.55976, 22.92311], [106.60179, 22.92884], [106.6516, 22.86862], [106.6734, 22.89587], [106.71387, 22.88296], [106.71128, 22.85982], [106.78422, 22.81532], [106.81271, 22.8226], [106.83685, 22.8098], [106.82404, 22.7881], [106.76293, 22.73491], [106.72321, 22.63606], [106.71698, 22.58432], [106.65316, 22.5757], [106.61269, 22.60301], [106.58395, 22.474], [106.55665, 22.46498], [106.57221, 22.37], [106.55976, 22.34841], [106.6516, 22.33977], [106.69986, 22.22309], [106.67495, 22.1885], [106.6983, 22.15102], [106.70142, 22.02409], [106.68274, 21.99811], [106.69276, 21.96013], [106.72551, 21.97923], [106.74345, 22.00965], [106.81038, 21.97934], [106.9178, 21.97357], [106.92714, 21.93459], [106.97228, 21.92592], [106.99252, 21.95191], [107.05634, 21.92303], [107.06101, 21.88982], [107.00964, 21.85948], [107.02615, 21.81981], [107.10771, 21.79879], [107.20734, 21.71493], [107.24625, 21.7077], [107.29296, 21.74674], [107.35834, 21.6672], [107.35989, 21.60063], [107.38636, 21.59774], [107.41593, 21.64839], [107.47197, 21.6672], [107.49532, 21.62958], [107.49065, 21.59774], [107.54047, 21.5934], [107.56537, 21.61945], [107.66967, 21.60787], [107.80355, 21.66141], [107.86114, 21.65128], [107.90006, 21.5905], [107.92652, 21.58906], [107.95232, 21.5388], [107.96774, 21.53601], [107.97074, 21.54072], [107.97383, 21.53961], [107.97932, 21.54503], [108.02926, 21.54997], [108.0569, 21.53604], [108.10003, 21.47338], [108.00365, 17.98159], [111.60491, 13.57105], [118.41371, 24.06775], [118.11703, 24.39734], [118.28244, 24.51231], [118.35291, 24.51645], [118.42453, 24.54644], [118.56434, 24.49266], [120.49232, 25.22863], [121.03532, 26.8787], [123.5458, 31.01942], [122.29378, 31.76513], [122.80525, 33.30571], [123.85601, 37.49093], [123.90497, 38.79949], [124.17532, 39.8232], [124.23201, 39.9248], [124.35029, 39.95639], [124.37089, 40.03004], [124.3322, 40.05573], [124.38556, 40.11047], [124.40719, 40.13655], [124.86913, 40.45387], [125.71172, 40.85223], [125.76869, 40.87908], [126.00335, 40.92835], [126.242, 41.15454], [126.53189, 41.35206], [126.60631, 41.65565], [126.90729, 41.79955], [127.17841, 41.59714], [127.29712, 41.49473], [127.92943, 41.44291], [128.02633, 41.42103], [128.03311, 41.39232], [128.12967, 41.37931], [128.18546, 41.41279], [128.20061, 41.40895], [128.30716, 41.60322], [128.15119, 41.74568], [128.04487, 42.01769], [128.94007, 42.03537], [128.96068, 42.06657], [129.15178, 42.17224], [129.22285, 42.26491], [129.22423, 42.3553], [129.28541, 42.41574], [129.42882, 42.44702], [129.54701, 42.37254], [129.60482, 42.44461], [129.72541, 42.43739], [129.75294, 42.59409], [129.77183, 42.69435], [129.7835, 42.76521], [129.80719, 42.79218], [129.83277, 42.86746], [129.85261, 42.96494], [129.8865, 43.00395], [129.95082, 43.01051], [129.96409, 42.97306], [130.12957, 42.98361], [130.09764, 42.91425], [130.26095, 42.9027], [130.23068, 42.80125], [130.2385, 42.71127], [130.41826, 42.6011], [130.44361, 42.54849], [130.50123, 42.61636], [130.55143, 42.52158], [130.62107, 42.58413], [130.56576, 42.68925], [130.40213, 42.70788], [130.44361, 42.76205], [130.66524, 42.84753], [131.02438, 42.86518], [131.02668, 42.91246], [131.135, 42.94114], [131.10274, 43.04734], [131.20414, 43.13654], [131.19031, 43.21385], [131.30324, 43.39498], [131.29402, 43.46695], [131.19492, 43.53047], [131.21105, 43.82383], [131.26176, 43.94011], [131.23583, 43.96085], [131.25484, 44.03131], [131.30365, 44.04262], [131.1108, 44.70266], [130.95639, 44.85154], [131.48415, 44.99513], [131.68466, 45.12374], [131.66852, 45.2196], [131.76532, 45.22609], [131.86903, 45.33636], [131.99417, 45.2567], [132.83978, 45.05916], [132.96373, 45.0212], [133.12293, 45.1332], [133.09279, 45.25693], [133.19419, 45.51913], [133.41083, 45.57723], [133.48457, 45.86203], [133.60442, 45.90053], [133.67569, 45.9759], [133.72695, 46.05576], [133.68047, 46.14697], [133.88097, 46.25066], [133.91496, 46.4274], [133.84104, 46.46681], [134.03538, 46.75668], [134.20016, 47.33458], [134.50898, 47.4812], [134.7671, 47.72051], [134.55508, 47.98651], [134.67098, 48.1564], [134.75328, 48.36763], [134.49516, 48.42884], [132.66989, 47.96491], [132.57309, 47.71741], [131.90448, 47.68011], [131.2635, 47.73325], [131.09871, 47.6852], [130.95985, 47.6957], [130.90915, 47.90623], [130.65103, 48.10052], [130.84462, 48.30942], [130.52147, 48.61745], [130.66946, 48.88251], [130.43232, 48.90844], [130.2355, 48.86741], [129.85416, 49.11067], [129.67598, 49.29596], [129.50685, 49.42398], [129.40398, 49.44194], [129.35317, 49.3481], [129.23232, 49.40353], [129.11153, 49.36813], [128.72896, 49.58676], [127.83476, 49.5748], [127.53516, 49.84306], [127.49299, 50.01251], [127.60515, 50.23503], [127.37384, 50.28393], [127.36009, 50.43787], [127.28765, 50.46585], [127.36335, 50.58306], [127.28165, 50.72075], [127.14586, 50.91152], [126.93135, 51.0841], [126.90369, 51.3238], [126.68349, 51.70607], [126.44606, 51.98254], [126.558, 52.13738], [125.6131, 53.07229]], [[113.56865, 22.20973], [113.57123, 22.20416], [113.60504, 22.20464], [113.63011, 22.10782], [113.57191, 22.07696], [113.54839, 22.10909], [113.54942, 22.14519], [113.54093, 22.15497], [113.52659, 22.18271], [113.53552, 22.20607], [113.53301, 22.21235], [113.53591, 22.21369], [113.54093, 22.21314], [113.54333, 22.21688], [113.5508, 22.21672], [113.56865, 22.20973]], [[114.50148, 22.15017], [113.92195, 22.13873], [113.83338, 22.1826], [113.81621, 22.2163], [113.86771, 22.42972], [114.03113, 22.5065], [114.05438, 22.5026], [114.05729, 22.51104], [114.06272, 22.51617], [114.07267, 22.51855], [114.07817, 22.52997], [114.08606, 22.53276], [114.09048, 22.53716], [114.09692, 22.53435], [114.1034, 22.5352], [114.11181, 22.52878], [114.11656, 22.53415], [114.12665, 22.54003], [114.13823, 22.54319], [114.1482, 22.54091], [114.15123, 22.55163], [114.1597, 22.56041], [114.17247, 22.55944], [114.18338, 22.55444], [114.20655, 22.55706], [114.22185, 22.55343], [114.22888, 22.5436], [114.25154, 22.55977], [114.44998, 22.55977], [114.50148, 22.15017]]]]
22271           }
22272         }, {
22273           type: "Feature",
22274           properties: {
22275             wikidata: "Q22890",
22276             nameEn: "Ireland",
22277             level: "sharedLandform"
22278           },
22279           geometry: null
22280         }, {
22281           type: "Feature",
22282           properties: {
22283             wikidata: "Q23666",
22284             nameEn: "Great Britain",
22285             country: "GB",
22286             level: "sharedLandform"
22287           },
22288           geometry: null
22289         }, {
22290           type: "Feature",
22291           properties: {
22292             wikidata: "Q23681",
22293             nameEn: "Northern Cyprus",
22294             groups: ["Q644636", "145", "142"],
22295             driveSide: "left",
22296             callingCodes: ["90 392"]
22297           },
22298           geometry: {
22299             type: "MultiPolygon",
22300             coordinates: [[[[33.67678, 35.03866], [33.67742, 35.05963], [33.68474, 35.06602], [33.69095, 35.06237], [33.70861, 35.07644], [33.7161, 35.07279], [33.70209, 35.04882], [33.71482, 35.03722], [33.73824, 35.05321], [33.76106, 35.04253], [33.78581, 35.05104], [33.82067, 35.07826], [33.84168, 35.06823], [33.8541, 35.07201], [33.87479, 35.08881], [33.87097, 35.09389], [33.87622, 35.10457], [33.87224, 35.12293], [33.88561, 35.12449], [33.88943, 35.12007], [33.88737, 35.11408], [33.89853, 35.11377], [33.91789, 35.08688], [33.91299, 35.07579], [33.90247, 35.07686], [33.89485, 35.06873], [33.88367, 35.07877], [33.85261, 35.0574], [33.8355, 35.05777], [33.82051, 35.0667], [33.8012, 35.04786], [33.81524, 35.04192], [33.83055, 35.02865], [33.82875, 35.01685], [33.84045, 35.00616], [33.85216, 35.00579], [33.85891, 35.001], [33.85621, 34.98956], [33.83505, 34.98108], [33.84811, 34.97075], [33.86432, 34.97592], [33.90075, 34.96623], [33.98684, 34.76642], [35.48515, 34.70851], [35.51152, 36.10954], [32.82353, 35.70297], [32.46489, 35.48584], [32.60361, 35.16647], [32.64864, 35.19967], [32.70947, 35.18328], [32.70779, 35.14127], [32.85733, 35.07742], [32.86406, 35.1043], [32.94471, 35.09422], [33.01192, 35.15639], [33.08249, 35.17319], [33.11105, 35.15639], [33.15138, 35.19504], [33.27068, 35.16815], [33.3072, 35.16816], [33.31955, 35.18096], [33.35056, 35.18328], [33.34964, 35.17803], [33.35596, 35.17942], [33.35612, 35.17402], [33.36569, 35.17479], [33.3717, 35.1788], [33.37248, 35.18698], [33.38575, 35.2018], [33.4076, 35.20062], [33.41675, 35.16325], [33.46813, 35.10564], [33.48136, 35.0636], [33.47825, 35.04103], [33.45178, 35.02078], [33.45256, 35.00288], [33.47666, 35.00701], [33.48915, 35.06594], [33.53975, 35.08151], [33.57478, 35.06049], [33.567, 35.04803], [33.59658, 35.03635], [33.61215, 35.0527], [33.63765, 35.03869], [33.67678, 35.03866]]]]
22301           }
22302         }, {
22303           type: "Feature",
22304           properties: {
22305             wikidata: "Q25231",
22306             nameEn: "Svalbard",
22307             aliases: ["NO-21"],
22308             country: "NO",
22309             groups: ["SJ", "154", "150", "UN"],
22310             level: "subterritory",
22311             callingCodes: ["47 79"]
22312           },
22313           geometry: {
22314             type: "MultiPolygon",
22315             coordinates: [[[[-7.49892, 77.24208], [32.07813, 72.01005], [36.85549, 84.09565], [-7.49892, 77.24208]]]]
22316           }
22317         }, {
22318           type: "Feature",
22319           properties: {
22320             wikidata: "Q25263",
22321             nameEn: "Azores",
22322             aliases: ["PT-20"],
22323             country: "PT",
22324             groups: ["Q3320166", "Q2914565", "Q105472", "EU", "039", "150", "UN"],
22325             callingCodes: ["351"]
22326           },
22327           geometry: {
22328             type: "MultiPolygon",
22329             coordinates: [[[[-23.12984, 40.26428], [-36.43765, 41.39418], [-22.54767, 33.34416], [-23.12984, 40.26428]]]]
22330           }
22331         }, {
22332           type: "Feature",
22333           properties: {
22334             wikidata: "Q25359",
22335             nameEn: "Navassa Island",
22336             aliases: ["UM-76"],
22337             country: "US",
22338             groups: ["UM", "Q1352230", "029", "003", "419", "019", "UN"],
22339             level: "subterritory",
22340             roadSpeedUnit: "mph",
22341             roadHeightUnit: "ft"
22342           },
22343           geometry: {
22344             type: "MultiPolygon",
22345             coordinates: [[[[-74.7289, 18.71009], [-75.71816, 18.46438], [-74.76465, 18.06252], [-74.7289, 18.71009]]]]
22346           }
22347         }, {
22348           type: "Feature",
22349           properties: {
22350             wikidata: "Q25396",
22351             nameEn: "Bonaire",
22352             aliases: ["BQ-BO", "NL-BQ1"],
22353             country: "NL",
22354             groups: ["Q1451600", "BQ", "029", "003", "419", "019", "UN"],
22355             level: "subterritory",
22356             callingCodes: ["599 7"]
22357           },
22358           geometry: {
22359             type: "MultiPolygon",
22360             coordinates: [[[[-67.89186, 12.4116], [-68.90012, 12.62309], [-68.33524, 11.78151], [-68.01417, 11.77722], [-67.89186, 12.4116]]]]
22361           }
22362         }, {
22363           type: "Feature",
22364           properties: {
22365             wikidata: "Q25528",
22366             nameEn: "Saba",
22367             aliases: ["BQ-SA", "NL-BQ2"],
22368             country: "NL",
22369             groups: ["Q1451600", "BQ", "029", "003", "419", "019", "UN"],
22370             level: "subterritory",
22371             callingCodes: ["599 4"]
22372           },
22373           geometry: {
22374             type: "MultiPolygon",
22375             coordinates: [[[[-63.07669, 17.79659], [-63.81314, 17.95045], [-63.22932, 17.32592], [-63.07669, 17.79659]]]]
22376           }
22377         }, {
22378           type: "Feature",
22379           properties: {
22380             wikidata: "Q26180",
22381             nameEn: "Sint Eustatius",
22382             aliases: ["BQ-SE", "NL-BQ3"],
22383             country: "NL",
22384             groups: ["Q1451600", "BQ", "029", "003", "419", "019", "UN"],
22385             level: "subterritory",
22386             callingCodes: ["599 3"]
22387           },
22388           geometry: {
22389             type: "MultiPolygon",
22390             coordinates: [[[[-63.07669, 17.79659], [-63.34999, 16.94218], [-62.76692, 17.64353], [-63.07669, 17.79659]]]]
22391           }
22392         }, {
22393           type: "Feature",
22394           properties: {
22395             wikidata: "Q26253",
22396             nameEn: "Madeira",
22397             aliases: ["PT-30"],
22398             country: "PT",
22399             groups: ["Q3320166", "Q2914565", "Q105472", "EU", "039", "150", "UN"],
22400             callingCodes: ["351"]
22401           },
22402           geometry: {
22403             type: "MultiPolygon",
22404             coordinates: [[[[-19.30302, 33.65304], [-16.04789, 29.65076], [-11.68307, 33.12333], [-19.30302, 33.65304]]]]
22405           }
22406         }, {
22407           type: "Feature",
22408           properties: {
22409             wikidata: "Q26927",
22410             nameEn: "Lakshadweep",
22411             aliases: ["IN-LD"],
22412             country: "IN",
22413             groups: ["034", "142", "UN"],
22414             driveSide: "left",
22415             callingCodes: ["91"]
22416           },
22417           geometry: {
22418             type: "MultiPolygon",
22419             coordinates: [[[[67.64074, 11.57295], [76.59015, 5.591], [72.67494, 13.58102], [67.64074, 11.57295]]]]
22420           }
22421         }, {
22422           type: "Feature",
22423           properties: {
22424             wikidata: "Q27329",
22425             nameEn: "Asian Russia",
22426             country: "RU",
22427             groups: ["142", "UN"],
22428             callingCodes: ["7"]
22429           },
22430           geometry: {
22431             type: "MultiPolygon",
22432             coordinates: [[[[-179.99933, 64.74703], [-172.76104, 63.77445], [-169.03888, 65.48473], [-168.95635, 65.98512], [-168.25765, 71.99091], [-179.9843, 71.90735], [-179.99933, 64.74703]]], [[[59.99809, 51.98263], [60.19925, 51.99173], [60.48915, 52.15175], [60.72581, 52.15538], [60.78201, 52.22067], [61.05417, 52.35096], [60.98021, 52.50068], [60.84709, 52.52228], [60.84118, 52.63912], [60.71693, 52.66245], [60.71989, 52.75923], [61.05842, 52.92217], [61.23462, 53.03227], [62.0422, 52.96105], [62.12799, 52.99133], [62.14574, 53.09626], [61.19024, 53.30536], [61.14291, 53.41481], [61.29082, 53.50992], [61.37957, 53.45887], [61.57185, 53.50112], [61.55706, 53.57144], [60.90626, 53.62937], [61.22574, 53.80268], [61.14283, 53.90063], [60.99796, 53.93699], [61.26863, 53.92797], [61.3706, 54.08464], [61.47603, 54.08048], [61.56941, 53.95703], [61.65318, 54.02445], [62.03913, 53.94768], [62.00966, 54.04134], [62.38535, 54.03961], [62.45931, 53.90737], [62.56876, 53.94047], [62.58651, 54.05871], [63.80604, 54.27079], [63.91224, 54.20013], [64.02715, 54.22679], [63.97686, 54.29763], [64.97216, 54.4212], [65.11033, 54.33028], [65.24663, 54.35721], [65.20174, 54.55216], [68.21308, 54.98645], [68.26661, 55.09226], [68.19206, 55.18823], [68.90865, 55.38148], [69.34224, 55.36344], [69.74917, 55.35545], [70.19179, 55.1476], [70.76493, 55.3027], [70.96009, 55.10558], [71.08288, 54.71253], [71.24185, 54.64965], [71.08706, 54.33376], [71.10379, 54.13326], [71.96141, 54.17736], [72.17477, 54.36303], [72.43415, 53.92685], [72.71026, 54.1161], [73.37963, 53.96132], [73.74778, 54.07194], [73.68921, 53.86522], [73.25412, 53.61532], [73.39218, 53.44623], [75.07405, 53.80831], [75.43398, 53.98652], [75.3668, 54.07439], [76.91052, 54.4677], [76.82266, 54.1798], [76.44076, 54.16017], [76.54243, 53.99329], [77.90383, 53.29807], [79.11255, 52.01171], [80.08138, 50.77658], [80.4127, 50.95581], [80.44819, 51.20855], [80.80318, 51.28262], [81.16999, 51.15662], [81.06091, 50.94833], [81.41248, 50.97524], [81.46581, 50.77658], [81.94999, 50.79307], [82.55443, 50.75412], [83.14607, 51.00796], [83.8442, 50.87375], [84.29385, 50.27257], [84.99198, 50.06793], [85.24047, 49.60239], [86.18709, 49.50259], [86.63674, 49.80136], [86.79056, 49.74787], [86.61307, 49.60239], [86.82606, 49.51796], [87.03071, 49.25142], [87.31465, 49.23603], [87.28386, 49.11626], [87.478, 49.07403], [87.48983, 49.13794], [87.81333, 49.17354], [87.98977, 49.18147], [88.15543, 49.30314], [88.17223, 49.46934], [88.42449, 49.48821], [88.82499, 49.44808], [89.70687, 49.72535], [89.59711, 49.90851], [91.86048, 50.73734], [92.07173, 50.69585], [92.44714, 50.78762], [93.01109, 50.79001], [92.99595, 50.63183], [94.30823, 50.57498], [94.39258, 50.22193], [94.49477, 50.17832], [94.6121, 50.04239], [94.97166, 50.04725], [95.02465, 49.96941], [95.74757, 49.97915], [95.80056, 50.04239], [96.97388, 49.88413], [97.24639, 49.74737], [97.56811, 49.84265], [97.56432, 49.92801], [97.76871, 49.99861], [97.85197, 49.91339], [98.29481, 50.33561], [98.31373, 50.4996], [98.06393, 50.61262], [97.9693, 50.78044], [98.01472, 50.86652], [97.83305, 51.00248], [98.05257, 51.46696], [98.22053, 51.46579], [98.33222, 51.71832], [98.74142, 51.8637], [98.87768, 52.14563], [99.27888, 51.96876], [99.75578, 51.90108], [99.89203, 51.74903], [100.61116, 51.73028], [101.39085, 51.45753], [101.5044, 51.50467], [102.14032, 51.35566], [102.32194, 50.67982], [102.71178, 50.38873], [103.70343, 50.13952], [105.32528, 50.4648], [106.05562, 50.40582], [106.07865, 50.33474], [106.47156, 50.31909], [106.49628, 50.32436], [106.51122, 50.34408], [106.58373, 50.34044], [106.80326, 50.30177], [107.00007, 50.1977], [107.1174, 50.04239], [107.36407, 49.97612], [107.96116, 49.93191], [107.95387, 49.66659], [108.27937, 49.53167], [108.53969, 49.32325], [109.18017, 49.34709], [109.51325, 49.22859], [110.24373, 49.16676], [110.39891, 49.25083], [110.64493, 49.1816], [113.02647, 49.60772], [113.20216, 49.83356], [114.325, 50.28098], [114.9703, 50.19254], [115.26068, 49.97367], [115.73602, 49.87688], [116.22402, 50.04477], [116.62502, 49.92919], [116.71193, 49.83813], [117.27597, 49.62544], [117.48208, 49.62324], [117.82343, 49.52696], [118.61623, 49.93809], [119.11003, 50.00276], [119.27996, 50.13348], [119.38598, 50.35162], [119.13553, 50.37412], [120.10963, 51.671], [120.65907, 51.93544], [120.77337, 52.20805], [120.61346, 52.32447], [120.71673, 52.54099], [120.46454, 52.63811], [120.04049, 52.58773], [120.0451, 52.7359], [120.85633, 53.28499], [121.39213, 53.31888], [122.35063, 53.49565], [122.85966, 53.47395], [123.26989, 53.54843], [123.86158, 53.49391], [124.46078, 53.21881], [125.17522, 53.20225], [125.6131, 53.07229], [126.558, 52.13738], [126.44606, 51.98254], [126.68349, 51.70607], [126.90369, 51.3238], [126.93135, 51.0841], [127.14586, 50.91152], [127.28165, 50.72075], [127.36335, 50.58306], [127.28765, 50.46585], [127.36009, 50.43787], [127.37384, 50.28393], [127.60515, 50.23503], [127.49299, 50.01251], [127.53516, 49.84306], [127.83476, 49.5748], [128.72896, 49.58676], [129.11153, 49.36813], [129.23232, 49.40353], [129.35317, 49.3481], [129.40398, 49.44194], [129.50685, 49.42398], [129.67598, 49.29596], [129.85416, 49.11067], [130.2355, 48.86741], [130.43232, 48.90844], [130.66946, 48.88251], [130.52147, 48.61745], [130.84462, 48.30942], [130.65103, 48.10052], [130.90915, 47.90623], [130.95985, 47.6957], [131.09871, 47.6852], [131.2635, 47.73325], [131.90448, 47.68011], [132.57309, 47.71741], [132.66989, 47.96491], [134.49516, 48.42884], [134.75328, 48.36763], [134.67098, 48.1564], [134.55508, 47.98651], [134.7671, 47.72051], [134.50898, 47.4812], [134.20016, 47.33458], [134.03538, 46.75668], [133.84104, 46.46681], [133.91496, 46.4274], [133.88097, 46.25066], [133.68047, 46.14697], [133.72695, 46.05576], [133.67569, 45.9759], [133.60442, 45.90053], [133.48457, 45.86203], [133.41083, 45.57723], [133.19419, 45.51913], [133.09279, 45.25693], [133.12293, 45.1332], [132.96373, 45.0212], [132.83978, 45.05916], [131.99417, 45.2567], [131.86903, 45.33636], [131.76532, 45.22609], [131.66852, 45.2196], [131.68466, 45.12374], [131.48415, 44.99513], [130.95639, 44.85154], [131.1108, 44.70266], [131.30365, 44.04262], [131.25484, 44.03131], [131.23583, 43.96085], [131.26176, 43.94011], [131.21105, 43.82383], [131.19492, 43.53047], [131.29402, 43.46695], [131.30324, 43.39498], [131.19031, 43.21385], [131.20414, 43.13654], [131.10274, 43.04734], [131.135, 42.94114], [131.02668, 42.91246], [131.02438, 42.86518], [130.66524, 42.84753], [130.44361, 42.76205], [130.40213, 42.70788], [130.56576, 42.68925], [130.62107, 42.58413], [130.55143, 42.52158], [130.56835, 42.43281], [130.60805, 42.4317], [130.64181, 42.41422], [130.66367, 42.38024], [130.65022, 42.32281], [131.95041, 41.5445], [140.9182, 45.92937], [145.82343, 44.571], [145.23667, 43.76813], [153.94307, 38.42848], [180, 62.52334], [180, 71.53642], [155.31937, 81.93282], [76.13964, 83.37843], [64.18965, 69.94255], [66.1708, 67.61252], [61.98014, 65.72191], [60.74386, 64.95767], [59.63945, 64.78384], [59.80579, 64.13948], [59.24834, 63.01859], [59.61398, 62.44915], [59.36223, 61.3882], [59.50685, 60.91162], [58.3853, 59.487], [59.15636, 59.14682], [59.40376, 58.45822], [58.71104, 58.07475], [58.81412, 57.71602], [58.13789, 57.68097], [58.07604, 57.08308], [57.28024, 56.87898], [57.51527, 56.08729], [59.28419, 56.15739], [59.49035, 55.60486], [58.81825, 55.03378], [57.25137, 55.26262], [57.14829, 54.84204], [57.95234, 54.39672], [59.95217, 54.85853], [59.70487, 54.14846], [58.94336, 53.953], [58.79644, 52.43392], [59.22409, 52.28437], [59.25033, 52.46803], [60.17516, 52.39457], [60.17253, 52.25814], [59.91279, 52.06924], [59.99809, 51.98263]]]]
22433           }
22434         }, {
22435           type: "Feature",
22436           properties: {
22437             wikidata: "Q34366",
22438             nameEn: "Tasmania",
22439             aliases: ["AU-TAS"],
22440             country: "AU",
22441             groups: ["053", "009", "UN"],
22442             driveSide: "left",
22443             callingCodes: ["61"]
22444           },
22445           geometry: {
22446             type: "MultiPolygon",
22447             coordinates: [[[[123.64533, -39.13605], [159.69067, -56.28945], [159.74028, -39.1978], [123.64533, -39.13605]]]]
22448           }
22449         }, {
22450           type: "Feature",
22451           properties: {
22452             wikidata: "Q34497",
22453             nameEn: "Saint Helena",
22454             aliases: ["SH-HL"],
22455             country: "GB",
22456             groups: ["SH", "BOTS", "011", "202", "002", "UN"],
22457             level: "subterritory",
22458             driveSide: "left",
22459             roadSpeedUnit: "mph",
22460             roadHeightUnit: "ft",
22461             callingCodes: ["290"]
22462           },
22463           geometry: {
22464             type: "MultiPolygon",
22465             coordinates: [[[[-8.3824, -13.9131], [-6.17428, -19.07236], [-3.29308, -15.22647], [-8.3824, -13.9131]]]]
22466           }
22467         }, {
22468           type: "Feature",
22469           properties: {
22470             wikidata: "Q35657",
22471             nameEn: "US States",
22472             country: "US",
22473             level: "subcountryGroup"
22474           },
22475           geometry: null
22476         }, {
22477           type: "Feature",
22478           properties: {
22479             wikidata: "Q36117",
22480             nameEn: "Borneo",
22481             level: "sharedLandform"
22482           },
22483           geometry: null
22484         }, {
22485           type: "Feature",
22486           properties: {
22487             wikidata: "Q36678",
22488             nameEn: "West Bank",
22489             country: "PS",
22490             groups: ["145", "142"],
22491             callingCodes: ["970"]
22492           },
22493           geometry: {
22494             type: "MultiPolygon",
22495             coordinates: [[[[35.47672, 31.49578], [35.55941, 31.76535], [35.52758, 31.9131], [35.54375, 31.96587], [35.52012, 32.04076], [35.57111, 32.21877], [35.55807, 32.38674], [35.42078, 32.41562], [35.41048, 32.43706], [35.41598, 32.45593], [35.42034, 32.46009], [35.40224, 32.50136], [35.35212, 32.52047], [35.30685, 32.51024], [35.29306, 32.50947], [35.25049, 32.52453], [35.2244, 32.55289], [35.15937, 32.50466], [35.10882, 32.4757], [35.10024, 32.47856], [35.09236, 32.47614], [35.08564, 32.46948], [35.07059, 32.4585], [35.05423, 32.41754], [35.05311, 32.4024], [35.0421, 32.38242], [35.05142, 32.3667], [35.04243, 32.35008], [35.01772, 32.33863], [35.01119, 32.28684], [35.02939, 32.2671], [35.01841, 32.23981], [34.98885, 32.20758], [34.95703, 32.19522], [34.96009, 32.17503], [34.99039, 32.14626], [34.98507, 32.12606], [34.99437, 32.10962], [34.9863, 32.09551], [35.00261, 32.027], [34.98682, 31.96935], [35.00124, 31.93264], [35.03489, 31.92448], [35.03978, 31.89276], [35.03489, 31.85919], [34.99712, 31.85569], [34.9724, 31.83352], [35.01978, 31.82944], [35.05617, 31.85685], [35.07677, 31.85627], [35.14174, 31.81325], [35.18603, 31.80901], [35.18169, 31.82542], [35.19461, 31.82687], [35.21469, 31.81835], [35.216, 31.83894], [35.21128, 31.863], [35.20381, 31.86716], [35.20673, 31.88151], [35.20791, 31.8821], [35.20945, 31.8815], [35.21016, 31.88237], [35.21276, 31.88153], [35.2136, 31.88241], [35.22014, 31.88264], [35.22294, 31.87889], [35.22567, 31.86745], [35.22817, 31.8638], [35.2249, 31.85433], [35.2304, 31.84222], [35.24816, 31.8458], [35.25753, 31.8387], [35.251, 31.83085], [35.26404, 31.82567], [35.25573, 31.81362], [35.26058, 31.79064], [35.25225, 31.7678], [35.26319, 31.74846], [35.25182, 31.73945], [35.24981, 31.72543], [35.2438, 31.7201], [35.24315, 31.71244], [35.23972, 31.70896], [35.22392, 31.71899], [35.21937, 31.71578], [35.20538, 31.72388], [35.18023, 31.72067], [35.16478, 31.73242], [35.15474, 31.73352], [35.15119, 31.73634], [35.13931, 31.73012], [35.12933, 31.7325], [35.11895, 31.71454], [35.10782, 31.71594], [35.08226, 31.69107], [35.00879, 31.65426], [34.95249, 31.59813], [34.9415, 31.55601], [34.94356, 31.50743], [34.93258, 31.47816], [34.89756, 31.43891], [34.87833, 31.39321], [34.88932, 31.37093], [34.92571, 31.34337], [35.02459, 31.35979], [35.13033, 31.3551], [35.22921, 31.37445], [35.39675, 31.49572], [35.47672, 31.49578]]]]
22496           }
22497         }, {
22498           type: "Feature",
22499           properties: {
22500             wikidata: "Q37362",
22501             nameEn: "Akrotiri and Dhekelia",
22502             aliases: ["SBA"],
22503             country: "GB"
22504           },
22505           geometry: null
22506         }, {
22507           type: "Feature",
22508           properties: {
22509             wikidata: "Q38095",
22510             nameEn: "Gal\xE1pagos Islands",
22511             aliases: ["EC-W"],
22512             country: "EC",
22513             groups: ["005", "419", "019", "UN"],
22514             callingCodes: ["593"]
22515           },
22516           geometry: {
22517             type: "MultiPolygon",
22518             coordinates: [[[[-93.12365, 2.64343], [-92.46744, -2.52874], [-87.07749, -0.8849], [-93.12365, 2.64343]]]]
22519           }
22520         }, {
22521           type: "Feature",
22522           properties: {
22523             wikidata: "Q39760",
22524             nameEn: "Gaza Strip",
22525             country: "PS",
22526             groups: ["145", "142"],
22527             callingCodes: ["970"]
22528           },
22529           geometry: {
22530             type: "MultiPolygon",
22531             coordinates: [[[[34.052, 31.46619], [34.21853, 31.32363], [34.23572, 31.2966], [34.24012, 31.29591], [34.26742, 31.21998], [34.29417, 31.24194], [34.36523, 31.28963], [34.37381, 31.30598], [34.36505, 31.36404], [34.40077, 31.40926], [34.48892, 31.48365], [34.56797, 31.54197], [34.48681, 31.59711], [34.29262, 31.70393], [34.052, 31.46619]]]]
22532           }
22533         }, {
22534           type: "Feature",
22535           properties: {
22536             wikidata: "Q40888",
22537             nameEn: "Andaman and Nicobar Islands",
22538             aliases: ["IN-AN"],
22539             country: "IN",
22540             groups: ["034", "142", "UN"],
22541             driveSide: "left",
22542             callingCodes: ["91"]
22543           },
22544           geometry: {
22545             type: "MultiPolygon",
22546             coordinates: [[[[94.42132, 5.96581], [94.6371, 13.81803], [86.7822, 13.41052], [94.42132, 5.96581]]]]
22547           }
22548         }, {
22549           type: "Feature",
22550           properties: {
22551             wikidata: "Q41684",
22552             nameEn: "Stewart Island",
22553             country: "NZ",
22554             groups: ["053", "009", "UN"],
22555             driveSide: "left",
22556             callingCodes: ["64"]
22557           },
22558           geometry: {
22559             type: "MultiPolygon",
22560             coordinates: [[[[166.59185, -47.61313], [169.70504, -47.56021], [167.52103, -46.41337], [166.59185, -47.61313]]]]
22561           }
22562         }, {
22563           type: "Feature",
22564           properties: {
22565             wikidata: "Q43296",
22566             nameEn: "Wake Island",
22567             aliases: ["WK", "WAK", "WKUM", "872", "UM-79"],
22568             country: "US",
22569             groups: ["UM", "Q1352230", "057", "009", "UN"],
22570             level: "subterritory",
22571             roadSpeedUnit: "mph",
22572             roadHeightUnit: "ft",
22573             callingCodes: ["1"]
22574           },
22575           geometry: {
22576             type: "MultiPolygon",
22577             coordinates: [[[[167.34779, 18.97692], [166.67967, 20.14834], [165.82549, 18.97692], [167.34779, 18.97692]]]]
22578           }
22579         }, {
22580           type: "Feature",
22581           properties: {
22582             wikidata: "Q46275",
22583             nameEn: "New Zealand Subantarctic Islands",
22584             country: "NZ",
22585             groups: ["Q851132", "053", "009", "UN"],
22586             driveSide: "left"
22587           },
22588           geometry: {
22589             type: "MultiPolygon",
22590             coordinates: [[[[164.30551, -47.88072], [161.96603, -56.07661], [179.49541, -50.04657], [179.49541, -47.2902], [169.91032, -47.66283], [164.30551, -47.88072]]]]
22591           }
22592         }, {
22593           type: "Feature",
22594           properties: {
22595             wikidata: "Q46395",
22596             nameEn: "British Overseas Territories",
22597             aliases: ["BOTS", "UKOTS"],
22598             country: "GB",
22599             level: "subcountryGroup"
22600           },
22601           geometry: null
22602         }, {
22603           type: "Feature",
22604           properties: {
22605             wikidata: "Q46772",
22606             nameEn: "Kerguelen Islands",
22607             country: "FR",
22608             groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
22609             level: "subterritory"
22610           },
22611           geometry: {
22612             type: "MultiPolygon",
22613             coordinates: [[[[61.9216, -49.39746], [70.67507, -51.14192], [74.25129, -45.45074], [61.9216, -49.39746]]]]
22614           }
22615         }, {
22616           type: "Feature",
22617           properties: {
22618             wikidata: "Q46879",
22619             nameEn: "Baker Island",
22620             aliases: ["UM-81"],
22621             country: "US",
22622             groups: ["UM", "Q1352230", "061", "009", "UN"],
22623             level: "subterritory",
22624             roadSpeedUnit: "mph",
22625             roadHeightUnit: "ft"
22626           },
22627           geometry: {
22628             type: "MultiPolygon",
22629             coordinates: [[[[-175.33482, -1.40631], [-175.31323, 0.5442], [-177.91421, 0.39582], [-175.33482, -1.40631]]]]
22630           }
22631         }, {
22632           type: "Feature",
22633           properties: {
22634             wikidata: "Q47863",
22635             nameEn: "Midway Atoll",
22636             aliases: ["MI", "MID", "MIUM", "488", "UM-71"],
22637             country: "US",
22638             groups: ["UM", "Q1352230", "061", "009", "UN"],
22639             level: "subterritory",
22640             roadSpeedUnit: "mph",
22641             roadHeightUnit: "ft",
22642             callingCodes: ["1"]
22643           },
22644           geometry: {
22645             type: "MultiPolygon",
22646             coordinates: [[[[-176.29741, 29.09786], [-177.77531, 29.29793], [-177.5224, 27.7635], [-176.29741, 29.09786]]]]
22647           }
22648         }, {
22649           type: "Feature",
22650           properties: {
22651             wikidata: "Q62218",
22652             nameEn: "Jarvis Island",
22653             aliases: ["UM-86"],
22654             country: "US",
22655             groups: ["UM", "Q1352230", "061", "009", "UN"],
22656             level: "subterritory",
22657             roadSpeedUnit: "mph",
22658             roadHeightUnit: "ft"
22659           },
22660           geometry: {
22661             type: "MultiPolygon",
22662             coordinates: [[[[-160.42921, -1.4364], [-159.12443, 0.19975], [-160.38779, 0.30331], [-160.42921, -1.4364]]]]
22663           }
22664         }, {
22665           type: "Feature",
22666           properties: {
22667             wikidata: "Q105472",
22668             nameEn: "Macaronesia",
22669             level: "sharedLandform"
22670           },
22671           geometry: null
22672         }, {
22673           type: "Feature",
22674           properties: {
22675             wikidata: "Q114935",
22676             nameEn: "Kermadec Islands",
22677             country: "NZ",
22678             groups: ["Q851132", "053", "009", "UN"],
22679             driveSide: "left",
22680             callingCodes: ["64"]
22681           },
22682           geometry: {
22683             type: "MultiPolygon",
22684             coordinates: [[[[-174.40891, -29.09438], [-180, -24.21376], [-179.96512, -35.00791], [-174.40891, -29.09438]]]]
22685           }
22686         }, {
22687           type: "Feature",
22688           properties: {
22689             wikidata: "Q115459",
22690             nameEn: "Chatham Islands",
22691             aliases: ["NZ-CIT"],
22692             country: "NZ",
22693             groups: ["Q851132", "053", "009", "UN"],
22694             driveSide: "left",
22695             callingCodes: ["64"]
22696           },
22697           geometry: {
22698             type: "MultiPolygon",
22699             coordinates: [[[[-179.93224, -45.18423], [-172.47015, -45.17912], [-176.30998, -41.38382], [-179.93224, -45.18423]]]]
22700           }
22701         }, {
22702           type: "Feature",
22703           properties: {
22704             wikidata: "Q118863",
22705             nameEn: "North Island",
22706             country: "NZ",
22707             groups: ["053", "009", "UN"],
22708             driveSide: "left",
22709             callingCodes: ["64"]
22710           },
22711           geometry: {
22712             type: "MultiPolygon",
22713             coordinates: [[[[179.49541, -47.2902], [179.49541, -36.79303], [174.17679, -32.62487], [170.27492, -36.38133], [174.58663, -40.80446], [174.46634, -41.55028], [179.49541, -47.2902]]]]
22714           }
22715         }, {
22716           type: "Feature",
22717           properties: {
22718             wikidata: "Q120755",
22719             nameEn: "South Island",
22720             country: "NZ",
22721             groups: ["053", "009", "UN"],
22722             driveSide: "left",
22723             callingCodes: ["64"]
22724           },
22725           geometry: {
22726             type: "MultiPolygon",
22727             coordinates: [[[[169.70504, -47.56021], [179.49541, -47.2902], [174.46634, -41.55028], [174.58663, -40.80446], [170.27492, -36.38133], [166.56976, -39.94841], [164.8365, -46.0205], [167.52103, -46.41337], [169.70504, -47.56021]]]]
22728           }
22729         }, {
22730           type: "Feature",
22731           properties: {
22732             wikidata: "Q123076",
22733             nameEn: "Palmyra Atoll",
22734             aliases: ["UM-95"],
22735             country: "US",
22736             groups: ["UM", "Q1352230", "061", "009", "UN"],
22737             level: "subterritory",
22738             roadSpeedUnit: "mph",
22739             roadHeightUnit: "ft",
22740             callingCodes: ["1"]
22741           },
22742           geometry: {
22743             type: "MultiPolygon",
22744             coordinates: [[[[-161.06795, 5.2462], [-161.0731, 7.1291], [-163.24478, 5.24198], [-161.06795, 5.2462]]]]
22745           }
22746         }, {
22747           type: "Feature",
22748           properties: {
22749             wikidata: "Q130574",
22750             nameEn: "Chafarinas Islands",
22751             country: "ES",
22752             groups: ["EU", "Q191011", "015", "002", "UN"],
22753             level: "subterritory"
22754           },
22755           geometry: {
22756             type: "MultiPolygon",
22757             coordinates: [[[[-2.40316, 35.16893], [-2.43262, 35.20652], [-2.45965, 35.16527], [-2.40316, 35.16893]]]]
22758           }
22759         }, {
22760           type: "Feature",
22761           properties: {
22762             wikidata: "Q130895",
22763             nameEn: "Kingman Reef",
22764             aliases: ["UM-89"],
22765             country: "US",
22766             groups: ["UM", "Q1352230", "061", "009", "UN"],
22767             level: "subterritory",
22768             roadSpeedUnit: "mph",
22769             roadHeightUnit: "ft"
22770           },
22771           geometry: {
22772             type: "MultiPolygon",
22773             coordinates: [[[[-161.0731, 7.1291], [-163.16627, 7.15036], [-163.24478, 5.24198], [-161.0731, 7.1291]]]]
22774           }
22775         }, {
22776           type: "Feature",
22777           properties: {
22778             wikidata: "Q131008",
22779             nameEn: "Johnston Atoll",
22780             aliases: ["JT", "JTN", "JTUM", "396", "UM-67"],
22781             country: "US",
22782             groups: ["UM", "Q1352230", "061", "009", "UN"],
22783             level: "subterritory",
22784             roadSpeedUnit: "mph",
22785             roadHeightUnit: "ft",
22786             callingCodes: ["1"]
22787           },
22788           geometry: {
22789             type: "MultiPolygon",
22790             coordinates: [[[[-170.65691, 16.57199], [-168.87689, 16.01159], [-169.2329, 17.4933], [-170.65691, 16.57199]]]]
22791           }
22792         }, {
22793           type: "Feature",
22794           properties: {
22795             wikidata: "Q131305",
22796             nameEn: "Howland Island",
22797             aliases: ["UM-84"],
22798             country: "US",
22799             groups: ["UM", "Q1352230", "061", "009", "UN"],
22800             level: "subterritory",
22801             roadSpeedUnit: "mph",
22802             roadHeightUnit: "ft"
22803           },
22804           geometry: {
22805             type: "MultiPolygon",
22806             coordinates: [[[[-177.91421, 0.39582], [-175.31323, 0.5442], [-176.74464, 2.28109], [-177.91421, 0.39582]]]]
22807           }
22808         }, {
22809           type: "Feature",
22810           properties: {
22811             wikidata: "Q133888",
22812             nameEn: "Ashmore and Cartier Islands",
22813             country: "AU",
22814             groups: ["053", "009", "UN"],
22815             driveSide: "left",
22816             callingCodes: ["61"]
22817           },
22818           geometry: {
22819             type: "MultiPolygon",
22820             coordinates: [[[[123.7463, -11.1783], [120.6877, -13.59408], [125.29076, -12.33139], [123.7463, -11.1783]]]]
22821           }
22822         }, {
22823           type: "Feature",
22824           properties: {
22825             wikidata: "Q153732",
22826             nameEn: "Mariana Islands",
22827             level: "sharedLandform"
22828           },
22829           geometry: null
22830         }, {
22831           type: "Feature",
22832           properties: {
22833             wikidata: "Q172216",
22834             nameEn: "Coral Sea Islands",
22835             country: "AU",
22836             groups: ["053", "009", "UN"],
22837             driveSide: "left",
22838             callingCodes: ["61"]
22839           },
22840           geometry: {
22841             type: "MultiPolygon",
22842             coordinates: [[[[159.77159, -28.41151], [156.73836, -14.50464], [145.2855, -9.62524], [147.69992, -17.5933], [152.93188, -20.92631], [154.02855, -24.43238], [159.77159, -28.41151]]]]
22843           }
22844         }, {
22845           type: "Feature",
22846           properties: {
22847             wikidata: "Q179313",
22848             nameEn: "Alderney",
22849             country: "GB",
22850             groups: ["GG", "830", "Q185086", "154", "150", "UN"],
22851             level: "subterritory",
22852             driveSide: "left",
22853             roadSpeedUnit: "mph",
22854             roadHeightUnit: "ft",
22855             callingCodes: ["44 01481"]
22856           },
22857           geometry: {
22858             type: "MultiPolygon",
22859             coordinates: [[[[-2.36485, 49.48223], [-2.09454, 49.46288], [-2.02963, 49.91866], [-2.49556, 49.79012], [-2.36485, 49.48223]]]]
22860           }
22861         }, {
22862           type: "Feature",
22863           properties: {
22864             wikidata: "Q185086",
22865             nameEn: "Crown Dependencies",
22866             country: "GB",
22867             level: "subcountryGroup"
22868           },
22869           geometry: null
22870         }, {
22871           type: "Feature",
22872           properties: {
22873             wikidata: "Q190571",
22874             nameEn: "Scattered Islands",
22875             country: "FR",
22876             groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
22877             level: "subterritory"
22878           },
22879           geometry: {
22880             type: "MultiPolygon",
22881             coordinates: [[[[53.53458, -16.36909], [54.96649, -16.28353], [54.61476, -15.02273], [53.53458, -16.36909]]], [[[38.55969, -20.75596], [40.68027, -23.38889], [43.52893, -15.62903], [38.55969, -20.75596]]], [[[47.03092, -11.05648], [47.11593, -12.08552], [47.96702, -11.46447], [47.03092, -11.05648]]]]
22882           }
22883         }, {
22884           type: "Feature",
22885           properties: {
22886             wikidata: "Q191011",
22887             nameEn: "Plazas de soberan\xEDa",
22888             country: "ES"
22889           },
22890           geometry: null
22891         }, {
22892           type: "Feature",
22893           properties: {
22894             wikidata: "Q191146",
22895             nameEn: "Pe\xF1\xF3n de V\xE9lez de la Gomera",
22896             country: "ES",
22897             groups: ["EU", "Q191011", "015", "002", "UN"],
22898             level: "subterritory"
22899           },
22900           geometry: {
22901             type: "MultiPolygon",
22902             coordinates: [[[[-4.30191, 35.17419], [-4.30112, 35.17058], [-4.29436, 35.17149], [-4.30191, 35.17419]]]]
22903           }
22904         }, {
22905           type: "Feature",
22906           properties: {
22907             wikidata: "Q201698",
22908             nameEn: "Crozet Islands",
22909             country: "FR",
22910             groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
22911             level: "subterritory"
22912           },
22913           geometry: {
22914             type: "MultiPolygon",
22915             coordinates: [[[[55.03425, -43.65017], [46.31615, -46.28749], [54.5587, -47.93013], [55.03425, -43.65017]]]]
22916           }
22917         }, {
22918           type: "Feature",
22919           properties: {
22920             wikidata: "Q578170",
22921             nameEn: "Contiguous United States",
22922             aliases: ["CONUS"],
22923             country: "US",
22924             groups: ["Q35657", "021", "003", "019", "UN"],
22925             roadSpeedUnit: "mph",
22926             roadHeightUnit: "ft",
22927             callingCodes: ["1"]
22928           },
22929           geometry: {
22930             type: "MultiPolygon",
22931             coordinates: [[[[-97.13927, 25.96583], [-96.92418, 25.97377], [-80.57035, 24.0565], [-78.91214, 27.76553], [-61.98255, 37.34815], [-67.16117, 44.20069], [-66.93432, 44.82597], [-66.96824, 44.83078], [-66.98249, 44.87071], [-66.96824, 44.90965], [-67.0216, 44.95333], [-67.11316, 45.11176], [-67.15965, 45.16179], [-67.19603, 45.16771], [-67.20349, 45.1722], [-67.22751, 45.16344], [-67.27039, 45.1934], [-67.29748, 45.18173], [-67.29754, 45.14865], [-67.34927, 45.122], [-67.48201, 45.27351], [-67.42394, 45.37969], [-67.50578, 45.48971], [-67.42144, 45.50584], [-67.43815, 45.59162], [-67.6049, 45.60725], [-67.80705, 45.69528], [-67.80653, 45.80022], [-67.75654, 45.82324], [-67.80961, 45.87531], [-67.75196, 45.91814], [-67.78111, 45.9392], [-67.78578, 47.06473], [-67.87993, 47.10377], [-67.94843, 47.1925], [-68.23244, 47.35712], [-68.37458, 47.35851], [-68.38332, 47.28723], [-68.57914, 47.28431], [-68.60575, 47.24659], [-68.70125, 47.24399], [-68.89222, 47.1807], [-69.05039, 47.2456], [-69.05073, 47.30076], [-69.05148, 47.42012], [-69.22119, 47.46461], [-69.99966, 46.69543], [-70.05812, 46.41768], [-70.18547, 46.35357], [-70.29078, 46.18832], [-70.23855, 46.1453], [-70.31025, 45.96424], [-70.24694, 45.95138], [-70.25976, 45.89675], [-70.41523, 45.79497], [-70.38934, 45.73215], [-70.54019, 45.67291], [-70.68516, 45.56964], [-70.72651, 45.49771], [-70.62518, 45.42286], [-70.65383, 45.37592], [-70.78372, 45.43269], [-70.82638, 45.39828], [-70.80236, 45.37444], [-70.84816, 45.22698], [-70.89864, 45.2398], [-70.91169, 45.29849], [-70.95193, 45.33895], [-71.0107, 45.34819], [-71.01866, 45.31573], [-71.08364, 45.30623], [-71.14568, 45.24128], [-71.19723, 45.25438], [-71.22338, 45.25184], [-71.29371, 45.29996], [-71.37133, 45.24624], [-71.44252, 45.2361], [-71.40364, 45.21382], [-71.42778, 45.12624], [-71.48735, 45.07784], [-71.50067, 45.01357], [-73.35025, 45.00942], [-74.32699, 44.99029], [-74.66689, 45.00646], [-74.8447, 45.00606], [-74.99101, 44.98051], [-75.01363, 44.95608], [-75.2193, 44.87821], [-75.41441, 44.76614], [-75.76813, 44.51537], [-75.8217, 44.43176], [-75.95947, 44.34463], [-76.00018, 44.34896], [-76.16285, 44.28262], [-76.1664, 44.23051], [-76.244, 44.19643], [-76.31222, 44.19894], [-76.35324, 44.13493], [-76.43859, 44.09393], [-76.79706, 43.63099], [-79.25796, 43.54052], [-79.06921, 43.26183], [-79.05512, 43.25375], [-79.05544, 43.21224], [-79.05002, 43.20133], [-79.05384, 43.17418], [-79.04652, 43.16396], [-79.0427, 43.13934], [-79.06881, 43.12029], [-79.05671, 43.10937], [-79.07486, 43.07845], [-79.01055, 43.06659], [-78.99941, 43.05612], [-79.02424, 43.01983], [-79.02074, 42.98444], [-78.98126, 42.97], [-78.96312, 42.95509], [-78.93224, 42.95229], [-78.90905, 42.93022], [-78.90712, 42.89733], [-78.93684, 42.82887], [-82.67862, 41.67615], [-83.11184, 41.95671], [-83.14962, 42.04089], [-83.12724, 42.2376], [-83.09837, 42.28877], [-83.07837, 42.30978], [-83.02253, 42.33045], [-82.82964, 42.37355], [-82.64242, 42.55594], [-82.58873, 42.54984], [-82.57583, 42.5718], [-82.51858, 42.611], [-82.51063, 42.66025], [-82.46613, 42.76615], [-82.4826, 42.8068], [-82.45331, 42.93139], [-82.4253, 42.95423], [-82.4146, 42.97626], [-82.42469, 42.992], [-82.48419, 45.30225], [-83.59589, 45.82131], [-83.43746, 45.99749], [-83.57017, 46.105], [-83.83329, 46.12169], [-83.90453, 46.05922], [-83.95399, 46.05634], [-84.1096, 46.23987], [-84.09756, 46.25512], [-84.11615, 46.2681], [-84.11254, 46.32329], [-84.13451, 46.39218], [-84.11196, 46.50248], [-84.12885, 46.53068], [-84.17723, 46.52753], [-84.1945, 46.54061], [-84.2264, 46.53337], [-84.26351, 46.49508], [-84.29893, 46.49127], [-84.34174, 46.50683], [-84.42101, 46.49853], [-84.4481, 46.48972], [-84.47607, 46.45225], [-84.55635, 46.45974], [-84.85871, 46.88881], [-88.37033, 48.30586], [-89.48837, 48.01412], [-89.57972, 48.00023], [-89.77248, 48.02607], [-89.89974, 47.98109], [-90.07418, 48.11043], [-90.56312, 48.09488], [-90.56444, 48.12184], [-90.75045, 48.09143], [-90.87588, 48.2484], [-91.08016, 48.18096], [-91.25025, 48.08522], [-91.43248, 48.04912], [-91.45829, 48.07454], [-91.58025, 48.04339], [-91.55649, 48.10611], [-91.70451, 48.11805], [-91.71231, 48.19875], [-91.86125, 48.21278], [-91.98929, 48.25409], [-92.05339, 48.35958], [-92.14732, 48.36578], [-92.202, 48.35252], [-92.26662, 48.35651], [-92.30939, 48.31251], [-92.27167, 48.25046], [-92.37185, 48.22259], [-92.48147, 48.36609], [-92.45588, 48.40624], [-92.50712, 48.44921], [-92.65606, 48.43471], [-92.71323, 48.46081], [-92.69927, 48.49573], [-92.62747, 48.50278], [-92.6342, 48.54133], [-92.7287, 48.54005], [-92.94973, 48.60866], [-93.25391, 48.64266], [-93.33946, 48.62787], [-93.3712, 48.60599], [-93.39758, 48.60364], [-93.40693, 48.60948], [-93.44472, 48.59147], [-93.47022, 48.54357], [-93.66382, 48.51845], [-93.79267, 48.51631], [-93.80939, 48.52439], [-93.80676, 48.58232], [-93.83288, 48.62745], [-93.85769, 48.63284], [-94.23215, 48.65202], [-94.25104, 48.65729], [-94.25172, 48.68404], [-94.27153, 48.70232], [-94.4174, 48.71049], [-94.44258, 48.69223], [-94.53826, 48.70216], [-94.54885, 48.71543], [-94.58903, 48.71803], [-94.69335, 48.77883], [-94.69669, 48.80918], [-94.70486, 48.82365], [-94.70087, 48.8339], [-94.687, 48.84077], [-94.75017, 49.09931], [-94.77355, 49.11998], [-94.82487, 49.29483], [-94.8159, 49.32299], [-94.85381, 49.32492], [-94.95681, 49.37035], [-94.99532, 49.36579], [-95.01419, 49.35647], [-95.05825, 49.35311], [-95.12903, 49.37056], [-95.15357, 49.384], [-95.15355, 48.9996], [-123.32163, 49.00419], [-123.0093, 48.83186], [-123.0093, 48.76586], [-123.26565, 48.6959], [-123.15614, 48.35395], [-123.50039, 48.21223], [-125.03842, 48.53282], [-133.98258, 38.06389], [-118.48109, 32.5991], [-117.1243, 32.53427], [-115.88053, 32.63624], [-114.71871, 32.71894], [-114.76736, 32.64094], [-114.80584, 32.62028], [-114.81141, 32.55543], [-114.79524, 32.55731], [-114.82011, 32.49609], [-111.07523, 31.33232], [-108.20979, 31.33316], [-108.20899, 31.78534], [-106.529, 31.784], [-106.52266, 31.77509], [-106.51251, 31.76922], [-106.50962, 31.76155], [-106.50111, 31.75714], [-106.48815, 31.74769], [-106.47298, 31.75054], [-106.46726, 31.75998], [-106.45244, 31.76523], [-106.43419, 31.75478], [-106.41773, 31.75196], [-106.38003, 31.73151], [-106.3718, 31.71165], [-106.34864, 31.69663], [-106.33419, 31.66303], [-106.30305, 31.62154], [-106.28084, 31.56173], [-106.24612, 31.54193], [-106.23711, 31.51262], [-106.20346, 31.46305], [-106.09025, 31.40569], [-106.00363, 31.39181], [-104.77674, 30.4236], [-104.5171, 29.64671], [-104.3969, 29.57105], [-104.39363, 29.55396], [-104.37752, 29.54255], [-103.15787, 28.93865], [-102.60596, 29.8192], [-101.47277, 29.7744], [-101.05686, 29.44738], [-101.01128, 29.36947], [-100.96725, 29.3477], [-100.94579, 29.34523], [-100.94056, 29.33371], [-100.87982, 29.296], [-100.79696, 29.24688], [-100.67294, 29.09744], [-100.63689, 28.90812], [-100.59809, 28.88197], [-100.52313, 28.75598], [-100.5075, 28.74066], [-100.51222, 28.70679], [-100.50029, 28.66117], [-99.55409, 27.61314], [-99.51478, 27.55836], [-99.52955, 27.49747], [-99.50208, 27.50021], [-99.48045, 27.49016], [-99.482, 27.47128], [-99.49744, 27.43746], [-99.53573, 27.30926], [-99.08477, 26.39849], [-99.03053, 26.41249], [-99.00546, 26.3925], [-98.35126, 26.15129], [-98.30491, 26.10475], [-98.27075, 26.09457], [-98.24603, 26.07191], [-97.97017, 26.05232], [-97.95155, 26.0625], [-97.66511, 26.01708], [-97.52025, 25.88518], [-97.49828, 25.89877], [-97.45669, 25.86874], [-97.42511, 25.83969], [-97.37332, 25.83854], [-97.35946, 25.92189], [-97.13927, 25.96583]]]]
22932           }
22933         }, {
22934           type: "Feature",
22935           properties: {
22936             wikidata: "Q620634",
22937             nameEn: "Bir Tawil",
22938             groups: ["015", "002"],
22939             level: "territory"
22940           },
22941           geometry: {
22942             type: "MultiPolygon",
22943             coordinates: [[[[33.17563, 22.00405], [33.57251, 21.72406], [33.99686, 21.76784], [34.0765, 22.00501], [33.17563, 22.00405]]]]
22944           }
22945         }, {
22946           type: "Feature",
22947           properties: {
22948             wikidata: "Q639185",
22949             nameEn: "Peros Banhos",
22950             country: "GB",
22951             groups: ["IO", "BOTS", "014", "202", "002", "UN"],
22952             level: "subterritory"
22953           },
22954           geometry: {
22955             type: "MultiPolygon",
22956             coordinates: [[[[72.12587, -4.02588], [70.1848, -6.37445], [72.09518, -5.61768], [72.12587, -4.02588]]]]
22957           }
22958         }, {
22959           type: "Feature",
22960           properties: {
22961             wikidata: "Q644636",
22962             nameEn: "Cyprus",
22963             level: "sharedLandform"
22964           },
22965           geometry: null
22966         }, {
22967           type: "Feature",
22968           properties: {
22969             wikidata: "Q851132",
22970             nameEn: "New Zealand Outlying Islands",
22971             country: "NZ",
22972             level: "subcountryGroup"
22973           },
22974           geometry: null
22975         }, {
22976           type: "Feature",
22977           properties: {
22978             wikidata: "Q875134",
22979             nameEn: "European Russia",
22980             country: "RU",
22981             groups: ["151", "150", "UN"],
22982             callingCodes: ["7"]
22983           },
22984           geometry: {
22985             type: "MultiPolygon",
22986             coordinates: [[[[18.57853, 55.25302], [19.64312, 54.45423], [19.8038, 54.44203], [20.63871, 54.3706], [21.41123, 54.32395], [22.79705, 54.36264], [22.7253, 54.41732], [22.70208, 54.45312], [22.67788, 54.532], [22.71293, 54.56454], [22.68021, 54.58486], [22.7522, 54.63525], [22.74225, 54.64339], [22.75467, 54.6483], [22.73397, 54.66604], [22.73631, 54.72952], [22.87317, 54.79492], [22.85083, 54.88711], [22.76422, 54.92521], [22.68723, 54.9811], [22.65451, 54.97037], [22.60075, 55.01863], [22.58907, 55.07085], [22.47688, 55.04408], [22.31562, 55.0655], [22.14267, 55.05345], [22.11697, 55.02131], [22.06087, 55.02935], [22.02582, 55.05078], [22.03984, 55.07888], [21.99543, 55.08691], [21.96505, 55.07353], [21.85521, 55.09493], [21.64954, 55.1791], [21.55605, 55.20311], [21.51095, 55.18507], [21.46766, 55.21115], [21.38446, 55.29348], [21.35465, 55.28427], [21.26425, 55.24456], [20.95181, 55.27994], [20.60454, 55.40986], [18.57853, 55.25302]]], [[[26.32936, 60.00121], [26.90044, 59.63819], [27.85643, 59.58538], [28.04187, 59.47017], [28.19061, 59.39962], [28.21137, 59.38058], [28.20537, 59.36491], [28.19284, 59.35791], [28.14215, 59.28934], [28.00689, 59.28351], [27.90911, 59.24353], [27.87978, 59.18097], [27.80482, 59.1116], [27.74429, 58.98351], [27.36366, 58.78381], [27.55489, 58.39525], [27.48541, 58.22615], [27.62393, 58.09462], [27.67282, 57.92627], [27.81841, 57.89244], [27.78526, 57.83963], [27.56689, 57.83356], [27.50171, 57.78842], [27.52615, 57.72843], [27.3746, 57.66834], [27.40393, 57.62125], [27.31919, 57.57672], [27.34698, 57.52242], [27.56832, 57.53728], [27.52453, 57.42826], [27.86101, 57.29402], [27.66511, 56.83921], [27.86101, 56.88204], [28.04768, 56.59004], [28.13526, 56.57989], [28.10069, 56.524], [28.19057, 56.44637], [28.16599, 56.37806], [28.23716, 56.27588], [28.15217, 56.16964], [28.30571, 56.06035], [28.36888, 56.05805], [28.37987, 56.11399], [28.43068, 56.09407], [28.5529, 56.11705], [28.68337, 56.10173], [28.63668, 56.07262], [28.73418, 55.97131], [29.08299, 56.03427], [29.21717, 55.98971], [29.44692, 55.95978], [29.3604, 55.75862], [29.51283, 55.70294], [29.61446, 55.77716], [29.80672, 55.79569], [29.97975, 55.87281], [30.12136, 55.8358], [30.27776, 55.86819], [30.30987, 55.83592], [30.48257, 55.81066], [30.51346, 55.78982], [30.51037, 55.76568], [30.63344, 55.73079], [30.67464, 55.64176], [30.72957, 55.66268], [30.7845, 55.58514], [30.86003, 55.63169], [30.93419, 55.6185], [30.95204, 55.50667], [30.90123, 55.46621], [30.93144, 55.3914], [30.8257, 55.3313], [30.81946, 55.27931], [30.87944, 55.28223], [30.97369, 55.17134], [31.02071, 55.06167], [31.00972, 55.02783], [30.94243, 55.03964], [30.9081, 55.02232], [30.95754, 54.98609], [30.93144, 54.9585], [30.81759, 54.94064], [30.8264, 54.90062], [30.75165, 54.80699], [30.95479, 54.74346], [30.97127, 54.71967], [31.0262, 54.70698], [30.98226, 54.68872], [30.99187, 54.67046], [31.19339, 54.66947], [31.21399, 54.63113], [31.08543, 54.50361], [31.22945, 54.46585], [31.3177, 54.34067], [31.30791, 54.25315], [31.57002, 54.14535], [31.89599, 54.0837], [31.88744, 54.03653], [31.85019, 53.91801], [31.77028, 53.80015], [31.89137, 53.78099], [32.12621, 53.81586], [32.36663, 53.7166], [32.45717, 53.74039], [32.50112, 53.68594], [32.40499, 53.6656], [32.47777, 53.5548], [32.74968, 53.45597], [32.73257, 53.33494], [32.51725, 53.28431], [32.40773, 53.18856], [32.15368, 53.07594], [31.82373, 53.10042], [31.787, 53.18033], [31.62496, 53.22886], [31.56316, 53.19432], [31.40523, 53.21406], [31.36403, 53.13504], [31.3915, 53.09712], [31.33519, 53.08805], [31.32283, 53.04101], [31.24147, 53.031], [31.35667, 52.97854], [31.592, 52.79011], [31.57277, 52.71613], [31.50406, 52.69707], [31.63869, 52.55361], [31.56316, 52.51518], [31.61397, 52.48843], [31.62084, 52.33849], [31.57971, 52.32146], [31.70735, 52.26711], [31.6895, 52.1973], [31.77877, 52.18636], [31.7822, 52.11406], [31.81722, 52.09955], [31.85018, 52.11305], [31.96141, 52.08015], [31.92159, 52.05144], [32.08813, 52.03319], [32.23331, 52.08085], [32.2777, 52.10266], [32.34044, 52.1434], [32.33083, 52.23685], [32.38988, 52.24946], [32.3528, 52.32842], [32.54781, 52.32423], [32.69475, 52.25535], [32.85405, 52.27888], [32.89937, 52.2461], [33.18913, 52.3754], [33.51323, 52.35779], [33.48027, 52.31499], [33.55718, 52.30324], [33.78789, 52.37204], [34.05239, 52.20132], [34.11199, 52.14087], [34.09413, 52.00835], [34.41136, 51.82793], [34.42922, 51.72852], [34.07765, 51.67065], [34.17599, 51.63253], [34.30562, 51.5205], [34.22048, 51.4187], [34.33446, 51.363], [34.23009, 51.26429], [34.31661, 51.23936], [34.38802, 51.2746], [34.6613, 51.25053], [34.6874, 51.18], [34.82472, 51.17483], [34.97304, 51.2342], [35.14058, 51.23162], [35.12685, 51.16191], [35.20375, 51.04723], [35.31774, 51.08434], [35.40837, 51.04119], [35.32598, 50.94524], [35.39307, 50.92145], [35.41367, 50.80227], [35.47704, 50.77274], [35.48116, 50.66405], [35.39464, 50.64751], [35.47463, 50.49247], [35.58003, 50.45117], [35.61711, 50.35707], [35.73659, 50.35489], [35.80388, 50.41356], [35.8926, 50.43829], [36.06893, 50.45205], [36.20763, 50.3943], [36.30101, 50.29088], [36.47817, 50.31457], [36.58371, 50.28563], [36.56655, 50.2413], [36.64571, 50.218], [36.69377, 50.26982], [36.91762, 50.34963], [37.08468, 50.34935], [37.48204, 50.46079], [37.47243, 50.36277], [37.62486, 50.29966], [37.62879, 50.24481], [37.61113, 50.21976], [37.75807, 50.07896], [37.79515, 50.08425], [37.90776, 50.04194], [38.02999, 49.94482], [38.02999, 49.90592], [38.21675, 49.98104], [38.18517, 50.08161], [38.32524, 50.08866], [38.35408, 50.00664], [38.65688, 49.97176], [38.68677, 50.00904], [38.73311, 49.90238], [38.90477, 49.86787], [38.9391, 49.79524], [39.1808, 49.88911], [39.27968, 49.75976], [39.44496, 49.76067], [39.59142, 49.73758], [39.65047, 49.61761], [39.84548, 49.56064], [40.13249, 49.61672], [40.16683, 49.56865], [40.03636, 49.52321], [40.03087, 49.45452], [40.1141, 49.38798], [40.14912, 49.37681], [40.18331, 49.34996], [40.22176, 49.25683], [40.01988, 49.1761], [39.93437, 49.05709], [39.6836, 49.05121], [39.6683, 48.99454], [39.71353, 48.98959], [39.72649, 48.9754], [39.74874, 48.98675], [39.78368, 48.91596], [39.98967, 48.86901], [40.03636, 48.91957], [40.08168, 48.87443], [39.97182, 48.79398], [39.79466, 48.83739], [39.73104, 48.7325], [39.71765, 48.68673], [39.67226, 48.59368], [39.79764, 48.58668], [39.84548, 48.57821], [39.86196, 48.46633], [39.88794, 48.44226], [39.94847, 48.35055], [39.84136, 48.33321], [39.84273, 48.30947], [39.90041, 48.3049], [39.91465, 48.26743], [39.95248, 48.29972], [39.9693, 48.29904], [39.97325, 48.31399], [39.99241, 48.31768], [40.00752, 48.22445], [39.94847, 48.22811], [39.83724, 48.06501], [39.88256, 48.04482], [39.77544, 48.04206], [39.82213, 47.96396], [39.73935, 47.82876], [38.87979, 47.87719], [38.79628, 47.81109], [38.76379, 47.69346], [38.35062, 47.61631], [38.28679, 47.53552], [38.28954, 47.39255], [38.22225, 47.30788], [38.33074, 47.30508], [38.32112, 47.2585], [38.23049, 47.2324], [38.22955, 47.12069], [38.3384, 46.98085], [38.12112, 46.86078], [37.62608, 46.82615], [35.23066, 45.79231], [35.04991, 45.76827], [36.6645, 45.4514], [36.6545, 45.3417], [36.5049, 45.3136], [36.475, 45.2411], [36.4883, 45.0488], [33.5943, 44.03313], [39.81147, 43.06294], [40.0078, 43.38551], [40.00853, 43.40578], [40.01552, 43.42025], [40.01007, 43.42411], [40.03312, 43.44262], [40.04445, 43.47776], [40.10657, 43.57344], [40.65957, 43.56212], [41.64935, 43.22331], [42.40563, 43.23226], [42.66667, 43.13917], [42.75889, 43.19651], [43.03322, 43.08883], [43.0419, 43.02413], [43.81453, 42.74297], [43.73119, 42.62043], [43.95517, 42.55396], [44.54202, 42.75699], [44.70002, 42.74679], [44.80941, 42.61277], [44.88754, 42.74934], [45.15318, 42.70598], [45.36501, 42.55268], [45.78692, 42.48358], [45.61676, 42.20768], [46.42738, 41.91323], [46.5332, 41.87389], [46.58924, 41.80547], [46.75269, 41.8623], [46.8134, 41.76252], [47.00955, 41.63583], [46.99554, 41.59743], [47.03757, 41.55434], [47.10762, 41.59044], [47.34579, 41.27884], [47.49004, 41.26366], [47.54504, 41.20275], [47.62288, 41.22969], [47.75831, 41.19455], [47.87973, 41.21798], [48.07587, 41.49957], [48.22064, 41.51472], [48.2878, 41.56221], [48.40277, 41.60441], [48.42301, 41.65444], [48.55078, 41.77917], [48.5867, 41.84306], [48.80971, 41.95365], [49.2134, 44.84989], [49.88945, 46.04554], [49.32259, 46.26944], [49.16518, 46.38542], [48.54988, 46.56267], [48.51142, 46.69268], [49.01136, 46.72716], [48.52326, 47.4102], [48.45173, 47.40818], [48.15348, 47.74545], [47.64973, 47.76559], [47.41689, 47.83687], [47.38731, 47.68176], [47.12107, 47.83687], [47.11516, 48.27188], [46.49011, 48.43019], [46.78392, 48.95352], [47.00857, 49.04921], [47.04658, 49.19834], [46.78398, 49.34026], [46.9078, 49.86707], [47.18319, 49.93721], [47.34589, 50.09308], [47.30448, 50.30894], [47.58551, 50.47867], [48.10044, 50.09242], [48.24519, 49.86099], [48.42564, 49.82283], [48.68352, 49.89546], [48.90782, 50.02281], [48.57946, 50.63278], [48.86936, 50.61589], [49.12673, 50.78639], [49.41959, 50.85927], [49.39001, 51.09396], [49.76866, 51.11067], [49.97277, 51.2405], [50.26859, 51.28677], [50.59695, 51.61859], [51.26254, 51.68466], [51.301, 51.48799], [51.77431, 51.49536], [51.8246, 51.67916], [52.36119, 51.74161], [52.54329, 51.48444], [53.46165, 51.49445], [53.69299, 51.23466], [54.12248, 51.11542], [54.46331, 50.85554], [54.41894, 50.61214], [54.55797, 50.52006], [54.71476, 50.61214], [54.56685, 51.01958], [54.72067, 51.03261], [55.67774, 50.54508], [56.11398, 50.7471], [56.17906, 50.93204], [57.17302, 51.11253], [57.44221, 50.88354], [57.74986, 50.93017], [57.75578, 51.13852], [58.3208, 51.15151], [58.87974, 50.70852], [59.48928, 50.64216], [59.51886, 50.49937], [59.81172, 50.54451], [60.01288, 50.8163], [60.17262, 50.83312], [60.31914, 50.67705], [60.81833, 50.6629], [61.4431, 50.80679], [61.56889, 51.23679], [61.6813, 51.25716], [61.55114, 51.32746], [61.50677, 51.40687], [60.95655, 51.48615], [60.92401, 51.61124], [60.5424, 51.61675], [60.36787, 51.66815], [60.50986, 51.7964], [60.09867, 51.87135], [59.99809, 51.98263], [59.91279, 52.06924], [60.17253, 52.25814], [60.17516, 52.39457], [59.25033, 52.46803], [59.22409, 52.28437], [58.79644, 52.43392], [58.94336, 53.953], [59.70487, 54.14846], [59.95217, 54.85853], [57.95234, 54.39672], [57.14829, 54.84204], [57.25137, 55.26262], [58.81825, 55.03378], [59.49035, 55.60486], [59.28419, 56.15739], [57.51527, 56.08729], [57.28024, 56.87898], [58.07604, 57.08308], [58.13789, 57.68097], [58.81412, 57.71602], [58.71104, 58.07475], [59.40376, 58.45822], [59.15636, 59.14682], [58.3853, 59.487], [59.50685, 60.91162], [59.36223, 61.3882], [59.61398, 62.44915], [59.24834, 63.01859], [59.80579, 64.13948], [59.63945, 64.78384], [60.74386, 64.95767], [61.98014, 65.72191], [66.1708, 67.61252], [64.18965, 69.94255], [76.13964, 83.37843], [36.85549, 84.09565], [32.07813, 72.01005], [31.59909, 70.16571], [30.84095, 69.80584], [30.95011, 69.54699], [30.52662, 69.54699], [30.16363, 69.65244], [29.97205, 69.41623], [29.27631, 69.2811], [29.26623, 69.13794], [29.0444, 69.0119], [28.91738, 69.04774], [28.45957, 68.91417], [28.78224, 68.86696], [28.43941, 68.53366], [28.62982, 68.19816], [29.34179, 68.06655], [29.66955, 67.79872], [30.02041, 67.67523], [29.91155, 67.51507], [28.9839, 66.94139], [29.91155, 66.13863], [30.16363, 65.66935], [29.97205, 65.70256], [29.74013, 65.64025], [29.84096, 65.56945], [29.68972, 65.31803], [29.61914, 65.23791], [29.8813, 65.22101], [29.84096, 65.1109], [29.61914, 65.05993], [29.68972, 64.80789], [30.05271, 64.79072], [30.12329, 64.64862], [30.01238, 64.57513], [30.06279, 64.35782], [30.4762, 64.25728], [30.55687, 64.09036], [30.25437, 63.83364], [29.98213, 63.75795], [30.49637, 63.46666], [31.23244, 63.22239], [31.29294, 63.09035], [31.58535, 62.91642], [31.38369, 62.66284], [31.10136, 62.43042], [29.01829, 61.17448], [28.82816, 61.1233], [28.47974, 60.93365], [27.77352, 60.52722], [27.71177, 60.3893], [27.44953, 60.22766], [26.32936, 60.00121]]]]
22987           }
22988         }, {
22989           type: "Feature",
22990           properties: {
22991             wikidata: "Q1083368",
22992             nameEn: "Mainland Finland",
22993             country: "FI",
22994             groups: ["EU", "154", "150", "UN"],
22995             callingCodes: ["358"]
22996           },
22997           geometry: {
22998             type: "MultiPolygon",
22999             coordinates: [[[[29.12697, 69.69193], [28.36883, 69.81658], [28.32849, 69.88605], [27.97558, 69.99671], [27.95542, 70.0965], [27.57226, 70.06215], [27.05802, 69.92069], [26.64461, 69.96565], [26.40261, 69.91377], [25.96904, 69.68397], [25.69679, 69.27039], [25.75729, 68.99383], [25.61613, 68.89602], [25.42455, 68.90328], [25.12206, 68.78684], [25.10189, 68.63307], [24.93048, 68.61102], [24.90023, 68.55579], [24.74898, 68.65143], [24.18432, 68.73936], [24.02299, 68.81601], [23.781, 68.84514], [23.68017, 68.70276], [23.13064, 68.64684], [22.53321, 68.74393], [22.38367, 68.71561], [22.27276, 68.89514], [21.63833, 69.27485], [21.27827, 69.31281], [21.00732, 69.22755], [20.98641, 69.18809], [21.11099, 69.10291], [21.05775, 69.0356], [20.72171, 69.11874], [20.55258, 69.06069], [20.78802, 69.03087], [20.91658, 68.96764], [20.85104, 68.93142], [20.90649, 68.89696], [21.03001, 68.88969], [22.00429, 68.50692], [22.73028, 68.40881], [23.10336, 68.26551], [23.15377, 68.14759], [23.26469, 68.15134], [23.40081, 68.05545], [23.65793, 67.9497], [23.45627, 67.85297], [23.54701, 67.59306], [23.39577, 67.46974], [23.75372, 67.43688], [23.75372, 67.29914], [23.54701, 67.25435], [23.58735, 67.20752], [23.56214, 67.17038], [23.98563, 66.84149], [23.98059, 66.79585], [23.89488, 66.772], [23.85959, 66.56434], [23.63776, 66.43568], [23.67591, 66.3862], [23.64982, 66.30603], [23.71339, 66.21299], [23.90497, 66.15802], [24.15791, 65.85385], [24.14798, 65.83466], [24.15107, 65.81427], [24.14112, 65.39731], [20.15877, 63.06556], [19.23413, 60.61414], [20.96741, 60.71528], [21.15143, 60.54555], [21.08159, 60.20167], [21.02509, 60.12142], [21.35468, 59.67511], [20.5104, 59.15546], [26.32936, 60.00121], [27.44953, 60.22766], [27.71177, 60.3893], [27.77352, 60.52722], [28.47974, 60.93365], [28.82816, 61.1233], [29.01829, 61.17448], [31.10136, 62.43042], [31.38369, 62.66284], [31.58535, 62.91642], [31.29294, 63.09035], [31.23244, 63.22239], [30.49637, 63.46666], [29.98213, 63.75795], [30.25437, 63.83364], [30.55687, 64.09036], [30.4762, 64.25728], [30.06279, 64.35782], [30.01238, 64.57513], [30.12329, 64.64862], [30.05271, 64.79072], [29.68972, 64.80789], [29.61914, 65.05993], [29.84096, 65.1109], [29.8813, 65.22101], [29.61914, 65.23791], [29.68972, 65.31803], [29.84096, 65.56945], [29.74013, 65.64025], [29.97205, 65.70256], [30.16363, 65.66935], [29.91155, 66.13863], [28.9839, 66.94139], [29.91155, 67.51507], [30.02041, 67.67523], [29.66955, 67.79872], [29.34179, 68.06655], [28.62982, 68.19816], [28.43941, 68.53366], [28.78224, 68.86696], [28.45957, 68.91417], [28.91738, 69.04774], [28.81248, 69.11997], [28.8629, 69.22395], [29.31664, 69.47994], [29.12697, 69.69193]]]]
23000           }
23001         }, {
23002           type: "Feature",
23003           properties: {
23004             wikidata: "Q1184963",
23005             nameEn: "Alhucemas Islands",
23006             country: "ES",
23007             groups: ["EU", "Q191011", "015", "002", "UN"],
23008             level: "subterritory"
23009           },
23010           geometry: {
23011             type: "MultiPolygon",
23012             coordinates: [[[[-3.90602, 35.21494], [-3.88372, 35.20767], [-3.89343, 35.22728], [-3.90602, 35.21494]]]]
23013           }
23014         }, {
23015           type: "Feature",
23016           properties: {
23017             wikidata: "Q1298289",
23018             nameEn: "Egmont Islands",
23019             country: "GB",
23020             groups: ["IO", "BOTS", "014", "202", "002", "UN"],
23021             level: "subterritory"
23022           },
23023           geometry: {
23024             type: "MultiPolygon",
23025             coordinates: [[[[70.1848, -6.37445], [70.67958, -8.2663], [72.17991, -6.68509], [70.1848, -6.37445]]]]
23026           }
23027         }, {
23028           type: "Feature",
23029           properties: {
23030             wikidata: "Q1352230",
23031             nameEn: "US Territories",
23032             country: "US",
23033             level: "subcountryGroup"
23034           },
23035           geometry: null
23036         }, {
23037           type: "Feature",
23038           properties: {
23039             wikidata: "Q1451600",
23040             nameEn: "Overseas Countries and Territories of the EU",
23041             aliases: ["OCT"],
23042             level: "subunion"
23043           },
23044           geometry: null
23045         }, {
23046           type: "Feature",
23047           properties: {
23048             wikidata: "Q1544253",
23049             nameEn: "Great Chagos Bank",
23050             country: "GB",
23051             groups: ["IO", "BOTS", "014", "202", "002", "UN"],
23052             level: "subterritory"
23053           },
23054           geometry: {
23055             type: "MultiPolygon",
23056             coordinates: [[[[70.1848, -6.37445], [72.17991, -6.68509], [73.20573, -5.20727], [70.1848, -6.37445]]]]
23057           }
23058         }, {
23059           type: "Feature",
23060           properties: {
23061             wikidata: "Q1585511",
23062             nameEn: "Salomon Atoll",
23063             country: "GB",
23064             groups: ["IO", "BOTS", "014", "202", "002", "UN"],
23065             level: "subterritory"
23066           },
23067           geometry: {
23068             type: "MultiPolygon",
23069             coordinates: [[[[72.09518, -5.61768], [73.20573, -5.20727], [72.12587, -4.02588], [72.09518, -5.61768]]]]
23070           }
23071         }, {
23072           type: "Feature",
23073           properties: {
23074             wikidata: "Q1681727",
23075             nameEn: "Saint-Paul and Amsterdam",
23076             country: "FR",
23077             groups: ["TF", "Q1451600", "014", "202", "002", "UN"],
23078             level: "subterritory"
23079           },
23080           geometry: {
23081             type: "MultiPolygon",
23082             coordinates: [[[[76.31747, -42.16264], [80.15867, -36.04977], [71.22311, -38.75287], [76.31747, -42.16264]]]]
23083           }
23084         }, {
23085           type: "Feature",
23086           properties: {
23087             wikidata: "Q1901211",
23088             nameEn: "East Malaysia",
23089             country: "MY",
23090             groups: ["Q36117", "035", "142", "UN"],
23091             driveSide: "left",
23092             callingCodes: ["60"]
23093           },
23094           geometry: {
23095             type: "MultiPolygon",
23096             coordinates: [[[[110.90339, 7.52694], [109.82788, 2.86812], [109.62558, 1.99182], [109.53794, 1.91771], [109.57923, 1.80624], [109.66397, 1.79972], [109.66397, 1.60425], [110.35354, 0.98869], [110.49182, 0.88088], [110.62374, 0.873], [111.22979, 1.08326], [111.55434, 0.97864], [111.82846, 0.99349], [111.94553, 1.12016], [112.15679, 1.17004], [112.2127, 1.44135], [112.48648, 1.56516], [113.021, 1.57819], [113.01448, 1.42832], [113.64677, 1.23933], [114.03788, 1.44787], [114.57892, 1.5], [114.80706, 1.92351], [114.80706, 2.21665], [115.1721, 2.49671], [115.11343, 2.82879], [115.53713, 3.14776], [115.58276, 3.93499], [115.90217, 4.37708], [117.25801, 4.35108], [117.47313, 4.18857], [117.67641, 4.16535], [118.06469, 4.16638], [118.93936, 4.09009], [119.52945, 5.35672], [117.98544, 6.27477], [117.93857, 6.89845], [117.17735, 7.52841], [116.79524, 7.43869], [115.02521, 5.35005], [115.16236, 5.01011], [115.15092, 4.87604], [115.20737, 4.8256], [115.27819, 4.63661], [115.2851, 4.42295], [115.36346, 4.33563], [115.31275, 4.30806], [115.09978, 4.39123], [115.07737, 4.53418], [115.04064, 4.63706], [115.02278, 4.74137], [115.02955, 4.82087], [115.05038, 4.90275], [114.99417, 4.88201], [114.96982, 4.81146], [114.88841, 4.81905], [114.8266, 4.75062], [114.77303, 4.72871], [114.83189, 4.42387], [114.88039, 4.4257], [114.78539, 4.12205], [114.64211, 4.00694], [114.49922, 4.13108], [114.4416, 4.27588], [114.32176, 4.2552], [114.32176, 4.34942], [114.26876, 4.49878], [114.15813, 4.57], [114.07448, 4.58441], [114.10166, 4.76112], [110.90339, 7.52694]]]]
23097           }
23098         }, {
23099           type: "Feature",
23100           properties: {
23101             wikidata: "Q1973345",
23102             nameEn: "Peninsular Malaysia",
23103             country: "MY",
23104             groups: ["035", "142", "UN"],
23105             driveSide: "left",
23106             callingCodes: ["60"]
23107           },
23108           geometry: {
23109             type: "MultiPolygon",
23110             coordinates: [[[[102.46318, 7.22462], [102.09086, 6.23546], [102.08127, 6.22679], [102.07732, 6.193], [102.09182, 6.14161], [102.01835, 6.05407], [101.99209, 6.04075], [101.97114, 6.01992], [101.9714, 6.00575], [101.94712, 5.98421], [101.92819, 5.85511], [101.91776, 5.84269], [101.89188, 5.8386], [101.80144, 5.74505], [101.75074, 5.79091], [101.69773, 5.75881], [101.58019, 5.93534], [101.25524, 5.78633], [101.25755, 5.71065], [101.14062, 5.61613], [100.98815, 5.79464], [101.02708, 5.91013], [101.087, 5.9193], [101.12388, 6.11411], [101.06165, 6.14161], [101.12618, 6.19431], [101.10313, 6.25617], [100.85884, 6.24929], [100.81045, 6.45086], [100.74822, 6.46231], [100.74361, 6.50811], [100.66986, 6.45086], [100.43027, 6.52389], [100.42351, 6.51762], [100.41791, 6.5189], [100.41152, 6.52299], [100.35413, 6.54932], [100.31929, 6.65413], [100.32607, 6.65933], [100.32671, 6.66526], [100.31884, 6.66423], [100.31618, 6.66781], [100.30828, 6.66462], [100.29651, 6.68439], [100.19511, 6.72559], [100.12, 6.42105], [100.0756, 6.4045], [99.91873, 6.50233], [99.50117, 6.44501], [99.31854, 5.99868], [99.75778, 3.86466], [103.03657, 1.30383], [103.56591, 1.19719], [103.62738, 1.35255], [103.67468, 1.43166], [103.7219, 1.46108], [103.74161, 1.4502], [103.76395, 1.45183], [103.81181, 1.47953], [103.86383, 1.46288], [103.89565, 1.42841], [103.93384, 1.42926], [104.00131, 1.42405], [104.02277, 1.4438], [104.04622, 1.44691], [104.07348, 1.43322], [104.08871, 1.42015], [104.09162, 1.39694], [104.08072, 1.35998], [104.12282, 1.27714], [104.34728, 1.33529], [104.56723, 1.44271], [105.01437, 3.24936], [102.46318, 7.22462]]]]
23111           }
23112         }, {
23113           type: "Feature",
23114           properties: {
23115             wikidata: "Q2093907",
23116             nameEn: "Three Kings Islands",
23117             country: "NZ",
23118             groups: ["Q851132", "053", "009", "UN"],
23119             driveSide: "left"
23120           },
23121           geometry: {
23122             type: "MultiPolygon",
23123             coordinates: [[[[174.17679, -32.62487], [170.93268, -32.97889], [171.97383, -34.64644], [174.17679, -32.62487]]]]
23124           }
23125         }, {
23126           type: "Feature",
23127           properties: {
23128             wikidata: "Q2298216",
23129             nameEn: "Solander Islands",
23130             country: "NZ",
23131             groups: ["Q851132", "053", "009", "UN"],
23132             driveSide: "left"
23133           },
23134           geometry: {
23135             type: "MultiPolygon",
23136             coordinates: [[[[167.39068, -46.49187], [166.5534, -46.39484], [166.84561, -46.84889], [167.39068, -46.49187]]]]
23137           }
23138         }, {
23139           type: "Feature",
23140           properties: {
23141             wikidata: "Q2872203",
23142             nameEn: "Mainland Australia",
23143             country: "AU",
23144             groups: ["053", "009", "UN"],
23145             level: "subcountryGroup",
23146             driveSide: "left",
23147             callingCodes: ["61"]
23148           },
23149           geometry: {
23150             type: "MultiPolygon",
23151             coordinates: [[[[88.16419, -23.49578], [123.64533, -39.13605], [159.74028, -39.1978], [159.76765, -29.76946], [154.02855, -24.43238], [152.93188, -20.92631], [147.69992, -17.5933], [145.2855, -9.62524], [143.87386, -9.02382], [143.29772, -9.33993], [142.48658, -9.36754], [142.19246, -9.15378], [141.88934, -9.36111], [141.01842, -9.35091], [135.49042, -9.2276], [127.55165, -9.05052], [125.29076, -12.33139], [88.16419, -23.49578]]]]
23152           }
23153         }, {
23154           type: "Feature",
23155           properties: {
23156             wikidata: "Q2914565",
23157             nameEn: "Autonomous Regions of Portugal",
23158             country: "PT",
23159             level: "subcountryGroup"
23160           },
23161           geometry: null
23162         }, {
23163           type: "Feature",
23164           properties: {
23165             wikidata: "Q2915956",
23166             nameEn: "Mainland Portugal",
23167             country: "PT",
23168             groups: ["Q12837", "EU", "039", "150", "UN"],
23169             level: "subcountryGroup",
23170             callingCodes: ["351"]
23171           },
23172           geometry: {
23173             type: "MultiPolygon",
23174             coordinates: [[[[-10.39881, 36.12218], [-7.37282, 36.96896], [-7.39769, 37.16868], [-7.41133, 37.20314], [-7.41854, 37.23813], [-7.43227, 37.25152], [-7.43974, 37.38913], [-7.46878, 37.47127], [-7.51759, 37.56119], [-7.41981, 37.75729], [-7.33441, 37.81193], [-7.27314, 37.90145], [-7.24544, 37.98884], [-7.12648, 38.00296], [-7.10366, 38.04404], [-7.05966, 38.01966], [-7.00375, 38.01914], [-6.93418, 38.21454], [-7.09389, 38.17227], [-7.15581, 38.27597], [-7.32529, 38.44336], [-7.265, 38.61674], [-7.26174, 38.72107], [-7.03848, 38.87221], [-7.051, 38.907], [-6.95211, 39.0243], [-6.97004, 39.07619], [-7.04011, 39.11919], [-7.10692, 39.10275], [-7.14929, 39.11287], [-7.12811, 39.17101], [-7.23566, 39.20132], [-7.23403, 39.27579], [-7.3149, 39.34857], [-7.2927, 39.45847], [-7.49477, 39.58794], [-7.54121, 39.66717], [-7.33507, 39.64569], [-7.24707, 39.66576], [-7.01613, 39.66877], [-6.97492, 39.81488], [-6.91463, 39.86618], [-6.86737, 40.01986], [-6.94233, 40.10716], [-7.00589, 40.12087], [-7.02544, 40.18564], [-7.00426, 40.23169], [-6.86085, 40.26776], [-6.86085, 40.2976], [-6.80218, 40.33239], [-6.78426, 40.36468], [-6.84618, 40.42177], [-6.84944, 40.46394], [-6.7973, 40.51723], [-6.80218, 40.55067], [-6.84292, 40.56801], [-6.79567, 40.65955], [-6.82826, 40.74603], [-6.82337, 40.84472], [-6.79892, 40.84842], [-6.80707, 40.88047], [-6.84292, 40.89771], [-6.8527, 40.93958], [-6.9357, 41.02888], [-6.913, 41.03922], [-6.88843, 41.03027], [-6.84781, 41.02692], [-6.80942, 41.03629], [-6.79241, 41.05397], [-6.75655, 41.10187], [-6.77319, 41.13049], [-6.69711, 41.1858], [-6.68286, 41.21641], [-6.65046, 41.24725], [-6.55937, 41.24417], [-6.38551, 41.35274], [-6.38553, 41.38655], [-6.3306, 41.37677], [-6.26777, 41.48796], [-6.19128, 41.57638], [-6.29863, 41.66432], [-6.44204, 41.68258], [-6.49907, 41.65823], [-6.54633, 41.68623], [-6.56426, 41.74219], [-6.51374, 41.8758], [-6.56752, 41.88429], [-6.5447, 41.94371], [-6.58544, 41.96674], [-6.61967, 41.94008], [-6.75004, 41.94129], [-6.76959, 41.98734], [-6.81196, 41.99097], [-6.82174, 41.94493], [-6.94396, 41.94403], [-6.95537, 41.96553], [-6.98144, 41.9728], [-7.01078, 41.94977], [-7.07596, 41.94977], [-7.08574, 41.97401], [-7.14115, 41.98855], [-7.18549, 41.97515], [-7.18677, 41.88793], [-7.32366, 41.8406], [-7.37092, 41.85031], [-7.42864, 41.80589], [-7.42854, 41.83262], [-7.44759, 41.84451], [-7.45566, 41.86488], [-7.49803, 41.87095], [-7.52737, 41.83939], [-7.62188, 41.83089], [-7.58603, 41.87944], [-7.65774, 41.88308], [-7.69848, 41.90977], [-7.84188, 41.88065], [-7.88055, 41.84571], [-7.88751, 41.92553], [-7.90707, 41.92432], [-7.92336, 41.8758], [-7.9804, 41.87337], [-8.01136, 41.83453], [-8.0961, 41.81024], [-8.16455, 41.81753], [-8.16944, 41.87944], [-8.19551, 41.87459], [-8.2185, 41.91237], [-8.16232, 41.9828], [-8.08796, 42.01398], [-8.08847, 42.05767], [-8.11729, 42.08537], [-8.18178, 42.06436], [-8.19406, 42.12141], [-8.18947, 42.13853], [-8.1986, 42.15402], [-8.22406, 42.1328], [-8.24681, 42.13993], [-8.2732, 42.12396], [-8.29809, 42.106], [-8.32161, 42.10218], [-8.33912, 42.08358], [-8.36353, 42.09065], [-8.38323, 42.07683], [-8.40143, 42.08052], [-8.42512, 42.07199], [-8.44123, 42.08218], [-8.48185, 42.0811], [-8.52837, 42.07658], [-8.5252, 42.06264], [-8.54563, 42.0537], [-8.58086, 42.05147], [-8.59493, 42.05708], [-8.63791, 42.04691], [-8.64626, 42.03668], [-8.65832, 42.02972], [-8.6681, 41.99703], [-8.69071, 41.98862], [-8.7478, 41.96282], [-8.74606, 41.9469], [-8.75712, 41.92833], [-8.81794, 41.90375], [-8.87157, 41.86488], [-11.19304, 41.83075], [-10.39881, 36.12218]]]]
23175           }
23176         }, {
23177           type: "Feature",
23178           properties: {
23179             wikidata: "Q3311985",
23180             nameEn: "Guernsey",
23181             country: "GB",
23182             groups: ["GG", "830", "Q185086", "154", "150", "UN"],
23183             level: "subterritory",
23184             driveSide: "left",
23185             roadSpeedUnit: "mph",
23186             roadHeightUnit: "ft",
23187             callingCodes: ["44 01481"]
23188           },
23189           geometry: {
23190             type: "MultiPolygon",
23191             coordinates: [[[[-2.49556, 49.79012], [-3.28154, 49.57329], [-2.65349, 49.15373], [-2.36485, 49.48223], [-2.49556, 49.79012]]]]
23192           }
23193         }, {
23194           type: "Feature",
23195           properties: {
23196             wikidata: "Q3320166",
23197             nameEn: "Outermost Regions of the EU",
23198             aliases: ["OMR"],
23199             level: "subunion"
23200           },
23201           geometry: null
23202         }, {
23203           type: "Feature",
23204           properties: {
23205             wikidata: "Q3336843",
23206             nameEn: "Countries of the United Kingdom",
23207             country: "GB",
23208             level: "subcountryGroup"
23209           },
23210           geometry: null
23211         }, {
23212           type: "Feature",
23213           properties: {
23214             wikidata: "Q6736667",
23215             nameEn: "Mainland India",
23216             country: "IN",
23217             groups: ["034", "142", "UN"],
23218             driveSide: "left",
23219             callingCodes: ["91"]
23220           },
23221           geometry: {
23222             type: "MultiPolygon",
23223             coordinates: [[[[89.08044, 21.41871], [89.07114, 22.15335], [88.9367, 22.58527], [88.94614, 22.66941], [88.9151, 22.75228], [88.96713, 22.83346], [88.87063, 22.95235], [88.88327, 23.03885], [88.86377, 23.08759], [88.99148, 23.21134], [88.71133, 23.2492], [88.79254, 23.46028], [88.79351, 23.50535], [88.74841, 23.47361], [88.56507, 23.64044], [88.58087, 23.87105], [88.66189, 23.87607], [88.73743, 23.91751], [88.6976, 24.14703], [88.74841, 24.1959], [88.68801, 24.31464], [88.50934, 24.32474], [88.12296, 24.51301], [88.08786, 24.63232], [88.00683, 24.66477], [88.15515, 24.85806], [88.14004, 24.93529], [88.21832, 24.96642], [88.27325, 24.88796], [88.33917, 24.86803], [88.46277, 25.07468], [88.44766, 25.20149], [88.94067, 25.18534], [89.00463, 25.26583], [89.01105, 25.30303], [88.85278, 25.34679], [88.81296, 25.51546], [88.677, 25.46959], [88.4559, 25.59227], [88.45103, 25.66245], [88.242, 25.80811], [88.13138, 25.78773], [88.08804, 25.91334], [88.16581, 26.0238], [88.1844, 26.14417], [88.34757, 26.22216], [88.35153, 26.29123], [88.51649, 26.35923], [88.48749, 26.45855], [88.36938, 26.48683], [88.35153, 26.45241], [88.33093, 26.48929], [88.41196, 26.63837], [88.4298, 26.54489], [88.62144, 26.46783], [88.69485, 26.38353], [88.67837, 26.26291], [88.78961, 26.31093], [88.85004, 26.23211], [89.05328, 26.2469], [88.91321, 26.37984], [88.92357, 26.40711], [88.95612, 26.4564], [89.08899, 26.38845], [89.15869, 26.13708], [89.35953, 26.0077], [89.53515, 26.00382], [89.57101, 25.9682], [89.63968, 26.22595], [89.70201, 26.15138], [89.73581, 26.15818], [89.77865, 26.08387], [89.77728, 26.04254], [89.86592, 25.93115], [89.80585, 25.82489], [89.84388, 25.70042], [89.86129, 25.61714], [89.81208, 25.37244], [89.84086, 25.31854], [89.83371, 25.29548], [89.87629, 25.28337], [89.90478, 25.31038], [90.1155, 25.22686], [90.40034, 25.1534], [90.65042, 25.17788], [90.87427, 25.15799], [91.25517, 25.20677], [91.63648, 25.12846], [92.0316, 25.1834], [92.33957, 25.07593], [92.39147, 25.01471], [92.49887, 24.88796], [92.38626, 24.86055], [92.25854, 24.9191], [92.15796, 24.54435], [92.11662, 24.38997], [91.96603, 24.3799], [91.89258, 24.14674], [91.82596, 24.22345], [91.76004, 24.23848], [91.73257, 24.14703], [91.65292, 24.22095], [91.63782, 24.1132], [91.55542, 24.08687], [91.37414, 24.10693], [91.35741, 23.99072], [91.29587, 24.0041], [91.22308, 23.89616], [91.25192, 23.83463], [91.15579, 23.6599], [91.28293, 23.37538], [91.36453, 23.06612], [91.40848, 23.07117], [91.4035, 23.27522], [91.46615, 23.2328], [91.54993, 23.01051], [91.61571, 22.93929], [91.7324, 23.00043], [91.81634, 23.08001], [91.76417, 23.26619], [91.84789, 23.42235], [91.95642, 23.47361], [91.95093, 23.73284], [92.04706, 23.64229], [92.15417, 23.73409], [92.26541, 23.70392], [92.38214, 23.28705], [92.37665, 22.9435], [92.5181, 22.71441], [92.60029, 22.1522], [92.56616, 22.13554], [92.60949, 21.97638], [92.67532, 22.03547], [92.70416, 22.16017], [92.86208, 22.05456], [92.89504, 21.95143], [92.93899, 22.02656], [92.99804, 21.98964], [92.99255, 22.05965], [93.04885, 22.20595], [93.15734, 22.18687], [93.14224, 22.24535], [93.19991, 22.25425], [93.18206, 22.43716], [93.13537, 22.45873], [93.11477, 22.54374], [93.134, 22.59573], [93.09417, 22.69459], [93.134, 22.92498], [93.12988, 23.05772], [93.2878, 23.00464], [93.38478, 23.13698], [93.36862, 23.35426], [93.38781, 23.36139], [93.39981, 23.38828], [93.38805, 23.4728], [93.43475, 23.68299], [93.3908, 23.7622], [93.3908, 23.92925], [93.36059, 23.93176], [93.32351, 24.04468], [93.34735, 24.10151], [93.41415, 24.07854], [93.46633, 23.97067], [93.50616, 23.94432], [93.62871, 24.00922], [93.75952, 24.0003], [93.80279, 23.92549], [93.92089, 23.95812], [94.14081, 23.83333], [94.30215, 24.23752], [94.32362, 24.27692], [94.45279, 24.56656], [94.50729, 24.59281], [94.5526, 24.70764], [94.60204, 24.70889], [94.73937, 25.00545], [94.74212, 25.13606], [94.57458, 25.20318], [94.68032, 25.47003], [94.80117, 25.49359], [95.18556, 26.07338], [95.11428, 26.1019], [95.12801, 26.38397], [95.05798, 26.45408], [95.23513, 26.68499], [95.30339, 26.65372], [95.437, 26.7083], [95.81603, 27.01335], [95.93002, 27.04149], [96.04949, 27.19428], [96.15591, 27.24572], [96.40779, 27.29818], [96.55761, 27.29928], [96.73888, 27.36638], [96.88445, 27.25046], [96.85287, 27.2065], [96.89132, 27.17474], [97.14675, 27.09041], [97.17422, 27.14052], [96.91431, 27.45752], [96.90112, 27.62149], [97.29919, 27.92233], [97.35824, 27.87256], [97.38845, 28.01329], [97.35412, 28.06663], [97.31292, 28.06784], [97.34547, 28.21385], [97.1289, 28.3619], [96.98882, 28.32564], [96.88445, 28.39452], [96.85561, 28.4875], [96.6455, 28.61657], [96.48895, 28.42955], [96.40929, 28.51526], [96.61391, 28.72742], [96.3626, 29.10607], [96.20467, 29.02325], [96.18682, 29.11087], [96.31316, 29.18643], [96.05361, 29.38167], [95.84899, 29.31464], [95.75149, 29.32063], [95.72086, 29.20797], [95.50842, 29.13487], [95.41091, 29.13007], [95.3038, 29.13847], [95.26122, 29.07727], [95.2214, 29.10727], [95.11291, 29.09527], [95.0978, 29.14446], [94.81353, 29.17804], [94.69318, 29.31739], [94.2752, 29.11687], [94.35897, 29.01965], [93.72797, 28.68821], [93.44621, 28.67189], [93.18069, 28.50319], [93.14635, 28.37035], [92.93075, 28.25671], [92.67486, 28.15018], [92.65472, 28.07632], [92.73025, 28.05814], [92.7275, 27.98662], [92.42538, 27.80092], [92.32101, 27.79363], [92.27432, 27.89077], [91.87057, 27.7195], [91.84722, 27.76325], [91.6469, 27.76358], [91.55819, 27.6144], [91.65007, 27.48287], [92.01132, 27.47352], [92.12019, 27.27829], [92.04702, 27.26861], [92.03457, 27.07334], [92.11863, 26.893], [92.05523, 26.8692], [91.83181, 26.87318], [91.50067, 26.79223], [90.67715, 26.77215], [90.48504, 26.8594], [90.39271, 26.90704], [90.30402, 26.85098], [90.04535, 26.72422], [89.86124, 26.73307], [89.63369, 26.74402], [89.42349, 26.83727], [89.3901, 26.84225], [89.38319, 26.85963], [89.37913, 26.86224], [89.1926, 26.81329], [89.12825, 26.81661], [89.09554, 26.89089], [88.95807, 26.92668], [88.92301, 26.99286], [88.8714, 26.97488], [88.86984, 27.10937], [88.74219, 27.144], [88.91901, 27.32483], [88.82981, 27.38814], [88.77517, 27.45415], [88.88091, 27.85192], [88.83559, 28.01936], [88.63235, 28.12356], [88.54858, 28.06057], [88.25332, 27.9478], [88.1278, 27.95417], [88.13378, 27.88015], [88.1973, 27.85067], [88.19107, 27.79285], [88.04008, 27.49223], [88.07277, 27.43007], [88.01646, 27.21612], [88.01587, 27.21388], [87.9887, 27.11045], [88.11719, 26.98758], [88.13422, 26.98705], [88.12302, 26.95324], [88.19107, 26.75516], [88.1659, 26.68177], [88.16452, 26.64111], [88.09963, 26.54195], [88.09414, 26.43732], [88.00895, 26.36029], [87.90115, 26.44923], [87.89085, 26.48565], [87.84193, 26.43663], [87.7918, 26.46737], [87.76004, 26.40711], [87.67893, 26.43501], [87.66803, 26.40294], [87.59175, 26.38342], [87.55274, 26.40596], [87.51571, 26.43106], [87.46566, 26.44058], [87.37314, 26.40815], [87.34568, 26.34787], [87.26568, 26.37294], [87.26587, 26.40592], [87.24682, 26.4143], [87.18863, 26.40558], [87.14751, 26.40542], [87.09147, 26.45039], [87.0707, 26.58571], [87.04691, 26.58685], [87.01559, 26.53228], [86.95912, 26.52076], [86.94543, 26.52076], [86.82898, 26.43919], [86.76797, 26.45892], [86.74025, 26.42386], [86.69124, 26.45169], [86.62686, 26.46891], [86.61313, 26.48658], [86.57073, 26.49825], [86.54258, 26.53819], [86.49726, 26.54218], [86.31564, 26.61925], [86.26235, 26.61886], [86.22513, 26.58863], [86.13596, 26.60651], [86.02729, 26.66756], [85.8492, 26.56667], [85.85126, 26.60866], [85.83126, 26.61134], [85.76907, 26.63076], [85.72315, 26.67471], [85.73483, 26.79613], [85.66239, 26.84822], [85.61621, 26.86721], [85.59461, 26.85161], [85.5757, 26.85955], [85.56471, 26.84133], [85.47752, 26.79292], [85.34302, 26.74954], [85.21159, 26.75933], [85.18046, 26.80519], [85.19291, 26.86909], [85.15883, 26.86966], [85.02635, 26.85381], [85.05592, 26.88991], [85.00536, 26.89523], [84.97186, 26.9149], [84.96687, 26.95599], [84.85754, 26.98984], [84.82913, 27.01989], [84.793, 26.9968], [84.64496, 27.04669], [84.69166, 27.21294], [84.62161, 27.33885], [84.29315, 27.39], [84.25735, 27.44941], [84.21376, 27.45218], [84.10791, 27.52399], [84.02229, 27.43836], [83.93306, 27.44939], [83.86182, 27.4241], [83.85595, 27.35797], [83.61288, 27.47013], [83.39495, 27.4798], [83.38872, 27.39276], [83.35136, 27.33885], [83.29999, 27.32778], [83.2673, 27.36235], [83.27197, 27.38309], [83.19413, 27.45632], [82.94938, 27.46036], [82.93261, 27.50328], [82.74119, 27.49838], [82.70378, 27.72122], [82.46405, 27.6716], [82.06554, 27.92222], [81.97214, 27.93322], [81.91223, 27.84995], [81.47867, 28.08303], [81.48179, 28.12148], [81.38683, 28.17638], [81.32923, 28.13521], [81.19847, 28.36284], [81.03471, 28.40054], [80.55142, 28.69182], [80.50575, 28.6706], [80.52443, 28.54897], [80.44504, 28.63098], [80.37188, 28.63371], [80.12125, 28.82346], [80.06957, 28.82763], [80.05743, 28.91479], [80.18085, 29.13649], [80.23178, 29.11626], [80.26602, 29.13938], [80.24112, 29.21414], [80.28626, 29.20327], [80.31428, 29.30784], [80.24322, 29.44299], [80.37939, 29.57098], [80.41858, 29.63581], [80.38428, 29.68513], [80.36803, 29.73865], [80.41554, 29.79451], [80.43458, 29.80466], [80.48997, 29.79566], [80.56247, 29.86661], [80.57179, 29.91422], [80.60226, 29.95732], [80.67076, 29.95732], [80.8778, 30.13384], [80.86673, 30.17321], [80.91143, 30.22173], [80.92547, 30.17193], [81.03953, 30.20059], [80.83343, 30.32023], [80.54504, 30.44936], [80.20721, 30.58541], [79.93255, 30.88288], [79.59884, 30.93943], [79.30694, 31.17357], [79.14016, 31.43403], [79.01931, 31.42817], [78.89344, 31.30481], [78.77898, 31.31209], [78.71032, 31.50197], [78.84516, 31.60631], [78.69933, 31.78723], [78.78036, 31.99478], [78.74404, 32.00384], [78.68754, 32.10256], [78.49609, 32.2762], [78.4645, 32.45367], [78.38897, 32.53938], [78.73916, 32.69438], [78.7831, 32.46873], [78.96713, 32.33655], [78.99322, 32.37948], [79.0979, 32.38051], [79.13174, 32.47766], [79.26768, 32.53277], [79.46562, 32.69668], [79.14016, 33.02545], [79.15252, 33.17156], [78.73636, 33.56521], [78.67599, 33.66445], [78.77349, 33.73871], [78.73367, 34.01121], [78.65657, 34.03195], [78.66225, 34.08858], [78.91769, 34.15452], [78.99802, 34.3027], [79.05364, 34.32482], [78.74465, 34.45174], [78.56475, 34.50835], [78.54964, 34.57283], [78.27781, 34.61484], [78.18435, 34.7998], [78.22692, 34.88771], [78.00033, 35.23954], [78.03466, 35.3785], [78.11664, 35.48022], [77.80532, 35.52058], [77.70232, 35.46244], [77.44277, 35.46132], [76.96624, 35.5932], [76.84539, 35.67356], [76.77323, 35.66062], [76.75475, 35.52617], [76.85088, 35.39754], [76.93465, 35.39866], [77.11796, 35.05419], [76.99251, 34.93349], [76.87193, 34.96906], [76.74514, 34.92488], [76.74377, 34.84039], [76.67648, 34.76371], [76.47186, 34.78965], [76.15463, 34.6429], [76.04614, 34.67566], [75.75438, 34.51827], [75.38009, 34.55021], [75.01479, 34.64629], [74.6663, 34.703], [74.58083, 34.77386], [74.31239, 34.79626], [74.12897, 34.70073], [73.96423, 34.68244], [73.93401, 34.63386], [73.93951, 34.57169], [73.89419, 34.54568], [73.88732, 34.48911], [73.74999, 34.3781], [73.74862, 34.34183], [73.8475, 34.32935], [73.90517, 34.35317], [73.98208, 34.2522], [73.90677, 34.10504], [73.88732, 34.05105], [73.91341, 34.01235], [74.21554, 34.03853], [74.25262, 34.01577], [74.26086, 33.92237], [74.14001, 33.83002], [74.05898, 33.82089], [74.00891, 33.75437], [73.96423, 33.73071], [73.98968, 33.66155], [73.97367, 33.64061], [74.03576, 33.56718], [74.10115, 33.56392], [74.18121, 33.4745], [74.17983, 33.3679], [74.08782, 33.26232], [74.01366, 33.25199], [74.02144, 33.18908], [74.15374, 33.13477], [74.17571, 33.07495], [74.31854, 33.02891], [74.34875, 32.97823], [74.31227, 32.92795], [74.41467, 32.90563], [74.45312, 32.77755], [74.6289, 32.75561], [74.64675, 32.82604], [74.7113, 32.84219], [74.65345, 32.71225], [74.69542, 32.66792], [74.64424, 32.60985], [74.65251, 32.56416], [74.67431, 32.56676], [74.68362, 32.49298], [74.84725, 32.49075], [74.97634, 32.45367], [75.03265, 32.49538], [75.28259, 32.36556], [75.38046, 32.26836], [75.25649, 32.10187], [75.00793, 32.03786], [74.9269, 32.0658], [74.86236, 32.04485], [74.79919, 31.95983], [74.58907, 31.87824], [74.47771, 31.72227], [74.57498, 31.60382], [74.61517, 31.55698], [74.59319, 31.50197], [74.64713, 31.45605], [74.59773, 31.4136], [74.53223, 31.30321], [74.51629, 31.13829], [74.56023, 31.08303], [74.60281, 31.10419], [74.60006, 31.13711], [74.6852, 31.12771], [74.67971, 31.05479], [74.5616, 31.04153], [73.88993, 30.36305], [73.95736, 30.28466], [73.97225, 30.19829], [73.80299, 30.06969], [73.58665, 30.01848], [73.3962, 29.94707], [73.28094, 29.56646], [73.05886, 29.1878], [73.01337, 29.16422], [72.94272, 29.02487], [72.40402, 28.78283], [72.29495, 28.66367], [72.20329, 28.3869], [71.9244, 28.11555], [71.89921, 27.96035], [70.79054, 27.68423], [70.60927, 28.02178], [70.37307, 28.01208], [70.12502, 27.8057], [70.03136, 27.56627], [69.58519, 27.18109], [69.50904, 26.74892], [69.88555, 26.56836], [70.05584, 26.60398], [70.17532, 26.55362], [70.17532, 26.24118], [70.08193, 26.08094], [70.0985, 25.93238], [70.2687, 25.71156], [70.37444, 25.67443], [70.53649, 25.68928], [70.60378, 25.71898], [70.67382, 25.68186], [70.66695, 25.39314], [70.89148, 25.15064], [70.94002, 24.92843], [71.09405, 24.69017], [70.97594, 24.60904], [71.00341, 24.46038], [71.12838, 24.42662], [71.04461, 24.34657], [70.94985, 24.3791], [70.85784, 24.30903], [70.88393, 24.27398], [70.71502, 24.23517], [70.57906, 24.27774], [70.5667, 24.43787], [70.11712, 24.30915], [70.03428, 24.172], [69.73335, 24.17007], [69.59579, 24.29777], [69.29778, 24.28712], [69.19341, 24.25646], [69.07806, 24.29777], [68.97781, 24.26021], [68.90914, 24.33156], [68.7416, 24.31904], [68.74643, 23.97027], [68.39339, 23.96838], [68.20763, 23.85849], [68.11329, 23.53945], [76.59015, 5.591], [79.50447, 8.91876], [79.42124, 9.80115], [80.48418, 10.20786], [89.08044, 21.41871]]]]
23224           }
23225         }, {
23226           type: "Feature",
23227           properties: {
23228             wikidata: "Q9143535",
23229             nameEn: "Akrotiri",
23230             country: "GB",
23231             groups: ["Q644636", "Q37362", "BOTS", "145", "142", "UN"],
23232             level: "subterritory",
23233             driveSide: "left",
23234             callingCodes: ["357"]
23235           },
23236           geometry: {
23237             type: "MultiPolygon",
23238             coordinates: [[[[32.86014, 34.70585], [32.82717, 34.70622], [32.79433, 34.67883], [32.76136, 34.68318], [32.75515, 34.64985], [32.74412, 34.43926], [33.26744, 34.49942], [33.0138, 34.64424], [32.96968, 34.64046], [32.96718, 34.63446], [32.95891, 34.62919], [32.95323, 34.64075], [32.95471, 34.64528], [32.94976, 34.65204], [32.94796, 34.6587], [32.95325, 34.66462], [32.97079, 34.66112], [32.97736, 34.65277], [32.99014, 34.65518], [32.98668, 34.67268], [32.99135, 34.68061], [32.95539, 34.68471], [32.94683, 34.67907], [32.94379, 34.67111], [32.93693, 34.67027], [32.93449, 34.66241], [32.92807, 34.66736], [32.93043, 34.67091], [32.91398, 34.67343], [32.9068, 34.66102], [32.86167, 34.68734], [32.86014, 34.70585]]]]
23239           }
23240         }, {
23241           type: "Feature",
23242           properties: {
23243             wikidata: "Q9206745",
23244             nameEn: "Dhekelia",
23245             country: "GB",
23246             groups: ["Q644636", "Q37362", "BOTS", "145", "142", "UN"],
23247             level: "subterritory",
23248             driveSide: "left",
23249             callingCodes: ["357"]
23250           },
23251           geometry: {
23252             type: "MultiPolygon",
23253             coordinates: [[[[33.70575, 34.97947], [33.83531, 34.73974], [33.98684, 34.76642], [33.90075, 34.96623], [33.86432, 34.97592], [33.84811, 34.97075], [33.83505, 34.98108], [33.85621, 34.98956], [33.85891, 35.001], [33.85216, 35.00579], [33.84045, 35.00616], [33.82875, 35.01685], [33.83055, 35.02865], [33.81524, 35.04192], [33.8012, 35.04786], [33.82051, 35.0667], [33.8355, 35.05777], [33.85261, 35.0574], [33.88367, 35.07877], [33.89485, 35.06873], [33.90247, 35.07686], [33.91299, 35.07579], [33.91789, 35.08688], [33.89853, 35.11377], [33.88737, 35.11408], [33.88943, 35.12007], [33.88561, 35.12449], [33.87224, 35.12293], [33.87622, 35.10457], [33.87097, 35.09389], [33.87479, 35.08881], [33.8541, 35.07201], [33.84168, 35.06823], [33.82067, 35.07826], [33.78581, 35.05104], [33.76106, 35.04253], [33.73824, 35.05321], [33.71482, 35.03722], [33.70209, 35.04882], [33.7161, 35.07279], [33.70861, 35.07644], [33.69095, 35.06237], [33.68474, 35.06602], [33.67742, 35.05963], [33.67678, 35.03866], [33.69938, 35.03123], [33.69731, 35.01754], [33.71514, 35.00294], [33.70639, 34.99303], [33.70575, 34.97947]], [[33.77312, 34.9976], [33.77553, 34.99518], [33.78516, 34.99582], [33.79191, 34.98914], [33.78917, 34.98854], [33.78571, 34.98951], [33.78318, 34.98699], [33.78149, 34.98854], [33.77843, 34.988], [33.7778, 34.98981], [33.76738, 34.99188], [33.76605, 34.99543], [33.75682, 34.99916], [33.75994, 35.00113], [33.77312, 34.9976]], [[33.74144, 35.01053], [33.7343, 35.01178], [33.73781, 35.02181], [33.74265, 35.02329], [33.74983, 35.02274], [33.7492, 35.01319], [33.74144, 35.01053]]]]
23254           }
23255         }, {
23256           type: "Feature",
23257           properties: {
23258             wikidata: "Q16390686",
23259             nameEn: "Peninsular Spain",
23260             country: "ES",
23261             groups: ["Q12837", "EU", "039", "150", "UN"],
23262             callingCodes: ["34"]
23263           },
23264           geometry: {
23265             type: "MultiPolygon",
23266             coordinates: [[[[3.75438, 42.33445], [3.17156, 42.43545], [3.11379, 42.43646], [3.10027, 42.42621], [3.08167, 42.42748], [3.03734, 42.47363], [2.96518, 42.46692], [2.94283, 42.48174], [2.92107, 42.4573], [2.88413, 42.45938], [2.86983, 42.46843], [2.85675, 42.45444], [2.84335, 42.45724], [2.77464, 42.41046], [2.75497, 42.42578], [2.72056, 42.42298], [2.65311, 42.38771], [2.6747, 42.33974], [2.57934, 42.35808], [2.55516, 42.35351], [2.54382, 42.33406], [2.48457, 42.33933], [2.43508, 42.37568], [2.43299, 42.39423], [2.38504, 42.39977], [2.25551, 42.43757], [2.20578, 42.41633], [2.16599, 42.42314], [2.12789, 42.41291], [2.11621, 42.38393], [2.06241, 42.35906], [2.00488, 42.35399], [1.96482, 42.37787], [1.9574, 42.42401], [1.94084, 42.43039], [1.94061, 42.43333], [1.94292, 42.44316], [1.93663, 42.45439], [1.88853, 42.4501], [1.83037, 42.48395], [1.76335, 42.48863], [1.72515, 42.50338], [1.70571, 42.48867], [1.66826, 42.50779], [1.65674, 42.47125], [1.58933, 42.46275], [1.57953, 42.44957], [1.55937, 42.45808], [1.55073, 42.43299], [1.5127, 42.42959], [1.44529, 42.43724], [1.43838, 42.47848], [1.41648, 42.48315], [1.46661, 42.50949], [1.44759, 42.54431], [1.41245, 42.53539], [1.4234, 42.55959], [1.44529, 42.56722], [1.42512, 42.58292], [1.44197, 42.60217], [1.35562, 42.71944], [1.15928, 42.71407], [1.0804, 42.78569], [0.98292, 42.78754], [0.96166, 42.80629], [0.93089, 42.79154], [0.711, 42.86372], [0.66121, 42.84021], [0.65421, 42.75872], [0.67873, 42.69458], [0.40214, 42.69779], [0.36251, 42.72282], [0.29407, 42.67431], [0.25336, 42.7174], [0.17569, 42.73424], [-0.02468, 42.68513], [-0.10519, 42.72761], [-0.16141, 42.79535], [-0.17939, 42.78974], [-0.3122, 42.84788], [-0.38833, 42.80132], [-0.41319, 42.80776], [-0.44334, 42.79939], [-0.50863, 42.82713], [-0.55497, 42.77846], [-0.67637, 42.88303], [-0.69837, 42.87945], [-0.72608, 42.89318], [-0.73422, 42.91228], [-0.72037, 42.92541], [-0.75478, 42.96916], [-0.81652, 42.95166], [-0.97133, 42.96239], [-1.00963, 42.99279], [-1.10333, 43.0059], [-1.22881, 43.05534], [-1.25244, 43.04164], [-1.30531, 43.06859], [-1.30052, 43.09581], [-1.27118, 43.11961], [-1.32209, 43.1127], [-1.34419, 43.09665], [-1.35272, 43.02658], [-1.44067, 43.047], [-1.47555, 43.08372], [-1.41562, 43.12815], [-1.3758, 43.24511], [-1.40942, 43.27272], [-1.45289, 43.27049], [-1.50992, 43.29481], [-1.55963, 43.28828], [-1.57674, 43.25269], [-1.61341, 43.25269], [-1.63052, 43.28591], [-1.62481, 43.30726], [-1.69407, 43.31378], [-1.73074, 43.29481], [-1.7397, 43.32979], [-1.75079, 43.3317], [-1.75334, 43.34107], [-1.77068, 43.34396], [-1.78714, 43.35476], [-1.78332, 43.36399], [-1.79319, 43.37497], [-1.77289, 43.38957], [-1.81005, 43.59738], [-10.14298, 44.17365], [-11.19304, 41.83075], [-8.87157, 41.86488], [-8.81794, 41.90375], [-8.75712, 41.92833], [-8.74606, 41.9469], [-8.7478, 41.96282], [-8.69071, 41.98862], [-8.6681, 41.99703], [-8.65832, 42.02972], [-8.64626, 42.03668], [-8.63791, 42.04691], [-8.59493, 42.05708], [-8.58086, 42.05147], [-8.54563, 42.0537], [-8.5252, 42.06264], [-8.52837, 42.07658], [-8.48185, 42.0811], [-8.44123, 42.08218], [-8.42512, 42.07199], [-8.40143, 42.08052], [-8.38323, 42.07683], [-8.36353, 42.09065], [-8.33912, 42.08358], [-8.32161, 42.10218], [-8.29809, 42.106], [-8.2732, 42.12396], [-8.24681, 42.13993], [-8.22406, 42.1328], [-8.1986, 42.15402], [-8.18947, 42.13853], [-8.19406, 42.12141], [-8.18178, 42.06436], [-8.11729, 42.08537], [-8.08847, 42.05767], [-8.08796, 42.01398], [-8.16232, 41.9828], [-8.2185, 41.91237], [-8.19551, 41.87459], [-8.16944, 41.87944], [-8.16455, 41.81753], [-8.0961, 41.81024], [-8.01136, 41.83453], [-7.9804, 41.87337], [-7.92336, 41.8758], [-7.90707, 41.92432], [-7.88751, 41.92553], [-7.88055, 41.84571], [-7.84188, 41.88065], [-7.69848, 41.90977], [-7.65774, 41.88308], [-7.58603, 41.87944], [-7.62188, 41.83089], [-7.52737, 41.83939], [-7.49803, 41.87095], [-7.45566, 41.86488], [-7.44759, 41.84451], [-7.42854, 41.83262], [-7.42864, 41.80589], [-7.37092, 41.85031], [-7.32366, 41.8406], [-7.18677, 41.88793], [-7.18549, 41.97515], [-7.14115, 41.98855], [-7.08574, 41.97401], [-7.07596, 41.94977], [-7.01078, 41.94977], [-6.98144, 41.9728], [-6.95537, 41.96553], [-6.94396, 41.94403], [-6.82174, 41.94493], [-6.81196, 41.99097], [-6.76959, 41.98734], [-6.75004, 41.94129], [-6.61967, 41.94008], [-6.58544, 41.96674], [-6.5447, 41.94371], [-6.56752, 41.88429], [-6.51374, 41.8758], [-6.56426, 41.74219], [-6.54633, 41.68623], [-6.49907, 41.65823], [-6.44204, 41.68258], [-6.29863, 41.66432], [-6.19128, 41.57638], [-6.26777, 41.48796], [-6.3306, 41.37677], [-6.38553, 41.38655], [-6.38551, 41.35274], [-6.55937, 41.24417], [-6.65046, 41.24725], [-6.68286, 41.21641], [-6.69711, 41.1858], [-6.77319, 41.13049], [-6.75655, 41.10187], [-6.79241, 41.05397], [-6.80942, 41.03629], [-6.84781, 41.02692], [-6.88843, 41.03027], [-6.913, 41.03922], [-6.9357, 41.02888], [-6.8527, 40.93958], [-6.84292, 40.89771], [-6.80707, 40.88047], [-6.79892, 40.84842], [-6.82337, 40.84472], [-6.82826, 40.74603], [-6.79567, 40.65955], [-6.84292, 40.56801], [-6.80218, 40.55067], [-6.7973, 40.51723], [-6.84944, 40.46394], [-6.84618, 40.42177], [-6.78426, 40.36468], [-6.80218, 40.33239], [-6.86085, 40.2976], [-6.86085, 40.26776], [-7.00426, 40.23169], [-7.02544, 40.18564], [-7.00589, 40.12087], [-6.94233, 40.10716], [-6.86737, 40.01986], [-6.91463, 39.86618], [-6.97492, 39.81488], [-7.01613, 39.66877], [-7.24707, 39.66576], [-7.33507, 39.64569], [-7.54121, 39.66717], [-7.49477, 39.58794], [-7.2927, 39.45847], [-7.3149, 39.34857], [-7.23403, 39.27579], [-7.23566, 39.20132], [-7.12811, 39.17101], [-7.14929, 39.11287], [-7.10692, 39.10275], [-7.04011, 39.11919], [-6.97004, 39.07619], [-6.95211, 39.0243], [-7.051, 38.907], [-7.03848, 38.87221], [-7.26174, 38.72107], [-7.265, 38.61674], [-7.32529, 38.44336], [-7.15581, 38.27597], [-7.09389, 38.17227], [-6.93418, 38.21454], [-7.00375, 38.01914], [-7.05966, 38.01966], [-7.10366, 38.04404], [-7.12648, 38.00296], [-7.24544, 37.98884], [-7.27314, 37.90145], [-7.33441, 37.81193], [-7.41981, 37.75729], [-7.51759, 37.56119], [-7.46878, 37.47127], [-7.43974, 37.38913], [-7.43227, 37.25152], [-7.41854, 37.23813], [-7.41133, 37.20314], [-7.39769, 37.16868], [-7.37282, 36.96896], [-7.2725, 35.73269], [-5.10878, 36.05227], [-2.27707, 35.35051], [3.75438, 42.33445]], [[-5.27801, 36.14942], [-5.34064, 36.03744], [-5.40526, 36.15488], [-5.34536, 36.15501], [-5.33822, 36.15272], [-5.27801, 36.14942]]], [[[1.99838, 42.44682], [2.01564, 42.45171], [1.99216, 42.46208], [1.98579, 42.47486], [1.99766, 42.4858], [1.98916, 42.49351], [1.98022, 42.49569], [1.97697, 42.48568], [1.97227, 42.48487], [1.97003, 42.48081], [1.96215, 42.47854], [1.95606, 42.45785], [1.96125, 42.45364], [1.98378, 42.44697], [1.99838, 42.44682]]]]
23267           }
23268         }, {
23269           type: "Feature",
23270           properties: {
23271             wikidata: "Q98059339",
23272             nameEn: "Mainland Norway",
23273             country: "NO",
23274             groups: ["154", "150", "UN"],
23275             callingCodes: ["47"]
23276           },
23277           geometry: {
23278             type: "MultiPolygon",
23279             coordinates: [[[[10.40861, 58.38489], [10.64958, 58.89391], [11.08911, 58.98745], [11.15367, 59.07862], [11.34459, 59.11672], [11.4601, 58.99022], [11.45199, 58.89604], [11.65732, 58.90177], [11.8213, 59.24985], [11.69297, 59.59442], [11.92112, 59.69531], [11.87121, 59.86039], [12.15641, 59.8926], [12.36317, 59.99259], [12.52003, 60.13846], [12.59133, 60.50559], [12.2277, 61.02442], [12.69115, 61.06584], [12.86939, 61.35427], [12.57707, 61.56547], [12.40595, 61.57226], [12.14746, 61.7147], [12.29187, 62.25699], [12.07085, 62.6297], [12.19919, 63.00104], [11.98529, 63.27487], [12.19919, 63.47935], [12.14928, 63.59373], [12.74105, 64.02171], [13.23411, 64.09087], [13.98222, 64.00953], [14.16051, 64.18725], [14.11117, 64.46674], [13.64276, 64.58402], [14.50926, 65.31786], [14.53778, 66.12399], [15.05113, 66.15572], [15.49318, 66.28509], [15.37197, 66.48217], [16.35589, 67.06419], [16.39154, 67.21653], [16.09922, 67.4364], [16.12774, 67.52106], [16.38441, 67.52923], [16.7409, 67.91037], [17.30416, 68.11591], [17.90787, 67.96537], [18.13836, 68.20874], [18.1241, 68.53721], [18.39503, 68.58672], [18.63032, 68.50849], [18.97255, 68.52416], [19.93508, 68.35911], [20.22027, 68.48759], [19.95647, 68.55546], [20.22027, 68.67246], [20.33435, 68.80174], [20.28444, 68.93283], [20.0695, 69.04469], [20.55258, 69.06069], [20.72171, 69.11874], [21.05775, 69.0356], [21.11099, 69.10291], [20.98641, 69.18809], [21.00732, 69.22755], [21.27827, 69.31281], [21.63833, 69.27485], [22.27276, 68.89514], [22.38367, 68.71561], [22.53321, 68.74393], [23.13064, 68.64684], [23.68017, 68.70276], [23.781, 68.84514], [24.02299, 68.81601], [24.18432, 68.73936], [24.74898, 68.65143], [24.90023, 68.55579], [24.93048, 68.61102], [25.10189, 68.63307], [25.12206, 68.78684], [25.42455, 68.90328], [25.61613, 68.89602], [25.75729, 68.99383], [25.69679, 69.27039], [25.96904, 69.68397], [26.40261, 69.91377], [26.64461, 69.96565], [27.05802, 69.92069], [27.57226, 70.06215], [27.95542, 70.0965], [27.97558, 69.99671], [28.32849, 69.88605], [28.36883, 69.81658], [29.12697, 69.69193], [29.31664, 69.47994], [28.8629, 69.22395], [28.81248, 69.11997], [28.91738, 69.04774], [29.0444, 69.0119], [29.26623, 69.13794], [29.27631, 69.2811], [29.97205, 69.41623], [30.16363, 69.65244], [30.52662, 69.54699], [30.95011, 69.54699], [30.84095, 69.80584], [31.59909, 70.16571], [32.07813, 72.01005], [-11.60274, 67.73467], [7.28637, 57.35913], [10.40861, 58.38489]]]]
23280           }
23281         }, {
23282           type: "Feature",
23283           properties: {
23284             wikidata: "Q98543636",
23285             nameEn: "Mainland Ecuador",
23286             country: "EC",
23287             groups: ["005", "419", "019", "UN"],
23288             callingCodes: ["593"]
23289           },
23290           geometry: {
23291             type: "MultiPolygon",
23292             coordinates: [[[[-84.52388, -3.36941], [-80.30602, -3.39149], [-80.20647, -3.431], [-80.24123, -3.46124], [-80.24586, -3.48677], [-80.23651, -3.48652], [-80.22629, -3.501], [-80.20535, -3.51667], [-80.21642, -3.5888], [-80.19848, -3.59249], [-80.18741, -3.63994], [-80.19926, -3.68894], [-80.13232, -3.90317], [-80.46386, -4.01342], [-80.4822, -4.05477], [-80.45023, -4.20938], [-80.32114, -4.21323], [-80.46386, -4.41516], [-80.39256, -4.48269], [-80.13945, -4.29786], [-79.79722, -4.47558], [-79.59402, -4.46848], [-79.26248, -4.95167], [-79.1162, -4.97774], [-79.01659, -5.01481], [-78.85149, -4.66795], [-78.68394, -4.60754], [-78.34362, -3.38633], [-78.24589, -3.39907], [-78.22642, -3.51113], [-78.14324, -3.47653], [-78.19369, -3.36431], [-77.94147, -3.05454], [-76.6324, -2.58397], [-76.05203, -2.12179], [-75.57429, -1.55961], [-75.3872, -0.9374], [-75.22862, -0.95588], [-75.22862, -0.60048], [-75.53615, -0.19213], [-75.60169, -0.18708], [-75.61997, -0.10012], [-75.40192, -0.17196], [-75.25764, -0.11943], [-75.82927, 0.09578], [-76.23441, 0.42294], [-76.41215, 0.38228], [-76.4094, 0.24015], [-76.89177, 0.24736], [-77.52001, 0.40782], [-77.49984, 0.64476], [-77.67815, 0.73863], [-77.66416, 0.81604], [-77.68613, 0.83029], [-77.7148, 0.85003], [-77.85677, 0.80197], [-78.42749, 1.15389], [-78.87137, 1.47457], [-82.12561, 4.00341], [-84.52388, -3.36941]]]]
23293           }
23294         }, {
23295           type: "Feature",
23296           properties: {
23297             m49: "001",
23298             wikidata: "Q2",
23299             nameEn: "World",
23300             aliases: ["Earth", "Planet"],
23301             level: "world"
23302           },
23303           geometry: null
23304         }, {
23305           type: "Feature",
23306           properties: {
23307             m49: "002",
23308             wikidata: "Q15",
23309             nameEn: "Africa",
23310             level: "region"
23311           },
23312           geometry: null
23313         }, {
23314           type: "Feature",
23315           properties: {
23316             m49: "003",
23317             wikidata: "Q49",
23318             nameEn: "North America",
23319             level: "subregion"
23320           },
23321           geometry: null
23322         }, {
23323           type: "Feature",
23324           properties: {
23325             m49: "005",
23326             wikidata: "Q18",
23327             nameEn: "South America",
23328             level: "intermediateRegion"
23329           },
23330           geometry: null
23331         }, {
23332           type: "Feature",
23333           properties: {
23334             m49: "009",
23335             wikidata: "Q538",
23336             nameEn: "Oceania",
23337             level: "region"
23338           },
23339           geometry: null
23340         }, {
23341           type: "Feature",
23342           properties: {
23343             m49: "011",
23344             wikidata: "Q4412",
23345             nameEn: "Western Africa",
23346             level: "intermediateRegion"
23347           },
23348           geometry: null
23349         }, {
23350           type: "Feature",
23351           properties: {
23352             m49: "013",
23353             wikidata: "Q27611",
23354             nameEn: "Central America",
23355             level: "intermediateRegion"
23356           },
23357           geometry: null
23358         }, {
23359           type: "Feature",
23360           properties: {
23361             m49: "014",
23362             wikidata: "Q27407",
23363             nameEn: "Eastern Africa",
23364             level: "intermediateRegion"
23365           },
23366           geometry: null
23367         }, {
23368           type: "Feature",
23369           properties: {
23370             m49: "015",
23371             wikidata: "Q27381",
23372             nameEn: "Northern Africa",
23373             level: "subregion"
23374           },
23375           geometry: null
23376         }, {
23377           type: "Feature",
23378           properties: {
23379             m49: "017",
23380             wikidata: "Q27433",
23381             nameEn: "Middle Africa",
23382             level: "intermediateRegion"
23383           },
23384           geometry: null
23385         }, {
23386           type: "Feature",
23387           properties: {
23388             m49: "018",
23389             wikidata: "Q27394",
23390             nameEn: "Southern Africa",
23391             level: "intermediateRegion"
23392           },
23393           geometry: null
23394         }, {
23395           type: "Feature",
23396           properties: {
23397             m49: "019",
23398             wikidata: "Q828",
23399             nameEn: "Americas",
23400             level: "region"
23401           },
23402           geometry: null
23403         }, {
23404           type: "Feature",
23405           properties: {
23406             m49: "021",
23407             wikidata: "Q2017699",
23408             nameEn: "Northern America",
23409             level: "subregion"
23410           },
23411           geometry: null
23412         }, {
23413           type: "Feature",
23414           properties: {
23415             m49: "029",
23416             wikidata: "Q664609",
23417             nameEn: "Caribbean",
23418             level: "intermediateRegion"
23419           },
23420           geometry: null
23421         }, {
23422           type: "Feature",
23423           properties: {
23424             m49: "030",
23425             wikidata: "Q27231",
23426             nameEn: "Eastern Asia",
23427             level: "subregion"
23428           },
23429           geometry: null
23430         }, {
23431           type: "Feature",
23432           properties: {
23433             m49: "034",
23434             wikidata: "Q771405",
23435             nameEn: "Southern Asia",
23436             level: "subregion"
23437           },
23438           geometry: null
23439         }, {
23440           type: "Feature",
23441           properties: {
23442             m49: "035",
23443             wikidata: "Q11708",
23444             nameEn: "South-eastern Asia",
23445             level: "subregion"
23446           },
23447           geometry: null
23448         }, {
23449           type: "Feature",
23450           properties: {
23451             m49: "039",
23452             wikidata: "Q27449",
23453             nameEn: "Southern Europe",
23454             level: "subregion"
23455           },
23456           geometry: null
23457         }, {
23458           type: "Feature",
23459           properties: {
23460             m49: "053",
23461             wikidata: "Q45256",
23462             nameEn: "Australia and New Zealand",
23463             aliases: ["Australasia"],
23464             level: "subregion"
23465           },
23466           geometry: null
23467         }, {
23468           type: "Feature",
23469           properties: {
23470             m49: "054",
23471             wikidata: "Q37394",
23472             nameEn: "Melanesia",
23473             level: "subregion"
23474           },
23475           geometry: null
23476         }, {
23477           type: "Feature",
23478           properties: {
23479             m49: "057",
23480             wikidata: "Q3359409",
23481             nameEn: "Micronesia",
23482             level: "subregion"
23483           },
23484           geometry: null
23485         }, {
23486           type: "Feature",
23487           properties: {
23488             m49: "061",
23489             wikidata: "Q35942",
23490             nameEn: "Polynesia",
23491             level: "subregion"
23492           },
23493           geometry: null
23494         }, {
23495           type: "Feature",
23496           properties: {
23497             m49: "142",
23498             wikidata: "Q48",
23499             nameEn: "Asia",
23500             level: "region"
23501           },
23502           geometry: null
23503         }, {
23504           type: "Feature",
23505           properties: {
23506             m49: "143",
23507             wikidata: "Q27275",
23508             nameEn: "Central Asia",
23509             level: "subregion"
23510           },
23511           geometry: null
23512         }, {
23513           type: "Feature",
23514           properties: {
23515             m49: "145",
23516             wikidata: "Q27293",
23517             nameEn: "Western Asia",
23518             level: "subregion"
23519           },
23520           geometry: null
23521         }, {
23522           type: "Feature",
23523           properties: {
23524             m49: "150",
23525             wikidata: "Q46",
23526             nameEn: "Europe",
23527             level: "region"
23528           },
23529           geometry: null
23530         }, {
23531           type: "Feature",
23532           properties: {
23533             m49: "151",
23534             wikidata: "Q27468",
23535             nameEn: "Eastern Europe",
23536             level: "subregion"
23537           },
23538           geometry: null
23539         }, {
23540           type: "Feature",
23541           properties: {
23542             m49: "154",
23543             wikidata: "Q27479",
23544             nameEn: "Northern Europe",
23545             level: "subregion"
23546           },
23547           geometry: null
23548         }, {
23549           type: "Feature",
23550           properties: {
23551             m49: "155",
23552             wikidata: "Q27496",
23553             nameEn: "Western Europe",
23554             level: "subregion"
23555           },
23556           geometry: null
23557         }, {
23558           type: "Feature",
23559           properties: {
23560             m49: "202",
23561             wikidata: "Q132959",
23562             nameEn: "Sub-Saharan Africa",
23563             level: "subregion"
23564           },
23565           geometry: null
23566         }, {
23567           type: "Feature",
23568           properties: {
23569             m49: "419",
23570             wikidata: "Q72829598",
23571             nameEn: "Latin America and the Caribbean",
23572             level: "subregion"
23573           },
23574           geometry: null
23575         }, {
23576           type: "Feature",
23577           properties: {
23578             m49: "680",
23579             wikidata: "Q3405693",
23580             nameEn: "Sark",
23581             country: "GB",
23582             groups: ["GG", "830", "Q185086", "154", "150", "UN"],
23583             level: "subterritory",
23584             driveSide: "left",
23585             roadSpeedUnit: "mph",
23586             roadHeightUnit: "ft",
23587             callingCodes: ["44 01481"]
23588           },
23589           geometry: {
23590             type: "MultiPolygon",
23591             coordinates: [[[[-2.36485, 49.48223], [-2.65349, 49.15373], [-2.09454, 49.46288], [-2.36485, 49.48223]]]]
23592           }
23593         }, {
23594           type: "Feature",
23595           properties: {
23596             m49: "830",
23597             wikidata: "Q42314",
23598             nameEn: "Channel Islands",
23599             level: "intermediateRegion"
23600           },
23601           geometry: null
23602         }, {
23603           type: "Feature",
23604           properties: {
23605             iso1A2: "AC",
23606             iso1A3: "ASC",
23607             wikidata: "Q46197",
23608             nameEn: "Ascension Island",
23609             aliases: ["SH-AC"],
23610             country: "GB",
23611             groups: ["SH", "BOTS", "011", "202", "002", "UN"],
23612             isoStatus: "excRes",
23613             driveSide: "left",
23614             roadSpeedUnit: "mph",
23615             roadHeightUnit: "ft",
23616             callingCodes: ["247"]
23617           },
23618           geometry: {
23619             type: "MultiPolygon",
23620             coordinates: [[[[-14.82771, -8.70814], [-13.33271, -8.07391], [-14.91926, -6.63386], [-14.82771, -8.70814]]]]
23621           }
23622         }, {
23623           type: "Feature",
23624           properties: {
23625             iso1A2: "AD",
23626             iso1A3: "AND",
23627             iso1N3: "020",
23628             wikidata: "Q228",
23629             nameEn: "Andorra",
23630             groups: ["Q12837", "039", "150", "UN"],
23631             callingCodes: ["376"]
23632           },
23633           geometry: {
23634             type: "MultiPolygon",
23635             coordinates: [[[[1.72515, 42.50338], [1.73683, 42.55492], [1.7858, 42.57698], [1.72588, 42.59098], [1.73452, 42.61515], [1.68267, 42.62533], [1.6625, 42.61982], [1.63485, 42.62957], [1.60085, 42.62703], [1.55418, 42.65669], [1.50867, 42.64483], [1.48043, 42.65203], [1.46718, 42.63296], [1.47986, 42.61346], [1.44197, 42.60217], [1.42512, 42.58292], [1.44529, 42.56722], [1.4234, 42.55959], [1.41245, 42.53539], [1.44759, 42.54431], [1.46661, 42.50949], [1.41648, 42.48315], [1.43838, 42.47848], [1.44529, 42.43724], [1.5127, 42.42959], [1.55073, 42.43299], [1.55937, 42.45808], [1.57953, 42.44957], [1.58933, 42.46275], [1.65674, 42.47125], [1.66826, 42.50779], [1.70571, 42.48867], [1.72515, 42.50338]]]]
23636           }
23637         }, {
23638           type: "Feature",
23639           properties: {
23640             iso1A2: "AE",
23641             iso1A3: "ARE",
23642             iso1N3: "784",
23643             wikidata: "Q878",
23644             nameEn: "United Arab Emirates",
23645             groups: ["145", "142", "UN"],
23646             callingCodes: ["971"]
23647           },
23648           geometry: {
23649             type: "MultiPolygon",
23650             coordinates: [[[[56.26534, 25.62825], [56.25341, 25.61443], [56.26636, 25.60643], [56.25365, 25.60211], [56.20473, 25.61119], [56.18363, 25.65508], [56.14826, 25.66351], [56.13579, 25.73524], [56.17416, 25.77239], [56.13963, 25.82765], [56.19334, 25.9795], [56.15498, 26.06828], [56.08666, 26.05038], [55.81777, 26.18798], [55.14145, 25.62624], [53.97892, 24.64436], [52.82259, 25.51697], [52.35509, 25.00368], [52.02277, 24.75635], [51.83108, 24.71675], [51.58834, 24.66608], [51.41644, 24.39615], [51.58871, 24.27256], [51.59617, 24.12041], [52.56622, 22.94341], [55.13599, 22.63334], [55.2137, 22.71065], [55.22634, 23.10378], [55.57358, 23.669], [55.48677, 23.94946], [55.73301, 24.05994], [55.8308, 24.01633], [56.01799, 24.07426], [55.95472, 24.2172], [55.83367, 24.20193], [55.77658, 24.23476], [55.76558, 24.23227], [55.75257, 24.23466], [55.75382, 24.2466], [55.75939, 24.26114], [55.76781, 24.26209], [55.79145, 24.27914], [55.80747, 24.31069], [55.83395, 24.32776], [55.83271, 24.41521], [55.76461, 24.5287], [55.83271, 24.68567], [55.83408, 24.77858], [55.81348, 24.80102], [55.81116, 24.9116], [55.85094, 24.96858], [55.90849, 24.96771], [55.96316, 25.00857], [56.05715, 24.95727], [56.05106, 24.87461], [55.97467, 24.89639], [55.97836, 24.87673], [56.03535, 24.81161], [56.06128, 24.74457], [56.13684, 24.73699], [56.20062, 24.78565], [56.20568, 24.85063], [56.30269, 24.88334], [56.34873, 24.93205], [56.3227, 24.97284], [56.86325, 25.03856], [56.82555, 25.7713], [56.26534, 25.62825]], [[56.26062, 25.33108], [56.3005, 25.31815], [56.3111, 25.30107], [56.35172, 25.30681], [56.34438, 25.26653], [56.27628, 25.23404], [56.24341, 25.22867], [56.20872, 25.24104], [56.20838, 25.25668], [56.24465, 25.27505], [56.25008, 25.28843], [56.23362, 25.31253], [56.26062, 25.33108]]], [[[56.28423, 25.26344], [56.29379, 25.2754], [56.28102, 25.28486], [56.2716, 25.27916], [56.27086, 25.26128], [56.28423, 25.26344]]]]
23651           }
23652         }, {
23653           type: "Feature",
23654           properties: {
23655             iso1A2: "AF",
23656             iso1A3: "AFG",
23657             iso1N3: "004",
23658             wikidata: "Q889",
23659             nameEn: "Afghanistan",
23660             groups: ["034", "142", "UN"],
23661             callingCodes: ["93"]
23662           },
23663           geometry: {
23664             type: "MultiPolygon",
23665             coordinates: [[[[70.61526, 38.34774], [70.60407, 38.28046], [70.54673, 38.24541], [70.4898, 38.12546], [70.17206, 37.93276], [70.1863, 37.84296], [70.27694, 37.81258], [70.28243, 37.66706], [70.15015, 37.52519], [69.95971, 37.5659], [69.93362, 37.61378], [69.84435, 37.60616], [69.80041, 37.5746], [69.51888, 37.5844], [69.44954, 37.4869], [69.36645, 37.40462], [69.45022, 37.23315], [69.39529, 37.16752], [69.25152, 37.09426], [69.03274, 37.25174], [68.96407, 37.32603], [68.88168, 37.33368], [68.91189, 37.26704], [68.80889, 37.32494], [68.81438, 37.23862], [68.6798, 37.27906], [68.61851, 37.19815], [68.41888, 37.13906], [68.41201, 37.10402], [68.29253, 37.10621], [68.27605, 37.00977], [68.18542, 37.02074], [68.02194, 36.91923], [67.87917, 37.0591], [67.7803, 37.08978], [67.78329, 37.1834], [67.51868, 37.26102], [67.2581, 37.17216], [67.2224, 37.24545], [67.13039, 37.27168], [67.08232, 37.35469], [66.95598, 37.40162], [66.64699, 37.32958], [66.55743, 37.35409], [66.30993, 37.32409], [65.72274, 37.55438], [65.64137, 37.45061], [65.64263, 37.34388], [65.51778, 37.23881], [64.97945, 37.21913], [64.61141, 36.6351], [64.62514, 36.44311], [64.57295, 36.34362], [64.43288, 36.24401], [64.05385, 36.10433], [63.98519, 36.03773], [63.56496, 35.95106], [63.53475, 35.90881], [63.29579, 35.85985], [63.12276, 35.86208], [63.10318, 35.81782], [63.23262, 35.67487], [63.10079, 35.63024], [63.12276, 35.53196], [63.0898, 35.43131], [62.90853, 35.37086], [62.74098, 35.25432], [62.62288, 35.22067], [62.48006, 35.28796], [62.29878, 35.13312], [62.29191, 35.25964], [62.15871, 35.33278], [62.05709, 35.43803], [61.97743, 35.4604], [61.77693, 35.41341], [61.58742, 35.43803], [61.27371, 35.61482], [61.18187, 35.30249], [61.0991, 35.27845], [61.12831, 35.09938], [61.06926, 34.82139], [61.00197, 34.70631], [60.99922, 34.63064], [60.72316, 34.52857], [60.91321, 34.30411], [60.66502, 34.31539], [60.50209, 34.13992], [60.5838, 33.80793], [60.5485, 33.73422], [60.57762, 33.59772], [60.69573, 33.56054], [60.91133, 33.55596], [60.88908, 33.50219], [60.56485, 33.12944], [60.86191, 32.22565], [60.84541, 31.49561], [61.70929, 31.37391], [61.80569, 31.16167], [61.80957, 31.12576], [61.83257, 31.0452], [61.8335, 30.97669], [61.78268, 30.92724], [61.80829, 30.84224], [60.87231, 29.86514], [62.47751, 29.40782], [63.5876, 29.50456], [64.12966, 29.39157], [64.19796, 29.50407], [64.62116, 29.58903], [65.04005, 29.53957], [66.24175, 29.85181], [66.36042, 29.9583], [66.23609, 30.06321], [66.34869, 30.404], [66.28413, 30.57001], [66.39194, 30.9408], [66.42645, 30.95309], [66.58175, 30.97532], [66.68166, 31.07597], [66.72561, 31.20526], [66.83273, 31.26867], [67.04147, 31.31561], [67.03323, 31.24519], [67.29964, 31.19586], [67.78854, 31.33203], [67.7748, 31.4188], [67.62374, 31.40473], [67.58323, 31.52772], [67.72056, 31.52304], [67.86887, 31.63536], [68.00071, 31.6564], [68.1655, 31.82691], [68.25614, 31.80357], [68.27605, 31.75863], [68.44222, 31.76446], [68.57475, 31.83158], [68.6956, 31.75687], [68.79997, 31.61665], [68.91078, 31.59687], [68.95995, 31.64822], [69.00939, 31.62249], [69.11514, 31.70782], [69.20577, 31.85957], [69.3225, 31.93186], [69.27032, 32.14141], [69.27932, 32.29119], [69.23599, 32.45946], [69.2868, 32.53938], [69.38155, 32.56601], [69.44747, 32.6678], [69.43649, 32.7302], [69.38018, 32.76601], [69.47082, 32.85834], [69.5436, 32.8768], [69.49854, 32.88843], [69.49004, 33.01509], [69.57656, 33.09911], [69.71526, 33.09911], [69.79766, 33.13247], [69.85259, 33.09451], [70.02563, 33.14282], [70.07369, 33.22557], [70.13686, 33.21064], [70.32775, 33.34496], [70.17062, 33.53535], [70.20141, 33.64387], [70.14785, 33.6553], [70.14236, 33.71701], [70.00503, 33.73528], [69.85671, 33.93719], [69.87307, 33.9689], [69.90203, 34.04194], [70.54336, 33.9463], [70.88119, 33.97933], [71.07345, 34.06242], [71.06933, 34.10564], [71.09307, 34.11961], [71.09453, 34.13524], [71.13078, 34.16503], [71.12815, 34.26619], [71.17662, 34.36769], [71.02401, 34.44835], [71.0089, 34.54568], [71.11602, 34.63047], [71.08718, 34.69034], [71.28356, 34.80882], [71.29472, 34.87728], [71.50329, 34.97328], [71.49917, 35.00478], [71.55273, 35.02615], [71.52938, 35.09023], [71.67495, 35.21262], [71.5541, 35.28776], [71.54294, 35.31037], [71.65435, 35.4479], [71.49917, 35.6267], [71.55273, 35.71483], [71.37969, 35.95865], [71.19505, 36.04134], [71.60491, 36.39429], [71.80267, 36.49924], [72.18135, 36.71838], [72.6323, 36.84601], [73.82685, 36.91421], [74.04856, 36.82648], [74.43389, 37.00977], [74.53739, 36.96224], [74.56453, 37.03023], [74.49981, 37.24518], [74.80605, 37.21565], [74.88887, 37.23275], [74.8294, 37.3435], [74.68383, 37.3948], [74.56161, 37.37734], [74.41055, 37.3948], [74.23339, 37.41116], [74.20308, 37.34208], [73.8564, 37.26158], [73.82552, 37.22659], [73.64974, 37.23643], [73.61129, 37.27469], [73.76647, 37.33913], [73.77197, 37.4417], [73.29633, 37.46495], [73.06884, 37.31729], [72.79693, 37.22222], [72.66381, 37.02014], [72.54095, 37.00007], [72.31676, 36.98115], [71.83229, 36.68084], [71.67083, 36.67346], [71.57195, 36.74943], [71.51502, 36.89128], [71.48481, 36.93218], [71.46923, 36.99925], [71.45578, 37.03094], [71.43097, 37.05855], [71.44127, 37.11856], [71.4494, 37.18137], [71.4555, 37.21418], [71.47386, 37.2269], [71.48339, 37.23937], [71.4824, 37.24921], [71.48536, 37.26017], [71.50674, 37.31502], [71.49821, 37.31975], [71.4862, 37.33405], [71.47685, 37.40281], [71.49612, 37.4279], [71.5256, 37.47971], [71.50616, 37.50733], [71.49693, 37.53527], [71.5065, 37.60912], [71.51972, 37.61945], [71.54186, 37.69691], [71.55234, 37.73209], [71.53053, 37.76534], [71.54324, 37.77104], [71.55752, 37.78677], [71.59255, 37.79956], [71.58843, 37.92425], [71.51565, 37.95349], [71.32871, 37.88564], [71.296, 37.93403], [71.2809, 37.91995], [71.24969, 37.93031], [71.27278, 37.96496], [71.27622, 37.99946], [71.28922, 38.01272], [71.29878, 38.04429], [71.36444, 38.15358], [71.37803, 38.25641], [71.33869, 38.27335], [71.33114, 38.30339], [71.21291, 38.32797], [71.1451, 38.40106], [71.10957, 38.40671], [71.10592, 38.42077], [71.09542, 38.42517], [71.0556, 38.40176], [71.03545, 38.44779], [70.98693, 38.48862], [70.92728, 38.43021], [70.88719, 38.46826], [70.84376, 38.44688], [70.82538, 38.45394], [70.81697, 38.44507], [70.80521, 38.44447], [70.79766, 38.44944], [70.78702, 38.45031], [70.78581, 38.45502], [70.77132, 38.45548], [70.75455, 38.4252], [70.72485, 38.4131], [70.69807, 38.41861], [70.67438, 38.40597], [70.6761, 38.39144], [70.69189, 38.37031], [70.64966, 38.34999], [70.61526, 38.34774]]]]
23666           }
23667         }, {
23668           type: "Feature",
23669           properties: {
23670             iso1A2: "AG",
23671             iso1A3: "ATG",
23672             iso1N3: "028",
23673             wikidata: "Q781",
23674             nameEn: "Antigua and Barbuda",
23675             groups: ["029", "003", "419", "019", "UN"],
23676             driveSide: "left",
23677             roadSpeedUnit: "mph",
23678             callingCodes: ["1 268"]
23679           },
23680           geometry: {
23681             type: "MultiPolygon",
23682             coordinates: [[[[-61.66959, 18.6782], [-62.58307, 16.68909], [-62.1023, 16.97277], [-61.23098, 16.62484], [-61.66959, 18.6782]]]]
23683           }
23684         }, {
23685           type: "Feature",
23686           properties: {
23687             iso1A2: "AI",
23688             iso1A3: "AIA",
23689             iso1N3: "660",
23690             wikidata: "Q25228",
23691             nameEn: "Anguilla",
23692             country: "GB",
23693             groups: ["BOTS", "029", "003", "419", "019", "UN"],
23694             driveSide: "left",
23695             roadSpeedUnit: "mph",
23696             callingCodes: ["1 264"]
23697           },
23698           geometry: {
23699             type: "MultiPolygon",
23700             coordinates: [[[[-63.79029, 19.11219], [-63.35989, 18.06012], [-62.62718, 18.26185], [-63.79029, 19.11219]]]]
23701           }
23702         }, {
23703           type: "Feature",
23704           properties: {
23705             iso1A2: "AL",
23706             iso1A3: "ALB",
23707             iso1N3: "008",
23708             wikidata: "Q222",
23709             nameEn: "Albania",
23710             groups: ["039", "150", "UN"],
23711             callingCodes: ["355"]
23712           },
23713           geometry: {
23714             type: "MultiPolygon",
23715             coordinates: [[[[20.07761, 42.55582], [20.01834, 42.54622], [20.00842, 42.5109], [19.9324, 42.51699], [19.82333, 42.46581], [19.76549, 42.50237], [19.74731, 42.57422], [19.77375, 42.58517], [19.73244, 42.66299], [19.65972, 42.62774], [19.4836, 42.40831], [19.42352, 42.36546], [19.42, 42.33019], [19.28623, 42.17745], [19.40687, 42.10024], [19.37548, 42.06835], [19.36867, 42.02564], [19.37691, 41.96977], [19.34601, 41.95675], [19.33812, 41.90669], [19.37451, 41.8842], [19.37597, 41.84849], [19.26406, 41.74971], [19.0384, 40.35325], [19.95905, 39.82857], [19.97622, 39.78684], [19.92466, 39.69533], [19.98042, 39.6504], [20.00957, 39.69227], [20.05189, 39.69112], [20.12956, 39.65805], [20.15988, 39.652], [20.22376, 39.64532], [20.22707, 39.67459], [20.27412, 39.69884], [20.31961, 39.72799], [20.29152, 39.80421], [20.30804, 39.81563], [20.38572, 39.78516], [20.41475, 39.81437], [20.41546, 39.82832], [20.31135, 39.99438], [20.37911, 39.99058], [20.42373, 40.06777], [20.48487, 40.06271], [20.51297, 40.08168], [20.55593, 40.06524], [20.61081, 40.07866], [20.62566, 40.0897], [20.67162, 40.09433], [20.71789, 40.27739], [20.78234, 40.35803], [20.7906, 40.42726], [20.83688, 40.47882], [20.94925, 40.46625], [20.96908, 40.51526], [21.03932, 40.56299], [21.05833, 40.66586], [20.98134, 40.76046], [20.95752, 40.76982], [20.98396, 40.79109], [20.97887, 40.85475], [20.97693, 40.90103], [20.94305, 40.92399], [20.83671, 40.92752], [20.81567, 40.89662], [20.73504, 40.9081], [20.71634, 40.91781], [20.65558, 41.08009], [20.63454, 41.0889], [20.59832, 41.09066], [20.58546, 41.11179], [20.59715, 41.13644], [20.51068, 41.2323], [20.49432, 41.33679], [20.52119, 41.34381], [20.55976, 41.4087], [20.51301, 41.442], [20.49039, 41.49277], [20.45331, 41.51436], [20.45809, 41.5549], [20.52103, 41.56473], [20.55508, 41.58113], [20.51769, 41.65975], [20.52937, 41.69292], [20.51301, 41.72433], [20.53405, 41.78099], [20.57144, 41.7897], [20.55976, 41.87068], [20.59524, 41.8818], [20.57946, 41.91593], [20.63069, 41.94913], [20.59434, 42.03879], [20.55633, 42.08173], [20.56955, 42.12097], [20.48857, 42.25444], [20.3819, 42.3029], [20.34479, 42.32656], [20.24399, 42.32168], [20.21797, 42.41237], [20.17127, 42.50469], [20.07761, 42.55582]]]]
23716           }
23717         }, {
23718           type: "Feature",
23719           properties: {
23720             iso1A2: "AM",
23721             iso1A3: "ARM",
23722             iso1N3: "051",
23723             wikidata: "Q399",
23724             nameEn: "Armenia",
23725             groups: ["145", "142", "UN"],
23726             callingCodes: ["374"]
23727           },
23728           geometry: {
23729             type: "MultiPolygon",
23730             coordinates: [[[[45.0133, 41.29747], [44.93493, 41.25685], [44.81437, 41.30371], [44.80053, 41.25949], [44.81749, 41.23488], [44.84358, 41.23088], [44.89911, 41.21366], [44.87887, 41.20195], [44.82084, 41.21513], [44.72814, 41.20338], [44.61462, 41.24018], [44.59322, 41.1933], [44.46791, 41.18204], [44.34417, 41.2382], [44.34337, 41.20312], [44.32139, 41.2079], [44.18148, 41.24644], [44.16591, 41.19141], [43.84835, 41.16329], [43.74717, 41.1117], [43.67712, 41.13398], [43.4717, 41.12611], [43.44984, 41.0988], [43.47319, 41.02251], [43.58683, 40.98961], [43.67712, 40.93084], [43.67712, 40.84846], [43.74872, 40.7365], [43.7425, 40.66805], [43.63664, 40.54159], [43.54791, 40.47413], [43.60862, 40.43267], [43.59928, 40.34019], [43.71136, 40.16673], [43.65221, 40.14889], [43.65688, 40.11199], [43.92307, 40.01787], [44.1057, 40.03555], [44.1778, 40.02845], [44.26973, 40.04866], [44.46635, 39.97733], [44.61845, 39.8281], [44.75779, 39.7148], [44.88354, 39.74432], [44.92869, 39.72157], [45.06604, 39.79277], [45.18554, 39.67846], [45.17464, 39.58614], [45.21784, 39.58074], [45.23535, 39.61373], [45.30385, 39.61373], [45.29606, 39.57654], [45.46992, 39.49888], [45.70547, 39.60174], [45.80804, 39.56716], [45.83, 39.46487], [45.79225, 39.3695], [45.99774, 39.28931], [46.02303, 39.09978], [46.06973, 39.0744], [46.14785, 38.84206], [46.20601, 38.85262], [46.34059, 38.92076], [46.53497, 38.86548], [46.51805, 38.94982], [46.54296, 39.07078], [46.44022, 39.19636], [46.52584, 39.18912], [46.54141, 39.15895], [46.58032, 39.21204], [46.63481, 39.23013], [46.56476, 39.24942], [46.50093, 39.33736], [46.43244, 39.35181], [46.37795, 39.42039], [46.4013, 39.45405], [46.53051, 39.47809], [46.51027, 39.52373], [46.57721, 39.54414], [46.57098, 39.56694], [46.52117, 39.58734], [46.42465, 39.57534], [46.40286, 39.63651], [46.18493, 39.60533], [45.96543, 39.78859], [45.82533, 39.82925], [45.7833, 39.9475], [45.60895, 39.97733], [45.59806, 40.0131], [45.78642, 40.03218], [45.83779, 39.98925], [45.97944, 40.181], [45.95609, 40.27846], [45.65098, 40.37696], [45.42994, 40.53804], [45.45484, 40.57707], [45.35366, 40.65979], [45.4206, 40.7424], [45.55914, 40.78366], [45.60584, 40.87436], [45.40814, 40.97904], [45.44083, 41.01663], [45.39725, 41.02603], [45.35677, 40.99784], [45.28859, 41.03757], [45.26162, 41.0228], [45.25897, 41.0027], [45.1994, 41.04518], [45.16493, 41.05068], [45.1634, 41.08082], [45.1313, 41.09369], [45.12923, 41.06059], [45.06784, 41.05379], [45.08028, 41.10917], [45.19942, 41.13299], [45.1969, 41.168], [45.11811, 41.19967], [45.05201, 41.19211], [45.02932, 41.2101], [45.05497, 41.2464], [45.0133, 41.29747]], [[45.21324, 40.9817], [45.21219, 40.99001], [45.20518, 40.99348], [45.19312, 40.98998], [45.18382, 41.0066], [45.20625, 41.01484], [45.23487, 41.00226], [45.23095, 40.97828], [45.21324, 40.9817]], [[45.00864, 41.03411], [44.9903, 41.05657], [44.96031, 41.06345], [44.95383, 41.07553], [44.97169, 41.09176], [45.00864, 41.09407], [45.03406, 41.07931], [45.04517, 41.06653], [45.03792, 41.03938], [45.00864, 41.03411]]], [[[45.50279, 40.58424], [45.56071, 40.64765], [45.51825, 40.67382], [45.47927, 40.65023], [45.50279, 40.58424]]]]
23731           }
23732         }, {
23733           type: "Feature",
23734           properties: {
23735             iso1A2: "AO",
23736             iso1A3: "AGO",
23737             iso1N3: "024",
23738             wikidata: "Q916",
23739             nameEn: "Angola",
23740             groups: ["017", "202", "002", "UN"],
23741             callingCodes: ["244"]
23742           },
23743           geometry: {
23744             type: "MultiPolygon",
23745             coordinates: [[[[16.55507, -5.85631], [13.04371, -5.87078], [12.42245, -6.07585], [11.95767, -5.94705], [12.20376, -5.76338], [12.26557, -5.74031], [12.52318, -5.74353], [12.52301, -5.17481], [12.53599, -5.1618], [12.53586, -5.14658], [12.51589, -5.1332], [12.49815, -5.14058], [12.46297, -5.09408], [12.60251, -5.01715], [12.63465, -4.94632], [12.70868, -4.95505], [12.8733, -4.74346], [13.11195, -4.67745], [13.09648, -4.63739], [12.91489, -4.47907], [12.87096, -4.40315], [12.76844, -4.38709], [12.64835, -4.55937], [12.40964, -4.60609], [12.32324, -4.78415], [12.25587, -4.79437], [12.20901, -4.75642], [12.16068, -4.90089], [12.00924, -5.02627], [11.50888, -5.33417], [10.5065, -17.25284], [11.75063, -17.25013], [12.07076, -17.15165], [12.52111, -17.24495], [12.97145, -16.98567], [13.36212, -16.98048], [13.95896, -17.43141], [14.28743, -17.38814], [18.39229, -17.38927], [18.84226, -17.80375], [21.14283, -17.94318], [21.42741, -18.02787], [23.47474, -17.62877], [23.20038, -17.47563], [22.17217, -16.50269], [22.00323, -16.18028], [21.97988, -13.00148], [24.03339, -12.99091], [23.90937, -12.844], [24.06672, -12.29058], [23.98804, -12.13149], [24.02603, -11.15368], [24.00027, -10.89356], [23.86868, -11.02856], [23.45631, -10.946], [23.16602, -11.10577], [22.54205, -11.05784], [22.25951, -11.24911], [22.17954, -10.85884], [22.32604, -10.76291], [22.19039, -9.94628], [21.84856, -9.59871], [21.79824, -7.29628], [20.56263, -7.28566], [20.61689, -6.90876], [20.31846, -6.91953], [20.30218, -6.98955], [19.5469, -7.00195], [19.33698, -7.99743], [18.33635, -8.00126], [17.5828, -8.13784], [16.96282, -7.21787], [16.55507, -5.85631]]]]
23746           }
23747         }, {
23748           type: "Feature",
23749           properties: {
23750             iso1A2: "AQ",
23751             iso1A3: "ATA",
23752             iso1N3: "010",
23753             wikidata: "Q51",
23754             nameEn: "Antarctica",
23755             level: "region",
23756             callingCodes: ["672"]
23757           },
23758           geometry: {
23759             type: "MultiPolygon",
23760             coordinates: [[[[180, -60], [-180, -60], [-180, -90], [180, -90], [180, -60]]]]
23761           }
23762         }, {
23763           type: "Feature",
23764           properties: {
23765             iso1A2: "AR",
23766             iso1A3: "ARG",
23767             iso1N3: "032",
23768             wikidata: "Q414",
23769             nameEn: "Argentina",
23770             aliases: ["RA"],
23771             groups: ["005", "419", "019", "UN"],
23772             callingCodes: ["54"]
23773           },
23774           geometry: {
23775             type: "MultiPolygon",
23776             coordinates: [[[[-72.31343, -50.58411], [-72.33873, -51.59954], [-71.99889, -51.98018], [-69.97824, -52.00845], [-68.41683, -52.33516], [-68.60702, -52.65781], [-68.60733, -54.9125], [-68.01394, -54.8753], [-67.46182, -54.92205], [-67.11046, -54.94199], [-66.07313, -55.19618], [-63.67376, -55.11859], [-54.78916, -36.21945], [-57.83001, -34.69099], [-58.34425, -34.15035], [-58.44442, -33.84033], [-58.40475, -33.11777], [-58.1224, -32.98842], [-58.22362, -32.52416], [-58.10036, -32.25338], [-58.20252, -31.86966], [-58.00076, -31.65016], [-58.0023, -31.53084], [-58.07569, -31.44916], [-57.98127, -31.3872], [-57.9908, -31.34924], [-57.86729, -31.06352], [-57.89476, -30.95994], [-57.8024, -30.77193], [-57.89115, -30.49572], [-57.64859, -30.35095], [-57.61478, -30.25165], [-57.65132, -30.19229], [-57.09386, -29.74211], [-56.81251, -29.48154], [-56.62789, -29.18073], [-56.57295, -29.11357], [-56.54171, -29.11447], [-56.05265, -28.62651], [-56.00458, -28.60421], [-56.01729, -28.51223], [-55.65418, -28.18304], [-55.6262, -28.17124], [-55.33303, -27.94661], [-55.16872, -27.86224], [-55.1349, -27.89759], [-54.90805, -27.73149], [-54.90159, -27.63132], [-54.67657, -27.57214], [-54.50416, -27.48232], [-54.41888, -27.40882], [-54.19268, -27.30751], [-54.19062, -27.27639], [-54.15978, -27.2889], [-53.80144, -27.09844], [-53.73372, -26.6131], [-53.68269, -26.33359], [-53.64505, -26.28089], [-53.64186, -26.25976], [-53.64632, -26.24798], [-53.63881, -26.25075], [-53.63739, -26.2496], [-53.65237, -26.23289], [-53.65018, -26.19501], [-53.73968, -26.10012], [-53.73391, -26.07006], [-53.7264, -26.0664], [-53.73086, -26.05842], [-53.73511, -26.04211], [-53.83691, -25.94849], [-53.90831, -25.55513], [-54.52926, -25.62846], [-54.5502, -25.58915], [-54.59398, -25.59224], [-54.62063, -25.91213], [-54.60664, -25.9691], [-54.67359, -25.98607], [-54.69333, -26.37705], [-54.70732, -26.45099], [-54.80868, -26.55669], [-55.00584, -26.78754], [-55.06351, -26.80195], [-55.16948, -26.96068], [-55.25243, -26.93808], [-55.39611, -26.97679], [-55.62322, -27.1941], [-55.59094, -27.32444], [-55.74475, -27.44485], [-55.89195, -27.3467], [-56.18313, -27.29851], [-56.85337, -27.5165], [-58.04205, -27.2387], [-58.59549, -27.29973], [-58.65321, -27.14028], [-58.3198, -26.83443], [-58.1188, -26.16704], [-57.87176, -25.93604], [-57.57431, -25.47269], [-57.80821, -25.13863], [-58.25492, -24.92528], [-58.33055, -24.97099], [-59.33886, -24.49935], [-59.45482, -24.34787], [-60.03367, -24.00701], [-60.28163, -24.04436], [-60.99754, -23.80934], [-61.0782, -23.62932], [-61.9756, -23.0507], [-62.22768, -22.55807], [-62.51761, -22.37684], [-62.64455, -22.25091], [-62.8078, -22.12534], [-62.81124, -21.9987], [-63.66482, -21.99918], [-63.68113, -22.0544], [-63.70963, -21.99934], [-63.93287, -21.99934], [-64.22918, -22.55807], [-64.31489, -22.88824], [-64.35108, -22.73282], [-64.4176, -22.67692], [-64.58888, -22.25035], [-64.67174, -22.18957], [-64.90014, -22.12136], [-64.99524, -22.08255], [-65.47435, -22.08908], [-65.57743, -22.07675], [-65.58694, -22.09794], [-65.61166, -22.09504], [-65.7467, -22.10105], [-65.9261, -21.93335], [-66.04832, -21.9187], [-66.03836, -21.84829], [-66.24077, -21.77837], [-66.29714, -22.08741], [-66.7298, -22.23644], [-67.18382, -22.81525], [-66.99632, -22.99839], [-67.33563, -24.04237], [-68.24825, -24.42596], [-68.56909, -24.69831], [-68.38372, -25.08636], [-68.57622, -25.32505], [-68.38372, -26.15353], [-68.56909, -26.28146], [-68.59048, -26.49861], [-68.27677, -26.90626], [-68.43363, -27.08414], [-68.77586, -27.16029], [-69.22504, -27.95042], [-69.66709, -28.44055], [-69.80969, -29.07185], [-69.99507, -29.28351], [-69.8596, -30.26131], [-70.14479, -30.36595], [-70.55832, -31.51559], [-69.88099, -33.34489], [-69.87386, -34.13344], [-70.49416, -35.24145], [-70.38008, -36.02375], [-70.95047, -36.4321], [-71.24279, -37.20264], [-70.89532, -38.6923], [-71.37826, -38.91474], [-71.92726, -40.72714], [-71.74901, -42.11711], [-72.15541, -42.15941], [-72.14828, -42.85321], [-71.64206, -43.64774], [-71.81318, -44.38097], [-71.16436, -44.46244], [-71.26418, -44.75684], [-72.06985, -44.81756], [-71.35687, -45.22075], [-71.75614, -45.61611], [-71.68577, -46.55385], [-71.94152, -47.13595], [-72.50478, -47.80586], [-72.27662, -48.28727], [-72.54042, -48.52392], [-72.56894, -48.81116], [-73.09655, -49.14342], [-73.45156, -49.79461], [-73.55259, -49.92488], [-73.15765, -50.78337], [-72.31343, -50.58411]]]]
23777           }
23778         }, {
23779           type: "Feature",
23780           properties: {
23781             iso1A2: "AS",
23782             iso1A3: "ASM",
23783             iso1N3: "016",
23784             wikidata: "Q16641",
23785             nameEn: "American Samoa",
23786             aliases: ["US-AS"],
23787             country: "US",
23788             groups: ["Q1352230", "061", "009", "UN"],
23789             roadSpeedUnit: "mph",
23790             roadHeightUnit: "ft",
23791             callingCodes: ["1 684"]
23792           },
23793           geometry: {
23794             type: "MultiPolygon",
23795             coordinates: [[[[-171.39864, -10.21587], [-170.99605, -15.1275], [-166.32598, -15.26169], [-171.39864, -10.21587]]]]
23796           }
23797         }, {
23798           type: "Feature",
23799           properties: {
23800             iso1A2: "AT",
23801             iso1A3: "AUT",
23802             iso1N3: "040",
23803             wikidata: "Q40",
23804             nameEn: "Austria",
23805             groups: ["EU", "155", "150", "UN"],
23806             callingCodes: ["43"]
23807           },
23808           geometry: {
23809             type: "MultiPolygon",
23810             coordinates: [[[[15.34823, 48.98444], [15.28305, 48.98831], [15.26177, 48.95766], [15.16358, 48.94278], [15.15534, 48.99056], [14.99878, 49.01444], [14.97612, 48.96983], [14.98917, 48.90082], [14.95072, 48.79101], [14.98032, 48.77959], [14.9782, 48.7766], [14.98112, 48.77524], [14.9758, 48.76857], [14.95641, 48.75915], [14.94773, 48.76268], [14.81545, 48.7874], [14.80821, 48.77711], [14.80584, 48.73489], [14.72756, 48.69502], [14.71794, 48.59794], [14.66762, 48.58215], [14.60808, 48.62881], [14.56139, 48.60429], [14.4587, 48.64695], [14.43076, 48.58855], [14.33909, 48.55852], [14.20691, 48.5898], [14.09104, 48.5943], [14.01482, 48.63788], [14.06151, 48.66873], [13.84023, 48.76988], [13.82266, 48.75544], [13.81863, 48.73257], [13.79337, 48.71375], [13.81791, 48.69832], [13.81283, 48.68426], [13.81901, 48.6761], [13.82609, 48.62345], [13.80038, 48.59487], [13.80519, 48.58026], [13.76921, 48.55324], [13.7513, 48.5624], [13.74816, 48.53058], [13.72802, 48.51208], [13.66113, 48.53558], [13.65186, 48.55092], [13.62508, 48.55501], [13.59705, 48.57013], [13.57535, 48.55912], [13.51291, 48.59023], [13.50131, 48.58091], [13.50663, 48.57506], [13.46967, 48.55157], [13.45214, 48.56472], [13.43695, 48.55776], [13.45727, 48.51092], [13.42527, 48.45711], [13.43929, 48.43386], [13.40709, 48.37292], [13.30897, 48.31575], [13.26039, 48.29422], [13.18093, 48.29577], [13.126, 48.27867], [13.0851, 48.27711], [13.02083, 48.25689], [12.95306, 48.20629], [12.87126, 48.20318], [12.84475, 48.16556], [12.836, 48.1647], [12.8362, 48.15876], [12.82673, 48.15245], [12.80676, 48.14979], [12.78595, 48.12445], [12.7617, 48.12796], [12.74973, 48.10885], [12.76141, 48.07373], [12.8549, 48.01122], [12.87476, 47.96195], [12.91683, 47.95647], [12.9211, 47.95135], [12.91985, 47.94069], [12.92668, 47.93879], [12.93419, 47.94063], [12.93642, 47.94436], [12.93886, 47.94046], [12.94163, 47.92927], [13.00588, 47.84374], [12.98543, 47.82896], [12.96311, 47.79957], [12.93202, 47.77302], [12.94371, 47.76281], [12.9353, 47.74788], [12.91711, 47.74026], [12.90274, 47.72513], [12.91333, 47.7178], [12.92969, 47.71094], [12.98578, 47.7078], [13.01382, 47.72116], [13.07692, 47.68814], [13.09562, 47.63304], [13.06407, 47.60075], [13.06641, 47.58577], [13.04537, 47.58183], [13.05355, 47.56291], [13.03252, 47.53373], [13.04537, 47.49426], [12.9998, 47.46267], [12.98344, 47.48716], [12.9624, 47.47452], [12.85256, 47.52741], [12.84672, 47.54556], [12.80699, 47.54477], [12.77427, 47.58025], [12.82101, 47.61493], [12.76492, 47.64485], [12.77777, 47.66689], [12.7357, 47.6787], [12.6071, 47.6741], [12.57438, 47.63238], [12.53816, 47.63553], [12.50076, 47.62293], [12.44117, 47.6741], [12.43883, 47.6977], [12.37222, 47.68433], [12.336, 47.69534], [12.27991, 47.68827], [12.26004, 47.67725], [12.24017, 47.69534], [12.26238, 47.73544], [12.2542, 47.7433], [12.22571, 47.71776], [12.18303, 47.70065], [12.16217, 47.70105], [12.16769, 47.68167], [12.18347, 47.66663], [12.18507, 47.65984], [12.19895, 47.64085], [12.20801, 47.61082], [12.20398, 47.60667], [12.18568, 47.6049], [12.17737, 47.60121], [12.18145, 47.61019], [12.17824, 47.61506], [12.13734, 47.60639], [12.05788, 47.61742], [12.02282, 47.61033], [12.0088, 47.62451], [11.85572, 47.60166], [11.84052, 47.58354], [11.63934, 47.59202], [11.60681, 47.57881], [11.58811, 47.55515], [11.58578, 47.52281], [11.52618, 47.50939], [11.4362, 47.51413], [11.38128, 47.47465], [11.4175, 47.44621], [11.33804, 47.44937], [11.29597, 47.42566], [11.27844, 47.39956], [11.22002, 47.3964], [11.25157, 47.43277], [11.20482, 47.43198], [11.12536, 47.41222], [11.11835, 47.39719], [10.97111, 47.39561], [10.97111, 47.41617], [10.98513, 47.42882], [10.92437, 47.46991], [10.93839, 47.48018], [10.90918, 47.48571], [10.87061, 47.4786], [10.86945, 47.5015], [10.91268, 47.51334], [10.88814, 47.53701], [10.77596, 47.51729], [10.7596, 47.53228], [10.6965, 47.54253], [10.68832, 47.55752], [10.63456, 47.5591], [10.60337, 47.56755], [10.56912, 47.53584], [10.48849, 47.54057], [10.47329, 47.58552], [10.43473, 47.58394], [10.44992, 47.5524], [10.4324, 47.50111], [10.44291, 47.48453], [10.46278, 47.47901], [10.47446, 47.43318], [10.4359, 47.41183], [10.4324, 47.38494], [10.39851, 47.37623], [10.33424, 47.30813], [10.23257, 47.27088], [10.17531, 47.27167], [10.17648, 47.29149], [10.2147, 47.31014], [10.19998, 47.32832], [10.23757, 47.37609], [10.22774, 47.38904], [10.2127, 47.38019], [10.17648, 47.38889], [10.16362, 47.36674], [10.11805, 47.37228], [10.09819, 47.35724], [10.06897, 47.40709], [10.1052, 47.4316], [10.09001, 47.46005], [10.07131, 47.45531], [10.03859, 47.48927], [10.00003, 47.48216], [9.96029, 47.53899], [9.92407, 47.53111], [9.87733, 47.54688], [9.87499, 47.52953], [9.8189, 47.54688], [9.82591, 47.58158], [9.80254, 47.59419], [9.76748, 47.5934], [9.72736, 47.53457], [9.55125, 47.53629], [9.56312, 47.49495], [9.58208, 47.48344], [9.59482, 47.46305], [9.60205, 47.46165], [9.60484, 47.46358], [9.60841, 47.47178], [9.62158, 47.45858], [9.62475, 47.45685], [9.6423, 47.45599], [9.65728, 47.45383], [9.65863, 47.44847], [9.64483, 47.43842], [9.6446, 47.43233], [9.65043, 47.41937], [9.65136, 47.40504], [9.6629, 47.39591], [9.67334, 47.39191], [9.67445, 47.38429], [9.6711, 47.37824], [9.66243, 47.37136], [9.65427, 47.36824], [9.62476, 47.36639], [9.59978, 47.34671], [9.58513, 47.31334], [9.55857, 47.29919], [9.54773, 47.2809], [9.53116, 47.27029], [9.56766, 47.24281], [9.55176, 47.22585], [9.56981, 47.21926], [9.58264, 47.20673], [9.56539, 47.17124], [9.62623, 47.14685], [9.63395, 47.08443], [9.61216, 47.07732], [9.60717, 47.06091], [9.87935, 47.01337], [9.88266, 46.93343], [9.98058, 46.91434], [10.10715, 46.84296], [10.22675, 46.86942], [10.24128, 46.93147], [10.30031, 46.92093], [10.36933, 47.00212], [10.48376, 46.93891], [10.47197, 46.85698], [10.54783, 46.84505], [10.66405, 46.87614], [10.75753, 46.82258], [10.72974, 46.78972], [11.00764, 46.76896], [11.10618, 46.92966], [11.33355, 46.99862], [11.50739, 47.00644], [11.74789, 46.98484], [12.19254, 47.09331], [12.21781, 47.03996], [12.11675, 47.01241], [12.2006, 46.88854], [12.27591, 46.88651], [12.38708, 46.71529], [12.59992, 46.6595], [12.94445, 46.60401], [13.27627, 46.56059], [13.64088, 46.53438], [13.7148, 46.5222], [13.89837, 46.52331], [14.00422, 46.48474], [14.04002, 46.49117], [14.12097, 46.47724], [14.15989, 46.43327], [14.28326, 46.44315], [14.314, 46.43327], [14.42608, 46.44614], [14.45877, 46.41717], [14.52176, 46.42617], [14.56463, 46.37208], [14.5942, 46.43434], [14.66892, 46.44936], [14.72185, 46.49974], [14.81836, 46.51046], [14.83549, 46.56614], [14.86419, 46.59411], [14.87129, 46.61], [14.92283, 46.60848], [14.96002, 46.63459], [14.98024, 46.6009], [15.01451, 46.641], [15.14215, 46.66131], [15.23711, 46.63994], [15.41235, 46.65556], [15.45514, 46.63697], [15.46906, 46.61321], [15.54431, 46.6312], [15.55333, 46.64988], [15.54533, 46.66985], [15.59826, 46.68908], [15.62317, 46.67947], [15.63255, 46.68069], [15.6365, 46.6894], [15.6543, 46.69228], [15.6543, 46.70616], [15.67411, 46.70735], [15.69523, 46.69823], [15.72279, 46.69548], [15.73823, 46.70011], [15.76771, 46.69863], [15.78518, 46.70712], [15.8162, 46.71897], [15.87691, 46.7211], [15.94864, 46.68769], [15.98512, 46.68463], [15.99988, 46.67947], [16.04036, 46.6549], [16.04347, 46.68694], [16.02808, 46.71094], [15.99769, 46.7266], [15.98432, 46.74991], [15.99126, 46.78199], [15.99054, 46.82772], [16.05786, 46.83927], [16.10983, 46.867], [16.19904, 46.94134], [16.22403, 46.939], [16.27594, 46.9643], [16.28202, 47.00159], [16.51369, 47.00084], [16.43936, 47.03548], [16.52176, 47.05747], [16.46134, 47.09395], [16.52863, 47.13974], [16.44932, 47.14418], [16.46442, 47.16845], [16.4523, 47.18812], [16.42801, 47.18422], [16.41739, 47.20649], [16.43663, 47.21127], [16.44142, 47.25079], [16.47782, 47.25918], [16.45104, 47.41181], [16.49908, 47.39416], [16.52414, 47.41007], [16.57152, 47.40868], [16.6718, 47.46139], [16.64821, 47.50155], [16.71059, 47.52692], [16.64193, 47.63114], [16.58699, 47.61772], [16.4222, 47.66537], [16.55129, 47.72268], [16.53514, 47.73837], [16.54779, 47.75074], [16.61183, 47.76171], [16.65679, 47.74197], [16.72089, 47.73469], [16.7511, 47.67878], [16.82938, 47.68432], [16.86509, 47.72268], [16.87538, 47.68895], [17.08893, 47.70928], [17.05048, 47.79377], [17.07039, 47.81129], [17.00997, 47.86245], [17.08275, 47.87719], [17.11022, 47.92461], [17.09786, 47.97336], [17.16001, 48.00636], [17.07039, 48.0317], [17.09168, 48.09366], [17.05735, 48.14179], [17.02919, 48.13996], [16.97701, 48.17385], [16.89461, 48.31332], [16.90903, 48.32519], [16.84243, 48.35258], [16.83317, 48.38138], [16.83588, 48.3844], [16.8497, 48.38321], [16.85204, 48.44968], [16.94611, 48.53614], [16.93955, 48.60371], [16.90354, 48.71541], [16.79779, 48.70998], [16.71883, 48.73806], [16.68518, 48.7281], [16.67008, 48.77699], [16.46134, 48.80865], [16.40915, 48.74576], [16.37345, 48.729], [16.06034, 48.75436], [15.84404, 48.86921], [15.78087, 48.87644], [15.75341, 48.8516], [15.6921, 48.85973], [15.61622, 48.89541], [15.51357, 48.91549], [15.48027, 48.94481], [15.34823, 48.98444]]]]
23811           }
23812         }, {
23813           type: "Feature",
23814           properties: {
23815             iso1A2: "AU",
23816             iso1A3: "AUS",
23817             iso1N3: "036",
23818             wikidata: "Q408",
23819             nameEn: "Australia"
23820           },
23821           geometry: null
23822         }, {
23823           type: "Feature",
23824           properties: {
23825             iso1A2: "AW",
23826             iso1A3: "ABW",
23827             iso1N3: "533",
23828             wikidata: "Q21203",
23829             nameEn: "Aruba",
23830             aliases: ["NL-AW"],
23831             country: "NL",
23832             groups: ["Q1451600", "029", "003", "419", "019", "UN"],
23833             callingCodes: ["297"]
23834           },
23835           geometry: {
23836             type: "MultiPolygon",
23837             coordinates: [[[[-70.00823, 12.98375], [-70.35625, 12.58277], [-69.60231, 12.17], [-70.00823, 12.98375]]]]
23838           }
23839         }, {
23840           type: "Feature",
23841           properties: {
23842             iso1A2: "AX",
23843             iso1A3: "ALA",
23844             iso1N3: "248",
23845             wikidata: "Q5689",
23846             nameEn: "\xC5land Islands",
23847             country: "FI",
23848             groups: ["EU", "154", "150", "UN"],
23849             callingCodes: ["358 18", "358 457"]
23850           },
23851           geometry: {
23852             type: "MultiPolygon",
23853             coordinates: [[[[19.08191, 60.19152], [20.5104, 59.15546], [21.35468, 59.67511], [21.02509, 60.12142], [21.08159, 60.20167], [21.15143, 60.54555], [20.96741, 60.71528], [19.23413, 60.61414], [19.08191, 60.19152]]]]
23854           }
23855         }, {
23856           type: "Feature",
23857           properties: {
23858             iso1A2: "AZ",
23859             iso1A3: "AZE",
23860             iso1N3: "031",
23861             wikidata: "Q227",
23862             nameEn: "Azerbaijan",
23863             groups: ["145", "142", "UN"],
23864             callingCodes: ["994"]
23865           },
23866           geometry: {
23867             type: "MultiPolygon",
23868             coordinates: [[[[46.42738, 41.91323], [46.3984, 41.84399], [46.30863, 41.79133], [46.23962, 41.75811], [46.20538, 41.77205], [46.17891, 41.72094], [46.19759, 41.62327], [46.24429, 41.59883], [46.26531, 41.63339], [46.28182, 41.60089], [46.3253, 41.60912], [46.34039, 41.5947], [46.34126, 41.57454], [46.29794, 41.5724], [46.33925, 41.4963], [46.40307, 41.48464], [46.4669, 41.43331], [46.63658, 41.37727], [46.72375, 41.28609], [46.66148, 41.20533], [46.63969, 41.09515], [46.55096, 41.1104], [46.48558, 41.0576], [46.456, 41.09984], [46.37661, 41.10805], [46.27698, 41.19011], [46.13221, 41.19479], [45.95786, 41.17956], [45.80842, 41.2229], [45.69946, 41.29545], [45.75705, 41.35157], [45.71035, 41.36208], [45.68389, 41.3539], [45.45973, 41.45898], [45.4006, 41.42402], [45.31352, 41.47168], [45.26285, 41.46433], [45.1797, 41.42231], [45.09867, 41.34065], [45.0133, 41.29747], [45.05497, 41.2464], [45.02932, 41.2101], [45.05201, 41.19211], [45.11811, 41.19967], [45.1969, 41.168], [45.19942, 41.13299], [45.08028, 41.10917], [45.06784, 41.05379], [45.12923, 41.06059], [45.1313, 41.09369], [45.1634, 41.08082], [45.16493, 41.05068], [45.1994, 41.04518], [45.25897, 41.0027], [45.26162, 41.0228], [45.28859, 41.03757], [45.35677, 40.99784], [45.39725, 41.02603], [45.44083, 41.01663], [45.40814, 40.97904], [45.60584, 40.87436], [45.55914, 40.78366], [45.4206, 40.7424], [45.35366, 40.65979], [45.45484, 40.57707], [45.42994, 40.53804], [45.65098, 40.37696], [45.95609, 40.27846], [45.97944, 40.181], [45.83779, 39.98925], [45.78642, 40.03218], [45.59806, 40.0131], [45.60895, 39.97733], [45.7833, 39.9475], [45.82533, 39.82925], [45.96543, 39.78859], [46.18493, 39.60533], [46.40286, 39.63651], [46.42465, 39.57534], [46.52117, 39.58734], [46.57098, 39.56694], [46.57721, 39.54414], [46.51027, 39.52373], [46.53051, 39.47809], [46.4013, 39.45405], [46.37795, 39.42039], [46.43244, 39.35181], [46.50093, 39.33736], [46.56476, 39.24942], [46.63481, 39.23013], [46.58032, 39.21204], [46.54141, 39.15895], [46.52584, 39.18912], [46.44022, 39.19636], [46.54296, 39.07078], [46.51805, 38.94982], [46.53497, 38.86548], [46.75752, 39.03231], [46.83822, 39.13143], [46.92539, 39.16644], [46.95341, 39.13505], [47.05771, 39.20143], [47.05927, 39.24846], [47.31301, 39.37492], [47.38978, 39.45999], [47.50099, 39.49615], [47.84774, 39.66285], [47.98977, 39.70999], [48.34264, 39.42935], [48.37385, 39.37584], [48.15984, 39.30028], [48.12404, 39.25208], [48.15361, 39.19419], [48.31239, 39.09278], [48.33884, 39.03022], [48.28437, 38.97186], [48.08627, 38.94434], [48.07734, 38.91616], [48.01409, 38.90333], [48.02581, 38.82705], [48.24773, 38.71883], [48.3146, 38.59958], [48.45084, 38.61013], [48.58793, 38.45076], [48.62217, 38.40198], [48.70001, 38.40564], [48.78979, 38.45026], [48.81072, 38.44853], [48.84969, 38.45015], [48.88288, 38.43975], [52.39847, 39.43556], [48.80971, 41.95365], [48.5867, 41.84306], [48.55078, 41.77917], [48.42301, 41.65444], [48.40277, 41.60441], [48.2878, 41.56221], [48.22064, 41.51472], [48.07587, 41.49957], [47.87973, 41.21798], [47.75831, 41.19455], [47.62288, 41.22969], [47.54504, 41.20275], [47.49004, 41.26366], [47.34579, 41.27884], [47.10762, 41.59044], [47.03757, 41.55434], [46.99554, 41.59743], [47.00955, 41.63583], [46.8134, 41.76252], [46.75269, 41.8623], [46.58924, 41.80547], [46.5332, 41.87389], [46.42738, 41.91323]], [[45.50279, 40.58424], [45.47927, 40.65023], [45.51825, 40.67382], [45.56071, 40.64765], [45.50279, 40.58424]]], [[[45.00864, 41.03411], [45.03792, 41.03938], [45.04517, 41.06653], [45.03406, 41.07931], [45.00864, 41.09407], [44.97169, 41.09176], [44.95383, 41.07553], [44.96031, 41.06345], [44.9903, 41.05657], [45.00864, 41.03411]]], [[[45.21324, 40.9817], [45.23095, 40.97828], [45.23487, 41.00226], [45.20625, 41.01484], [45.18382, 41.0066], [45.19312, 40.98998], [45.20518, 40.99348], [45.21219, 40.99001], [45.21324, 40.9817]]], [[[45.46992, 39.49888], [45.29606, 39.57654], [45.30385, 39.61373], [45.23535, 39.61373], [45.21784, 39.58074], [45.17464, 39.58614], [45.18554, 39.67846], [45.06604, 39.79277], [44.92869, 39.72157], [44.88354, 39.74432], [44.75779, 39.7148], [44.80977, 39.65768], [44.81043, 39.62677], [44.88916, 39.59653], [44.96746, 39.42998], [45.05932, 39.36435], [45.08751, 39.35052], [45.16168, 39.21952], [45.30489, 39.18333], [45.40148, 39.09007], [45.40452, 39.07224], [45.44811, 39.04927], [45.44966, 38.99243], [45.6131, 38.964], [45.6155, 38.94304], [45.65172, 38.95199], [45.83883, 38.90768], [45.90266, 38.87739], [45.94624, 38.89072], [46.00228, 38.87376], [46.06766, 38.87861], [46.14785, 38.84206], [46.06973, 39.0744], [46.02303, 39.09978], [45.99774, 39.28931], [45.79225, 39.3695], [45.83, 39.46487], [45.80804, 39.56716], [45.70547, 39.60174], [45.46992, 39.49888]]]]
23869           }
23870         }, {
23871           type: "Feature",
23872           properties: {
23873             iso1A2: "BA",
23874             iso1A3: "BIH",
23875             iso1N3: "070",
23876             wikidata: "Q225",
23877             nameEn: "Bosnia and Herzegovina",
23878             groups: ["039", "150", "UN"],
23879             callingCodes: ["387"]
23880           },
23881           geometry: {
23882             type: "MultiPolygon",
23883             coordinates: [[[[17.84826, 45.04489], [17.66571, 45.13408], [17.59104, 45.10816], [17.51469, 45.10791], [17.47589, 45.12656], [17.45615, 45.12523], [17.4498, 45.16119], [17.41229, 45.13335], [17.33573, 45.14521], [17.32092, 45.16246], [17.26815, 45.18444], [17.25131, 45.14957], [17.24325, 45.146], [17.18438, 45.14764], [17.0415, 45.20759], [16.9385, 45.22742], [16.92405, 45.27607], [16.83804, 45.18951], [16.81137, 45.18434], [16.78219, 45.19002], [16.74845, 45.20393], [16.64962, 45.20714], [16.60194, 45.23042], [16.56559, 45.22307], [16.5501, 45.2212], [16.52982, 45.22713], [16.49155, 45.21153], [16.4634, 45.14522], [16.40023, 45.1147], [16.38309, 45.05955], [16.38219, 45.05139], [16.3749, 45.05206], [16.35863, 45.03529], [16.35404, 45.00241], [16.29036, 44.99732], [16.12153, 45.09616], [15.98412, 45.23088], [15.83512, 45.22459], [15.76371, 45.16508], [15.78842, 45.11519], [15.74585, 45.0638], [15.78568, 44.97401], [15.74723, 44.96818], [15.76096, 44.87045], [15.79472, 44.8455], [15.72584, 44.82334], [15.8255, 44.71501], [15.89348, 44.74964], [16.05828, 44.61538], [16.00884, 44.58605], [16.03012, 44.55572], [16.10566, 44.52586], [16.16814, 44.40679], [16.12969, 44.38275], [16.21346, 44.35231], [16.18688, 44.27012], [16.36864, 44.08263], [16.43662, 44.07523], [16.43629, 44.02826], [16.50528, 44.0244], [16.55472, 43.95326], [16.70922, 43.84887], [16.75316, 43.77157], [16.80736, 43.76011], [17.00585, 43.58037], [17.15828, 43.49376], [17.24411, 43.49376], [17.29699, 43.44542], [17.25579, 43.40353], [17.286, 43.33065], [17.46986, 43.16559], [17.64268, 43.08595], [17.70879, 42.97223], [17.5392, 42.92787], [17.6444, 42.88641], [17.68151, 42.92725], [17.7948, 42.89556], [17.80854, 42.9182], [17.88201, 42.83668], [18.24318, 42.6112], [18.36197, 42.61423], [18.43735, 42.55921], [18.49778, 42.58409], [18.53751, 42.57376], [18.55504, 42.58409], [18.52232, 42.62279], [18.57373, 42.64429], [18.54841, 42.68328], [18.54603, 42.69171], [18.55221, 42.69045], [18.56789, 42.72074], [18.47324, 42.74992], [18.45921, 42.81682], [18.47633, 42.85829], [18.4935, 42.86433], [18.49661, 42.89306], [18.49076, 42.95553], [18.52232, 43.01451], [18.66254, 43.03928], [18.64735, 43.14766], [18.66605, 43.2056], [18.71747, 43.2286], [18.6976, 43.25243], [18.76538, 43.29838], [18.85342, 43.32426], [18.84794, 43.33735], [18.83912, 43.34795], [18.90911, 43.36383], [18.95819, 43.32899], [18.95001, 43.29327], [19.00844, 43.24988], [19.04233, 43.30008], [19.08206, 43.29668], [19.08673, 43.31453], [19.04071, 43.397], [19.01078, 43.43854], [18.96053, 43.45042], [18.95469, 43.49367], [18.91379, 43.50299], [19.01078, 43.55806], [19.04934, 43.50384], [19.13933, 43.5282], [19.15685, 43.53943], [19.22807, 43.5264], [19.24774, 43.53061], [19.2553, 43.5938], [19.33426, 43.58833], [19.36653, 43.60921], [19.41941, 43.54056], [19.42696, 43.57987], [19.50455, 43.58385], [19.5176, 43.71403], [19.3986, 43.79668], [19.23465, 43.98764], [19.24363, 44.01502], [19.38439, 43.96611], [19.52515, 43.95573], [19.56498, 43.99922], [19.61836, 44.01464], [19.61991, 44.05254], [19.57467, 44.04716], [19.55999, 44.06894], [19.51167, 44.08158], [19.47321, 44.1193], [19.48386, 44.14332], [19.47338, 44.15034], [19.43905, 44.13088], [19.40927, 44.16722], [19.3588, 44.18353], [19.34773, 44.23244], [19.32464, 44.27185], [19.26945, 44.26957], [19.23306, 44.26097], [19.20508, 44.2917], [19.18328, 44.28383], [19.16741, 44.28648], [19.13332, 44.31492], [19.13556, 44.338], [19.11547, 44.34218], [19.1083, 44.3558], [19.11865, 44.36712], [19.10298, 44.36924], [19.10365, 44.37795], [19.10704, 44.38249], [19.10749, 44.39421], [19.11785, 44.40313], [19.14681, 44.41463], [19.14837, 44.45253], [19.12278, 44.50132], [19.13369, 44.52521], [19.16699, 44.52197], [19.26388, 44.65412], [19.32543, 44.74058], [19.36722, 44.88164], [19.18183, 44.92055], [19.01994, 44.85493], [18.8704, 44.85097], [18.76347, 44.90669], [18.76369, 44.93707], [18.80661, 44.93561], [18.78357, 44.97741], [18.65723, 45.07544], [18.47939, 45.05871], [18.41896, 45.11083], [18.32077, 45.1021], [18.24387, 45.13699], [18.1624, 45.07654], [18.03121, 45.12632], [18.01594, 45.15163], [17.99479, 45.14958], [17.97834, 45.13831], [17.97336, 45.12245], [17.93706, 45.08016], [17.87148, 45.04645], [17.84826, 45.04489]]]]
23884           }
23885         }, {
23886           type: "Feature",
23887           properties: {
23888             iso1A2: "BB",
23889             iso1A3: "BRB",
23890             iso1N3: "052",
23891             wikidata: "Q244",
23892             nameEn: "Barbados",
23893             groups: ["029", "003", "419", "019", "UN"],
23894             driveSide: "left",
23895             callingCodes: ["1 246"]
23896           },
23897           geometry: {
23898             type: "MultiPolygon",
23899             coordinates: [[[[-58.56442, 13.24471], [-59.80731, 13.87556], [-59.82929, 12.70644], [-58.56442, 13.24471]]]]
23900           }
23901         }, {
23902           type: "Feature",
23903           properties: {
23904             iso1A2: "BD",
23905             iso1A3: "BGD",
23906             iso1N3: "050",
23907             wikidata: "Q902",
23908             nameEn: "Bangladesh",
23909             groups: ["034", "142", "UN"],
23910             driveSide: "left",
23911             callingCodes: ["880"]
23912           },
23913           geometry: {
23914             type: "MultiPolygon",
23915             coordinates: [[[[89.15869, 26.13708], [89.08899, 26.38845], [88.95612, 26.4564], [88.92357, 26.40711], [88.91321, 26.37984], [89.05328, 26.2469], [88.85004, 26.23211], [88.78961, 26.31093], [88.67837, 26.26291], [88.69485, 26.38353], [88.62144, 26.46783], [88.4298, 26.54489], [88.41196, 26.63837], [88.33093, 26.48929], [88.35153, 26.45241], [88.36938, 26.48683], [88.48749, 26.45855], [88.51649, 26.35923], [88.35153, 26.29123], [88.34757, 26.22216], [88.1844, 26.14417], [88.16581, 26.0238], [88.08804, 25.91334], [88.13138, 25.78773], [88.242, 25.80811], [88.45103, 25.66245], [88.4559, 25.59227], [88.677, 25.46959], [88.81296, 25.51546], [88.85278, 25.34679], [89.01105, 25.30303], [89.00463, 25.26583], [88.94067, 25.18534], [88.44766, 25.20149], [88.46277, 25.07468], [88.33917, 24.86803], [88.27325, 24.88796], [88.21832, 24.96642], [88.14004, 24.93529], [88.15515, 24.85806], [88.00683, 24.66477], [88.08786, 24.63232], [88.12296, 24.51301], [88.50934, 24.32474], [88.68801, 24.31464], [88.74841, 24.1959], [88.6976, 24.14703], [88.73743, 23.91751], [88.66189, 23.87607], [88.58087, 23.87105], [88.56507, 23.64044], [88.74841, 23.47361], [88.79351, 23.50535], [88.79254, 23.46028], [88.71133, 23.2492], [88.99148, 23.21134], [88.86377, 23.08759], [88.88327, 23.03885], [88.87063, 22.95235], [88.96713, 22.83346], [88.9151, 22.75228], [88.94614, 22.66941], [88.9367, 22.58527], [89.07114, 22.15335], [89.08044, 21.41871], [92.47409, 20.38654], [92.26071, 21.05697], [92.17752, 21.17445], [92.20087, 21.337], [92.37939, 21.47764], [92.43158, 21.37025], [92.55105, 21.3856], [92.60187, 21.24615], [92.68152, 21.28454], [92.59775, 21.6092], [92.62187, 21.87037], [92.60949, 21.97638], [92.56616, 22.13554], [92.60029, 22.1522], [92.5181, 22.71441], [92.37665, 22.9435], [92.38214, 23.28705], [92.26541, 23.70392], [92.15417, 23.73409], [92.04706, 23.64229], [91.95093, 23.73284], [91.95642, 23.47361], [91.84789, 23.42235], [91.76417, 23.26619], [91.81634, 23.08001], [91.7324, 23.00043], [91.61571, 22.93929], [91.54993, 23.01051], [91.46615, 23.2328], [91.4035, 23.27522], [91.40848, 23.07117], [91.36453, 23.06612], [91.28293, 23.37538], [91.15579, 23.6599], [91.25192, 23.83463], [91.22308, 23.89616], [91.29587, 24.0041], [91.35741, 23.99072], [91.37414, 24.10693], [91.55542, 24.08687], [91.63782, 24.1132], [91.65292, 24.22095], [91.73257, 24.14703], [91.76004, 24.23848], [91.82596, 24.22345], [91.89258, 24.14674], [91.96603, 24.3799], [92.11662, 24.38997], [92.15796, 24.54435], [92.25854, 24.9191], [92.38626, 24.86055], [92.49887, 24.88796], [92.39147, 25.01471], [92.33957, 25.07593], [92.0316, 25.1834], [91.63648, 25.12846], [91.25517, 25.20677], [90.87427, 25.15799], [90.65042, 25.17788], [90.40034, 25.1534], [90.1155, 25.22686], [89.90478, 25.31038], [89.87629, 25.28337], [89.83371, 25.29548], [89.84086, 25.31854], [89.81208, 25.37244], [89.86129, 25.61714], [89.84388, 25.70042], [89.80585, 25.82489], [89.86592, 25.93115], [89.77728, 26.04254], [89.77865, 26.08387], [89.73581, 26.15818], [89.70201, 26.15138], [89.63968, 26.22595], [89.57101, 25.9682], [89.53515, 26.00382], [89.35953, 26.0077], [89.15869, 26.13708]]]]
23916           }
23917         }, {
23918           type: "Feature",
23919           properties: {
23920             iso1A2: "BE",
23921             iso1A3: "BEL",
23922             iso1N3: "056",
23923             wikidata: "Q31",
23924             nameEn: "Belgium",
23925             groups: ["EU", "155", "150", "UN"],
23926             callingCodes: ["32"]
23927           },
23928           geometry: {
23929             type: "MultiPolygon",
23930             coordinates: [[[[4.93295, 51.44945], [4.93909, 51.44632], [4.9524, 51.45014], [4.95244, 51.45207], [4.93295, 51.44945]]], [[[4.91493, 51.4353], [4.92652, 51.43329], [4.92952, 51.42984], [4.93986, 51.43064], [4.94265, 51.44003], [4.93471, 51.43861], [4.93416, 51.44185], [4.94025, 51.44193], [4.93544, 51.44634], [4.92879, 51.44161], [4.92815, 51.43856], [4.92566, 51.44273], [4.92811, 51.4437], [4.92287, 51.44741], [4.91811, 51.44621], [4.92227, 51.44252], [4.91935, 51.43634], [4.91493, 51.4353]]], [[[4.82946, 51.4213], [4.82409, 51.44736], [4.84139, 51.4799], [4.78803, 51.50284], [4.77321, 51.50529], [4.74578, 51.48937], [4.72935, 51.48424], [4.65442, 51.42352], [4.57489, 51.4324], [4.53521, 51.4243], [4.52846, 51.45002], [4.54675, 51.47265], [4.5388, 51.48184], [4.47736, 51.4778], [4.38122, 51.44905], [4.39747, 51.43316], [4.38064, 51.41965], [4.43777, 51.36989], [4.39292, 51.35547], [4.34086, 51.35738], [4.33265, 51.37687], [4.21923, 51.37443], [4.24024, 51.35371], [4.16721, 51.29348], [4.05165, 51.24171], [4.01957, 51.24504], [3.97889, 51.22537], [3.90125, 51.20371], [3.78783, 51.2151], [3.78999, 51.25766], [3.58939, 51.30064], [3.51502, 51.28697], [3.52698, 51.2458], [3.43488, 51.24135], [3.41704, 51.25933], [3.38289, 51.27331], [3.35847, 51.31572], [3.38696, 51.33436], [3.36263, 51.37112], [2.56575, 51.85301], [2.18458, 51.52087], [2.55904, 51.07014], [2.57551, 51.00326], [2.63074, 50.94746], [2.59093, 50.91751], [2.63331, 50.81457], [2.71165, 50.81295], [2.81056, 50.71773], [2.8483, 50.72276], [2.86985, 50.7033], [2.87937, 50.70298], [2.88504, 50.70656], [2.90069, 50.69263], [2.91036, 50.6939], [2.90873, 50.702], [2.95019, 50.75138], [2.96778, 50.75242], [3.00537, 50.76588], [3.04314, 50.77674], [3.09163, 50.77717], [3.10614, 50.78303], [3.11206, 50.79416], [3.11987, 50.79188], [3.1257, 50.78603], [3.15017, 50.79031], [3.16476, 50.76843], [3.18339, 50.74981], [3.18811, 50.74025], [3.20064, 50.73547], [3.19017, 50.72569], [3.20845, 50.71662], [3.22042, 50.71019], [3.24593, 50.71389], [3.26063, 50.70086], [3.26141, 50.69151], [3.2536, 50.68977], [3.264, 50.67668], [3.23951, 50.6585], [3.2729, 50.60718], [3.28575, 50.52724], [3.37693, 50.49538], [3.44629, 50.51009], [3.47385, 50.53397], [3.51564, 50.5256], [3.49509, 50.48885], [3.5683, 50.50192], [3.58361, 50.49049], [3.61014, 50.49568], [3.64426, 50.46275], [3.66153, 50.45165], [3.67494, 50.40239], [3.67262, 50.38663], [3.65709, 50.36873], [3.66976, 50.34563], [3.71009, 50.30305], [3.70987, 50.3191], [3.73911, 50.34809], [3.84314, 50.35219], [3.90781, 50.32814], [3.96771, 50.34989], [4.0268, 50.35793], [4.0689, 50.3254], [4.10237, 50.31247], [4.10957, 50.30234], [4.11954, 50.30425], [4.13665, 50.25609], [4.16808, 50.25786], [4.15524, 50.2833], [4.17347, 50.28838], [4.17861, 50.27443], [4.20651, 50.27333], [4.21945, 50.25539], [4.15524, 50.21103], [4.16014, 50.19239], [4.13561, 50.13078], [4.20147, 50.13535], [4.23101, 50.06945], [4.16294, 50.04719], [4.13508, 50.01976], [4.14239, 49.98034], [4.20532, 49.95803], [4.31963, 49.97043], [4.35051, 49.95315], [4.43488, 49.94122], [4.51098, 49.94659], [4.5414, 49.96911], [4.68695, 49.99685], [4.70064, 50.09384], [4.75237, 50.11314], [4.82438, 50.16878], [4.83279, 50.15331], [4.88602, 50.15182], [4.8382, 50.06738], [4.78827, 49.95609], [4.88529, 49.9236], [4.85134, 49.86457], [4.86965, 49.82271], [4.85464, 49.78995], [4.96714, 49.79872], [5.09249, 49.76193], [5.14545, 49.70287], [5.26232, 49.69456], [5.31465, 49.66846], [5.33039, 49.6555], [5.30214, 49.63055], [5.3137, 49.61225], [5.33851, 49.61599], [5.34837, 49.62889], [5.3974, 49.61596], [5.43713, 49.5707], [5.46734, 49.52648], [5.46541, 49.49825], [5.55001, 49.52729], [5.60909, 49.51228], [5.64505, 49.55146], [5.75649, 49.54321], [5.7577, 49.55915], [5.77435, 49.56298], [5.79195, 49.55228], [5.81838, 49.54777], [5.84143, 49.5533], [5.84692, 49.55663], [5.8424, 49.56082], [5.87256, 49.57539], [5.86986, 49.58756], [5.84971, 49.58674], [5.84826, 49.5969], [5.8762, 49.60898], [5.87609, 49.62047], [5.88393, 49.62802], [5.88552, 49.63507], [5.90599, 49.63853], [5.90164, 49.6511], [5.9069, 49.66377], [5.86175, 49.67862], [5.86527, 49.69291], [5.88677, 49.70951], [5.86503, 49.72739], [5.84193, 49.72161], [5.82562, 49.72395], [5.83149, 49.74729], [5.82245, 49.75048], [5.78871, 49.7962], [5.75409, 49.79239], [5.74953, 49.81428], [5.74364, 49.82058], [5.74844, 49.82435], [5.7404, 49.83452], [5.74076, 49.83823], [5.74975, 49.83933], [5.74953, 49.84709], [5.75884, 49.84811], [5.74567, 49.85368], [5.75861, 49.85631], [5.75269, 49.8711], [5.78415, 49.87922], [5.73621, 49.89796], [5.77314, 49.93646], [5.77291, 49.96056], [5.80833, 49.96451], [5.81163, 49.97142], [5.83467, 49.97823], [5.83968, 49.9892], [5.82331, 49.99662], [5.81866, 50.01286], [5.8551, 50.02683], [5.86904, 50.04614], [5.85474, 50.06342], [5.8857, 50.07824], [5.89488, 50.11476], [5.95929, 50.13295], [5.96453, 50.17259], [6.02488, 50.18283], [6.03093, 50.16362], [6.06406, 50.15344], [6.08577, 50.17246], [6.12028, 50.16374], [6.1137, 50.13668], [6.1379, 50.12964], [6.15298, 50.14126], [6.14132, 50.14971], [6.14588, 50.17106], [6.18739, 50.1822], [6.18364, 50.20815], [6.16853, 50.2234], [6.208, 50.25179], [6.28797, 50.27458], [6.29949, 50.30887], [6.32488, 50.32333], [6.35701, 50.31139], [6.40641, 50.32425], [6.40785, 50.33557], [6.3688, 50.35898], [6.34406, 50.37994], [6.36852, 50.40776], [6.37219, 50.45397], [6.34005, 50.46083], [6.3465, 50.48833], [6.30809, 50.50058], [6.26637, 50.50272], [6.22335, 50.49578], [6.20599, 50.52089], [6.19193, 50.5212], [6.18716, 50.52653], [6.19579, 50.5313], [6.19735, 50.53576], [6.17802, 50.54179], [6.17739, 50.55875], [6.20281, 50.56952], [6.22581, 50.5907], [6.24005, 50.58732], [6.24888, 50.59869], [6.2476, 50.60392], [6.26957, 50.62444], [6.17852, 50.6245], [6.11707, 50.72231], [6.04428, 50.72861], [6.0406, 50.71848], [6.0326, 50.72647], [6.03889, 50.74618], [6.01976, 50.75398], [5.97545, 50.75441], [5.95942, 50.7622], [5.89132, 50.75124], [5.89129, 50.75125], [5.88734, 50.77092], [5.84888, 50.75448], [5.84548, 50.76542], [5.80673, 50.7558], [5.77513, 50.78308], [5.76533, 50.78159], [5.74356, 50.7691], [5.73904, 50.75674], [5.72216, 50.76398], [5.69469, 50.75529], [5.68091, 50.75804], [5.70107, 50.7827], [5.68995, 50.79641], [5.70118, 50.80764], [5.65259, 50.82309], [5.64009, 50.84742], [5.64504, 50.87107], [5.67886, 50.88142], [5.69858, 50.91046], [5.71626, 50.90796], [5.72644, 50.91167], [5.72545, 50.92312], [5.74644, 50.94723], [5.75927, 50.95601], [5.74752, 50.96202], [5.72875, 50.95428], [5.71864, 50.96092], [5.76242, 50.99703], [5.77688, 51.02483], [5.75961, 51.03113], [5.77258, 51.06196], [5.79835, 51.05834], [5.79903, 51.09371], [5.82921, 51.09328], [5.83226, 51.10585], [5.8109, 51.10861], [5.80798, 51.11661], [5.85508, 51.14445], [5.82564, 51.16753], [5.77697, 51.1522], [5.77735, 51.17845], [5.74617, 51.18928], [5.70344, 51.1829], [5.65528, 51.18736], [5.65145, 51.19788], [5.5603, 51.22249], [5.5569, 51.26544], [5.515, 51.29462], [5.48476, 51.30053], [5.46519, 51.2849], [5.4407, 51.28169], [5.41672, 51.26248], [5.347, 51.27502], [5.33886, 51.26314], [5.29716, 51.26104], [5.26461, 51.26693], [5.23814, 51.26064], [5.22542, 51.26888], [5.24244, 51.30495], [5.2002, 51.32243], [5.16222, 51.31035], [5.13377, 51.31592], [5.13105, 51.34791], [5.07102, 51.39469], [5.10456, 51.43163], [5.07891, 51.4715], [5.04774, 51.47022], [5.03281, 51.48679], [5.0106, 51.47167], [5.00393, 51.44406], [4.92152, 51.39487], [4.90016, 51.41404], [4.84988, 51.41502], [4.78941, 51.41102], [4.77229, 51.41337], [4.76577, 51.43046], [4.78314, 51.43319], [4.82946, 51.4213]]]]
23931           }
23932         }, {
23933           type: "Feature",
23934           properties: {
23935             iso1A2: "BF",
23936             iso1A3: "BFA",
23937             iso1N3: "854",
23938             wikidata: "Q965",
23939             nameEn: "Burkina Faso",
23940             groups: ["011", "202", "002", "UN"],
23941             callingCodes: ["226"]
23942           },
23943           geometry: {
23944             type: "MultiPolygon",
23945             coordinates: [[[[0.23859, 15.00135], [0.06588, 14.96961], [-0.24673, 15.07805], [-0.72004, 15.08655], [-1.05875, 14.7921], [-1.32166, 14.72774], [-1.68083, 14.50023], [-1.97945, 14.47709], [-1.9992, 14.19011], [-2.10223, 14.14878], [-2.47587, 14.29671], [-2.66175, 14.14713], [-2.84667, 14.05532], [-2.90831, 13.81174], [-2.88189, 13.64921], [-3.26407, 13.70699], [-3.28396, 13.5422], [-3.23599, 13.29035], [-3.43507, 13.27272], [-3.4313, 13.1588], [-3.54454, 13.1781], [-3.7911, 13.36665], [-3.96282, 13.38164], [-3.90558, 13.44375], [-3.96501, 13.49778], [-4.34477, 13.12927], [-4.21819, 12.95722], [-4.238, 12.71467], [-4.47356, 12.71252], [-4.41412, 12.31922], [-4.57703, 12.19875], [-4.54841, 12.1385], [-4.62546, 12.13204], [-4.62987, 12.06531], [-4.70692, 12.06746], [-4.72893, 12.01579], [-5.07897, 11.97918], [-5.26389, 11.84778], [-5.40258, 11.8327], [-5.26389, 11.75728], [-5.29251, 11.61715], [-5.22867, 11.60421], [-5.20665, 11.43811], [-5.25509, 11.36905], [-5.25949, 11.24816], [-5.32553, 11.21578], [-5.32994, 11.13371], [-5.49284, 11.07538], [-5.41579, 10.84628], [-5.47083, 10.75329], [-5.46643, 10.56074], [-5.51058, 10.43177], [-5.39602, 10.2929], [-5.12465, 10.29788], [-4.96453, 9.99923], [-4.96621, 9.89132], [-4.6426, 9.70696], [-4.31392, 9.60062], [-4.25999, 9.76012], [-3.69703, 9.94279], [-3.31779, 9.91125], [-3.27228, 9.84981], [-3.19306, 9.93781], [-3.16609, 9.85147], [-3.00765, 9.74019], [-2.93012, 9.57403], [-2.76494, 9.40778], [-2.68802, 9.49343], [-2.76534, 9.56589], [-2.74174, 9.83172], [-2.83108, 10.40252], [-2.94232, 10.64281], [-2.83373, 11.0067], [-0.67143, 10.99811], [-0.61937, 10.91305], [-0.44298, 11.04292], [-0.42391, 11.11661], [-0.38219, 11.12596], [-0.35955, 11.07801], [-0.28566, 11.12713], [-0.27374, 11.17157], [-0.13493, 11.14075], [0.50388, 11.01011], [0.48852, 10.98561], [0.50521, 10.98035], [0.4958, 10.93269], [0.66104, 10.99964], [0.91245, 10.99597], [0.9813, 11.08876], [1.03409, 11.04719], [1.42823, 11.46822], [2.00988, 11.42227], [2.29983, 11.68254], [2.39723, 11.89473], [2.05785, 12.35539], [2.26349, 12.41915], [0.99167, 13.10727], [0.99253, 13.37515], [1.18873, 13.31771], [1.21217, 13.37853], [1.24516, 13.33968], [1.28509, 13.35488], [1.24429, 13.39373], [1.20088, 13.38951], [1.02813, 13.46635], [0.99514, 13.5668], [0.77637, 13.64442], [0.77377, 13.6866], [0.61924, 13.68491], [0.38051, 14.05575], [0.16936, 14.51654], [0.23859, 15.00135]]]]
23946           }
23947         }, {
23948           type: "Feature",
23949           properties: {
23950             iso1A2: "BG",
23951             iso1A3: "BGR",
23952             iso1N3: "100",
23953             wikidata: "Q219",
23954             nameEn: "Bulgaria",
23955             groups: ["EU", "151", "150", "UN"],
23956             callingCodes: ["359"]
23957           },
23958           geometry: {
23959             type: "MultiPolygon",
23960             coordinates: [[[[23.05288, 43.79494], [22.85314, 43.84452], [22.83753, 43.88055], [22.87873, 43.9844], [23.01674, 44.01946], [23.04988, 44.07694], [22.67173, 44.21564], [22.61711, 44.16938], [22.61688, 44.06534], [22.41449, 44.00514], [22.35558, 43.81281], [22.41043, 43.69566], [22.47582, 43.6558], [22.53397, 43.47225], [22.82036, 43.33665], [22.89727, 43.22417], [23.00806, 43.19279], [22.98104, 43.11199], [22.89521, 43.03625], [22.78397, 42.98253], [22.74826, 42.88701], [22.54302, 42.87774], [22.43309, 42.82057], [22.4997, 42.74144], [22.43983, 42.56851], [22.55669, 42.50144], [22.51961, 42.3991], [22.47498, 42.3915], [22.45919, 42.33822], [22.34773, 42.31725], [22.38136, 42.30339], [22.47251, 42.20393], [22.50289, 42.19527], [22.51224, 42.15457], [22.67701, 42.06614], [22.86749, 42.02275], [22.90254, 41.87587], [22.96682, 41.77137], [23.01239, 41.76527], [23.03342, 41.71034], [22.95513, 41.63265], [22.96331, 41.35782], [22.93334, 41.34104], [23.1833, 41.31755], [23.21953, 41.33773], [23.22771, 41.37106], [23.31301, 41.40525], [23.33639, 41.36317], [23.40416, 41.39999], [23.52453, 41.40262], [23.63203, 41.37632], [23.67644, 41.41139], [23.76525, 41.40175], [23.80148, 41.43943], [23.89613, 41.45257], [23.91483, 41.47971], [23.96975, 41.44118], [24.06908, 41.46132], [24.06323, 41.53222], [24.10063, 41.54796], [24.18126, 41.51735], [24.27124, 41.57682], [24.30513, 41.51297], [24.52599, 41.56808], [24.61129, 41.42278], [24.71529, 41.41928], [24.8041, 41.34913], [24.82514, 41.4035], [24.86136, 41.39298], [24.90928, 41.40876], [24.942, 41.38685], [25.11611, 41.34212], [25.28322, 41.23411], [25.48187, 41.28506], [25.52394, 41.2798], [25.55082, 41.31667], [25.61042, 41.30614], [25.66183, 41.31316], [25.70507, 41.29209], [25.8266, 41.34563], [25.87919, 41.30526], [26.12926, 41.35878], [26.16548, 41.42278], [26.20288, 41.43943], [26.14796, 41.47533], [26.176, 41.50072], [26.17951, 41.55409], [26.14328, 41.55496], [26.15146, 41.60828], [26.07083, 41.64584], [26.06148, 41.70345], [26.16841, 41.74858], [26.21325, 41.73223], [26.22888, 41.74139], [26.2654, 41.71544], [26.30255, 41.70925], [26.35957, 41.71149], [26.32952, 41.73637], [26.33589, 41.76802], [26.36952, 41.82265], [26.53968, 41.82653], [26.57961, 41.90024], [26.56051, 41.92995], [26.62996, 41.97644], [26.79143, 41.97386], [26.95638, 42.00741], [27.03277, 42.0809], [27.08486, 42.08735], [27.19251, 42.06028], [27.22376, 42.10152], [27.27411, 42.10409], [27.45478, 41.96591], [27.52379, 41.93756], [27.55191, 41.90928], [27.69949, 41.97515], [27.81235, 41.94803], [27.83492, 41.99709], [27.91479, 41.97902], [28.02971, 41.98066], [28.32297, 41.98371], [29.24336, 43.70874], [28.23293, 43.76], [27.99558, 43.84193], [27.92008, 44.00761], [27.73468, 43.95326], [27.64542, 44.04958], [27.60834, 44.01206], [27.39757, 44.0141], [27.26845, 44.12602], [26.95141, 44.13555], [26.62712, 44.05698], [26.38764, 44.04356], [26.10115, 43.96908], [26.05584, 43.90925], [25.94911, 43.85745], [25.72792, 43.69263], [25.39528, 43.61866], [25.17144, 43.70261], [25.10718, 43.6831], [24.96682, 43.72693], [24.73542, 43.68523], [24.62281, 43.74082], [24.50264, 43.76314], [24.35364, 43.70211], [24.18149, 43.68218], [23.73978, 43.80627], [23.61687, 43.79289], [23.4507, 43.84936], [23.26772, 43.84843], [23.05288, 43.79494]]]]
23961           }
23962         }, {
23963           type: "Feature",
23964           properties: {
23965             iso1A2: "BH",
23966             iso1A3: "BHR",
23967             iso1N3: "048",
23968             wikidata: "Q398",
23969             nameEn: "Bahrain",
23970             groups: ["145", "142", "UN"],
23971             callingCodes: ["973"]
23972           },
23973           geometry: {
23974             type: "MultiPolygon",
23975             coordinates: [[[[50.93865, 26.30758], [50.71771, 26.73086], [50.38162, 26.53976], [50.26923, 26.08243], [50.302, 25.87592], [50.57069, 25.57887], [50.80824, 25.54641], [50.7801, 25.595], [50.86149, 25.6965], [50.81266, 25.88946], [50.93865, 26.30758]]]]
23976           }
23977         }, {
23978           type: "Feature",
23979           properties: {
23980             iso1A2: "BI",
23981             iso1A3: "BDI",
23982             iso1N3: "108",
23983             wikidata: "Q967",
23984             nameEn: "Burundi",
23985             groups: ["014", "202", "002", "UN"],
23986             callingCodes: ["257"]
23987           },
23988           geometry: {
23989             type: "MultiPolygon",
23990             coordinates: [[[[30.54501, -2.41404], [30.42933, -2.31064], [30.14034, -2.43626], [29.95911, -2.33348], [29.88237, -2.75105], [29.36805, -2.82933], [29.32234, -2.6483], [29.0562, -2.58632], [29.04081, -2.7416], [29.00167, -2.78523], [29.00404, -2.81978], [29.0505, -2.81774], [29.09119, -2.87871], [29.09797, -2.91935], [29.16037, -2.95457], [29.17258, -2.99385], [29.25633, -3.05471], [29.21463, -3.3514], [29.23708, -3.75856], [29.43673, -4.44845], [29.63827, -4.44681], [29.75109, -4.45836], [29.77289, -4.41733], [29.82885, -4.36153], [29.88172, -4.35743], [30.03323, -4.26631], [30.22042, -4.01738], [30.45915, -3.56532], [30.84165, -3.25152], [30.83823, -2.97837], [30.6675, -2.98987], [30.57926, -2.89791], [30.4987, -2.9573], [30.40662, -2.86151], [30.52747, -2.65841], [30.41789, -2.66266], [30.54501, -2.41404]]]]
23991           }
23992         }, {
23993           type: "Feature",
23994           properties: {
23995             iso1A2: "BJ",
23996             iso1A3: "BEN",
23997             iso1N3: "204",
23998             wikidata: "Q962",
23999             nameEn: "Benin",
24000             aliases: ["DY"],
24001             groups: ["011", "202", "002", "UN"],
24002             callingCodes: ["229"]
24003           },
24004           geometry: {
24005             type: "MultiPolygon",
24006             coordinates: [[[[3.59375, 11.70269], [3.48187, 11.86092], [3.31613, 11.88495], [3.25352, 12.01467], [2.83978, 12.40585], [2.6593, 12.30631], [2.37783, 12.24804], [2.39657, 12.10952], [2.45824, 11.98672], [2.39723, 11.89473], [2.29983, 11.68254], [2.00988, 11.42227], [1.42823, 11.46822], [1.03409, 11.04719], [0.9813, 11.08876], [0.91245, 10.99597], [0.8804, 10.803], [0.80358, 10.71459], [0.77666, 10.37665], [1.35507, 9.99525], [1.36624, 9.5951], [1.33675, 9.54765], [1.41746, 9.3226], [1.5649, 9.16941], [1.61838, 9.0527], [1.64249, 6.99562], [1.55877, 6.99737], [1.61812, 6.74843], [1.58105, 6.68619], [1.76906, 6.43189], [1.79826, 6.28221], [1.62913, 6.24075], [1.67336, 6.02702], [2.74181, 6.13349], [2.70566, 6.38038], [2.70464, 6.50831], [2.74334, 6.57291], [2.7325, 6.64057], [2.78204, 6.70514], [2.78823, 6.76356], [2.73405, 6.78508], [2.74024, 6.92802], [2.71702, 6.95722], [2.76965, 7.13543], [2.74489, 7.42565], [2.79442, 7.43486], [2.78668, 7.5116], [2.73405, 7.5423], [2.73095, 7.7755], [2.67523, 7.87825], [2.77907, 9.06924], [3.08017, 9.10006], [3.14147, 9.28375], [3.13928, 9.47167], [3.25093, 9.61632], [3.34726, 9.70696], [3.32099, 9.78032], [3.35383, 9.83641], [3.54429, 9.87739], [3.66908, 10.18136], [3.57275, 10.27185], [3.6844, 10.46351], [3.78292, 10.40538], [3.84243, 10.59316], [3.71505, 11.13015], [3.49175, 11.29765], [3.59375, 11.70269]]]]
24007           }
24008         }, {
24009           type: "Feature",
24010           properties: {
24011             iso1A2: "BL",
24012             iso1A3: "BLM",
24013             iso1N3: "652",
24014             wikidata: "Q25362",
24015             nameEn: "Saint-Barth\xE9lemy",
24016             country: "FR",
24017             groups: ["Q1451600", "029", "003", "419", "019", "UN"],
24018             callingCodes: ["590"]
24019           },
24020           geometry: {
24021             type: "MultiPolygon",
24022             coordinates: [[[[-62.62718, 18.26185], [-63.1055, 17.86651], [-62.34423, 17.49165], [-62.62718, 18.26185]]]]
24023           }
24024         }, {
24025           type: "Feature",
24026           properties: {
24027             iso1A2: "BM",
24028             iso1A3: "BMU",
24029             iso1N3: "060",
24030             wikidata: "Q23635",
24031             nameEn: "Bermuda",
24032             country: "GB",
24033             groups: ["BOTS", "021", "003", "019", "UN"],
24034             driveSide: "left",
24035             callingCodes: ["1 441"]
24036           },
24037           geometry: {
24038             type: "MultiPolygon",
24039             coordinates: [[[[-63.20987, 32.6953], [-65.31453, 32.68437], [-65.63955, 31.43417], [-63.20987, 32.6953]]]]
24040           }
24041         }, {
24042           type: "Feature",
24043           properties: {
24044             iso1A2: "BN",
24045             iso1A3: "BRN",
24046             iso1N3: "096",
24047             wikidata: "Q921",
24048             nameEn: "Brunei",
24049             groups: ["Q36117", "035", "142", "UN"],
24050             driveSide: "left",
24051             callingCodes: ["673"]
24052           },
24053           geometry: {
24054             type: "MultiPolygon",
24055             coordinates: [[[[115.16236, 5.01011], [115.02521, 5.35005], [114.10166, 4.76112], [114.07448, 4.58441], [114.15813, 4.57], [114.26876, 4.49878], [114.32176, 4.34942], [114.32176, 4.2552], [114.4416, 4.27588], [114.49922, 4.13108], [114.64211, 4.00694], [114.78539, 4.12205], [114.88039, 4.4257], [114.83189, 4.42387], [114.77303, 4.72871], [114.8266, 4.75062], [114.88841, 4.81905], [114.96982, 4.81146], [114.99417, 4.88201], [115.05038, 4.90275], [115.02955, 4.82087], [115.02278, 4.74137], [115.04064, 4.63706], [115.07737, 4.53418], [115.09978, 4.39123], [115.31275, 4.30806], [115.36346, 4.33563], [115.2851, 4.42295], [115.27819, 4.63661], [115.20737, 4.8256], [115.15092, 4.87604], [115.16236, 5.01011]]]]
24056           }
24057         }, {
24058           type: "Feature",
24059           properties: {
24060             iso1A2: "BO",
24061             iso1A3: "BOL",
24062             iso1N3: "068",
24063             wikidata: "Q750",
24064             nameEn: "Bolivia",
24065             groups: ["005", "419", "019", "UN"],
24066             callingCodes: ["591"]
24067           },
24068           geometry: {
24069             type: "MultiPolygon",
24070             coordinates: [[[[-63.90248, -12.52544], [-64.22539, -12.45267], [-64.30708, -12.46398], [-64.99778, -11.98604], [-65.30027, -11.48749], [-65.28141, -10.86289], [-65.35402, -10.78685], [-65.37923, -10.35141], [-65.29019, -9.86253], [-65.40615, -9.63894], [-65.56244, -9.84266], [-65.68343, -9.75323], [-67.17784, -10.34016], [-68.71533, -11.14749], [-68.7651, -11.0496], [-68.75179, -11.03688], [-68.75265, -11.02383], [-68.74802, -11.00891], [-69.42792, -10.93451], [-69.47839, -10.95254], [-69.57156, -10.94555], [-68.98115, -11.8979], [-68.65044, -12.50689], [-68.85615, -12.87769], [-68.8864, -13.40792], [-69.05265, -13.68546], [-68.88135, -14.18639], [-69.36254, -14.94634], [-69.14856, -15.23478], [-69.40336, -15.61358], [-69.20291, -16.16668], [-69.09986, -16.22693], [-68.96238, -16.194], [-68.79464, -16.33272], [-68.98358, -16.42165], [-69.04027, -16.57214], [-69.00853, -16.66769], [-69.16896, -16.72233], [-69.62883, -17.28142], [-69.46863, -17.37466], [-69.46897, -17.4988], [-69.46623, -17.60518], [-69.34126, -17.72753], [-69.28671, -17.94844], [-69.07496, -18.03715], [-69.14807, -18.16893], [-69.07432, -18.28259], [-68.94987, -18.93302], [-68.87082, -19.06003], [-68.80602, -19.08355], [-68.61989, -19.27584], [-68.41218, -19.40499], [-68.66761, -19.72118], [-68.54611, -19.84651], [-68.57132, -20.03134], [-68.74273, -20.08817], [-68.7276, -20.46178], [-68.44023, -20.62701], [-68.55383, -20.7355], [-68.53957, -20.91542], [-68.40403, -20.94562], [-68.18816, -21.28614], [-67.85114, -22.87076], [-67.54284, -22.89771], [-67.18382, -22.81525], [-66.7298, -22.23644], [-66.29714, -22.08741], [-66.24077, -21.77837], [-66.03836, -21.84829], [-66.04832, -21.9187], [-65.9261, -21.93335], [-65.7467, -22.10105], [-65.61166, -22.09504], [-65.58694, -22.09794], [-65.57743, -22.07675], [-65.47435, -22.08908], [-64.99524, -22.08255], [-64.90014, -22.12136], [-64.67174, -22.18957], [-64.58888, -22.25035], [-64.4176, -22.67692], [-64.35108, -22.73282], [-64.31489, -22.88824], [-64.22918, -22.55807], [-63.93287, -21.99934], [-63.70963, -21.99934], [-63.68113, -22.0544], [-63.66482, -21.99918], [-62.81124, -21.9987], [-62.8078, -22.12534], [-62.64455, -22.25091], [-62.2757, -21.06657], [-62.26883, -20.55311], [-61.93912, -20.10053], [-61.73723, -19.63958], [-60.00638, -19.2981], [-59.06965, -19.29148], [-58.23216, -19.80058], [-58.16225, -20.16193], [-57.8496, -19.98346], [-58.14215, -19.76276], [-57.78463, -19.03259], [-57.71113, -19.03161], [-57.69134, -19.00544], [-57.71995, -18.97546], [-57.71995, -18.89573], [-57.76764, -18.90087], [-57.56807, -18.25655], [-57.48237, -18.24219], [-57.69877, -17.8431], [-57.73949, -17.56095], [-57.90082, -17.44555], [-57.99661, -17.5273], [-58.32935, -17.28195], [-58.5058, -16.80958], [-58.30918, -16.3699], [-58.32431, -16.25861], [-58.41506, -16.32636], [-60.16069, -16.26479], [-60.23797, -15.50267], [-60.58224, -15.09887], [-60.23968, -15.09515], [-60.27887, -14.63021], [-60.46037, -14.22496], [-60.48053, -13.77981], [-61.05527, -13.50054], [-61.81151, -13.49564], [-63.76259, -12.42952], [-63.90248, -12.52544]]]]
24071           }
24072         }, {
24073           type: "Feature",
24074           properties: {
24075             iso1A2: "BQ",
24076             iso1A3: "BES",
24077             iso1N3: "535",
24078             wikidata: "Q27561",
24079             nameEn: "Caribbean Netherlands",
24080             country: "NL"
24081           },
24082           geometry: null
24083         }, {
24084           type: "Feature",
24085           properties: {
24086             iso1A2: "BR",
24087             iso1A3: "BRA",
24088             iso1N3: "076",
24089             wikidata: "Q155",
24090             nameEn: "Brazil",
24091             groups: ["005", "419", "019", "UN"],
24092             callingCodes: ["55"]
24093           },
24094           geometry: {
24095             type: "MultiPolygon",
24096             coordinates: [[[[-59.69361, 4.34069], [-59.78878, 4.45637], [-60.15953, 4.53456], [-60.04189, 4.69801], [-59.98129, 5.07097], [-60.20944, 5.28754], [-60.32352, 5.21299], [-60.73204, 5.20931], [-60.5802, 4.94312], [-60.86539, 4.70512], [-60.98303, 4.54167], [-61.15703, 4.49839], [-61.31457, 4.54167], [-61.29675, 4.44216], [-61.48569, 4.43149], [-61.54629, 4.2822], [-62.13094, 4.08309], [-62.44822, 4.18621], [-62.57656, 4.04754], [-62.74411, 4.03331], [-62.7655, 3.73099], [-62.98296, 3.59935], [-63.21111, 3.96219], [-63.4464, 3.9693], [-63.42233, 3.89995], [-63.50611, 3.83592], [-63.67099, 4.01731], [-63.70218, 3.91417], [-63.86082, 3.94796], [-63.99183, 3.90172], [-64.14512, 4.12932], [-64.57648, 4.12576], [-64.72977, 4.28931], [-64.84028, 4.24665], [-64.48379, 3.7879], [-64.02908, 2.79797], [-64.0257, 2.48156], [-63.39114, 2.4317], [-63.39827, 2.16098], [-64.06135, 1.94722], [-64.08274, 1.64792], [-64.34654, 1.35569], [-64.38932, 1.5125], [-65.11657, 1.12046], [-65.57288, 0.62856], [-65.50158, 0.92086], [-65.6727, 1.01353], [-66.28507, 0.74585], [-66.85795, 1.22998], [-67.08222, 1.17441], [-67.15784, 1.80439], [-67.299, 1.87494], [-67.40488, 2.22258], [-67.9292, 1.82455], [-68.18632, 2.00091], [-68.26699, 1.83463], [-68.18128, 1.72881], [-69.38621, 1.70865], [-69.53746, 1.76408], [-69.83491, 1.69353], [-69.82987, 1.07864], [-69.26017, 1.06856], [-69.14422, 0.84172], [-69.20976, 0.57958], [-69.47696, 0.71065], [-70.04162, 0.55437], [-70.03658, -0.19681], [-69.603, -0.51947], [-69.59796, -0.75136], [-69.4215, -1.01853], [-69.43395, -1.42219], [-69.94708, -4.2431], [-70.00888, -4.37833], [-70.11305, -4.27281], [-70.19582, -4.3607], [-70.33236, -4.15214], [-70.77601, -4.15717], [-70.96814, -4.36915], [-71.87003, -4.51661], [-72.64391, -5.0391], [-72.83973, -5.14765], [-73.24579, -6.05764], [-73.12983, -6.43852], [-73.73986, -6.87919], [-73.77011, -7.28944], [-73.96938, -7.58465], [-73.65485, -7.77897], [-73.76576, -7.89884], [-72.92886, -9.04074], [-73.21498, -9.40904], [-72.72216, -9.41397], [-72.31883, -9.5184], [-72.14742, -9.98049], [-71.23394, -9.9668], [-70.53373, -9.42628], [-70.58453, -9.58303], [-70.55429, -9.76692], [-70.62487, -9.80666], [-70.64134, -11.0108], [-70.51395, -10.92249], [-70.38791, -11.07096], [-69.90896, -10.92744], [-69.57835, -10.94051], [-69.57156, -10.94555], [-69.47839, -10.95254], [-69.42792, -10.93451], [-68.74802, -11.00891], [-68.75265, -11.02383], [-68.75179, -11.03688], [-68.7651, -11.0496], [-68.71533, -11.14749], [-67.17784, -10.34016], [-65.68343, -9.75323], [-65.56244, -9.84266], [-65.40615, -9.63894], [-65.29019, -9.86253], [-65.37923, -10.35141], [-65.35402, -10.78685], [-65.28141, -10.86289], [-65.30027, -11.48749], [-64.99778, -11.98604], [-64.30708, -12.46398], [-64.22539, -12.45267], [-63.90248, -12.52544], [-63.76259, -12.42952], [-61.81151, -13.49564], [-61.05527, -13.50054], [-60.48053, -13.77981], [-60.46037, -14.22496], [-60.27887, -14.63021], [-60.23968, -15.09515], [-60.58224, -15.09887], [-60.23797, -15.50267], [-60.16069, -16.26479], [-58.41506, -16.32636], [-58.32431, -16.25861], [-58.30918, -16.3699], [-58.5058, -16.80958], [-58.32935, -17.28195], [-57.99661, -17.5273], [-57.90082, -17.44555], [-57.73949, -17.56095], [-57.69877, -17.8431], [-57.48237, -18.24219], [-57.56807, -18.25655], [-57.76764, -18.90087], [-57.71995, -18.89573], [-57.71995, -18.97546], [-57.69134, -19.00544], [-57.71113, -19.03161], [-57.78463, -19.03259], [-58.14215, -19.76276], [-57.8496, -19.98346], [-58.16225, -20.16193], [-57.84536, -20.93155], [-57.93492, -21.65505], [-57.88239, -21.6868], [-57.94642, -21.73799], [-57.98625, -22.09157], [-56.6508, -22.28387], [-56.5212, -22.11556], [-56.45893, -22.08072], [-56.23206, -22.25347], [-55.8331, -22.29008], [-55.74941, -22.46436], [-55.741, -22.52018], [-55.72366, -22.5519], [-55.6986, -22.56268], [-55.68742, -22.58407], [-55.62493, -22.62765], [-55.63849, -22.95122], [-55.5446, -23.22811], [-55.52288, -23.2595], [-55.5555, -23.28237], [-55.43585, -23.87157], [-55.44117, -23.9185], [-55.41784, -23.9657], [-55.12292, -23.99669], [-55.0518, -23.98666], [-55.02691, -23.97317], [-54.6238, -23.83078], [-54.32807, -24.01865], [-54.28207, -24.07305], [-54.4423, -25.13381], [-54.62033, -25.46026], [-54.60196, -25.48397], [-54.59509, -25.53696], [-54.59398, -25.59224], [-54.5502, -25.58915], [-54.52926, -25.62846], [-53.90831, -25.55513], [-53.83691, -25.94849], [-53.73511, -26.04211], [-53.73086, -26.05842], [-53.7264, -26.0664], [-53.73391, -26.07006], [-53.73968, -26.10012], [-53.65018, -26.19501], [-53.65237, -26.23289], [-53.63739, -26.2496], [-53.63881, -26.25075], [-53.64632, -26.24798], [-53.64186, -26.25976], [-53.64505, -26.28089], [-53.68269, -26.33359], [-53.73372, -26.6131], [-53.80144, -27.09844], [-54.15978, -27.2889], [-54.19062, -27.27639], [-54.19268, -27.30751], [-54.41888, -27.40882], [-54.50416, -27.48232], [-54.67657, -27.57214], [-54.90159, -27.63132], [-54.90805, -27.73149], [-55.1349, -27.89759], [-55.16872, -27.86224], [-55.33303, -27.94661], [-55.6262, -28.17124], [-55.65418, -28.18304], [-56.01729, -28.51223], [-56.00458, -28.60421], [-56.05265, -28.62651], [-56.54171, -29.11447], [-56.57295, -29.11357], [-56.62789, -29.18073], [-56.81251, -29.48154], [-57.09386, -29.74211], [-57.65132, -30.19229], [-57.22502, -30.26121], [-56.90236, -30.02578], [-56.49267, -30.39471], [-56.4795, -30.3899], [-56.4619, -30.38457], [-55.87388, -31.05053], [-55.58866, -30.84117], [-55.5634, -30.8686], [-55.55373, -30.8732], [-55.55218, -30.88193], [-55.54572, -30.89051], [-55.53431, -30.89714], [-55.53276, -30.90218], [-55.52712, -30.89997], [-55.51862, -30.89828], [-55.50841, -30.9027], [-55.50821, -30.91349], [-54.17384, -31.86168], [-53.76024, -32.0751], [-53.39572, -32.58596], [-53.37671, -32.57005], [-53.1111, -32.71147], [-53.53459, -33.16843], [-53.52794, -33.68908], [-53.44031, -33.69344], [-53.39593, -33.75169], [-53.37138, -33.74313], [-52.83257, -34.01481], [-28.34015, -20.99094], [-28.99601, 1.86593], [-51.35485, 4.8383], [-51.63798, 4.51394], [-51.61983, 4.14596], [-51.79599, 3.89336], [-51.82312, 3.85825], [-51.85573, 3.83427], [-52.31787, 3.17896], [-52.6906, 2.37298], [-52.96539, 2.1881], [-53.78743, 2.34412], [-54.16286, 2.10779], [-54.6084, 2.32856], [-55.01919, 2.564], [-55.71493, 2.40342], [-55.96292, 2.53188], [-56.13054, 2.27723], [-55.92159, 2.05236], [-55.89863, 1.89861], [-55.99278, 1.83137], [-56.47045, 1.95135], [-56.7659, 1.89509], [-57.07092, 1.95304], [-57.09109, 2.01854], [-57.23981, 1.95808], [-57.35073, 1.98327], [-57.55743, 1.69605], [-57.77281, 1.73344], [-57.97336, 1.64566], [-58.01873, 1.51966], [-58.33887, 1.58014], [-58.4858, 1.48399], [-58.53571, 1.29154], [-58.84229, 1.17749], [-58.92072, 1.31293], [-59.25583, 1.40559], [-59.74066, 1.87596], [-59.7264, 2.27497], [-59.91177, 2.36759], [-59.99733, 2.92312], [-59.79769, 3.37162], [-59.86899, 3.57089], [-59.51963, 3.91951], [-59.73353, 4.20399], [-59.69361, 4.34069]]]]
24097           }
24098         }, {
24099           type: "Feature",
24100           properties: {
24101             iso1A2: "BS",
24102             iso1A3: "BHS",
24103             iso1N3: "044",
24104             wikidata: "Q778",
24105             nameEn: "The Bahamas",
24106             groups: ["029", "003", "419", "019", "UN"],
24107             driveSide: "left",
24108             roadSpeedUnit: "mph",
24109             callingCodes: ["1 242"]
24110           },
24111           geometry: {
24112             type: "MultiPolygon",
24113             coordinates: [[[[-72.98446, 20.4801], [-71.70065, 25.7637], [-78.91214, 27.76553], [-80.65727, 23.71953], [-72.98446, 20.4801]]]]
24114           }
24115         }, {
24116           type: "Feature",
24117           properties: {
24118             iso1A2: "BT",
24119             iso1A3: "BTN",
24120             iso1N3: "064",
24121             wikidata: "Q917",
24122             nameEn: "Bhutan",
24123             groups: ["034", "142", "UN"],
24124             driveSide: "left",
24125             callingCodes: ["975"]
24126           },
24127           geometry: {
24128             type: "MultiPolygon",
24129             coordinates: [[[[91.6469, 27.76358], [91.5629, 27.84823], [91.48973, 27.93903], [91.46327, 28.0064], [91.25779, 28.07509], [91.20019, 27.98715], [90.69894, 28.07784], [90.58842, 28.02838], [90.13387, 28.19178], [89.79762, 28.23979], [89.59525, 28.16433], [89.12825, 27.62502], [89.0582, 27.60985], [88.97213, 27.51671], [88.95355, 27.4106], [89.00216, 27.32532], [88.96947, 27.30319], [88.93678, 27.33777], [88.91901, 27.32483], [88.74219, 27.144], [88.86984, 27.10937], [88.8714, 26.97488], [88.92301, 26.99286], [88.95807, 26.92668], [89.09554, 26.89089], [89.12825, 26.81661], [89.1926, 26.81329], [89.37913, 26.86224], [89.38319, 26.85963], [89.3901, 26.84225], [89.42349, 26.83727], [89.63369, 26.74402], [89.86124, 26.73307], [90.04535, 26.72422], [90.30402, 26.85098], [90.39271, 26.90704], [90.48504, 26.8594], [90.67715, 26.77215], [91.50067, 26.79223], [91.83181, 26.87318], [92.05523, 26.8692], [92.11863, 26.893], [92.03457, 27.07334], [92.04702, 27.26861], [92.12019, 27.27829], [92.01132, 27.47352], [91.65007, 27.48287], [91.55819, 27.6144], [91.6469, 27.76358]]]]
24130           }
24131         }, {
24132           type: "Feature",
24133           properties: {
24134             iso1A2: "BV",
24135             iso1A3: "BVT",
24136             iso1N3: "074",
24137             wikidata: "Q23408",
24138             nameEn: "Bouvet Island",
24139             country: "NO",
24140             groups: ["005", "419", "019", "UN"]
24141           },
24142           geometry: {
24143             type: "MultiPolygon",
24144             coordinates: [[[[4.54042, -54.0949], [2.28941, -54.13089], [3.35353, -55.17558], [4.54042, -54.0949]]]]
24145           }
24146         }, {
24147           type: "Feature",
24148           properties: {
24149             iso1A2: "BW",
24150             iso1A3: "BWA",
24151             iso1N3: "072",
24152             wikidata: "Q963",
24153             nameEn: "Botswana",
24154             groups: ["018", "202", "002", "UN"],
24155             driveSide: "left",
24156             callingCodes: ["267"]
24157           },
24158           geometry: {
24159             type: "MultiPolygon",
24160             coordinates: [[[[25.26433, -17.79571], [25.16882, -17.78253], [25.05895, -17.84452], [24.95586, -17.79674], [24.73364, -17.89338], [24.71887, -17.9218], [24.6303, -17.9863], [24.57485, -18.07151], [24.40577, -17.95726], [24.19416, -18.01919], [23.61088, -18.4881], [23.29618, -17.99855], [23.0996, -18.00075], [21.45556, -18.31795], [20.99904, -18.31743], [20.99751, -22.00026], [19.99912, -21.99991], [19.99817, -24.76768], [20.02809, -24.78725], [20.03678, -24.81004], [20.29826, -24.94869], [20.64795, -25.47827], [20.86081, -26.14892], [20.61754, -26.4692], [20.63275, -26.78181], [20.68596, -26.9039], [20.87031, -26.80047], [21.13353, -26.86661], [21.37869, -26.82083], [21.69322, -26.86152], [21.7854, -26.79199], [21.77114, -26.69015], [21.83291, -26.65959], [21.90703, -26.66808], [22.06192, -26.61882], [22.21206, -26.3773], [22.41921, -26.23078], [22.56365, -26.19668], [22.70808, -25.99186], [22.86012, -25.50572], [23.03497, -25.29971], [23.47588, -25.29971], [23.9244, -25.64286], [24.18287, -25.62916], [24.36531, -25.773], [24.44703, -25.73021], [24.67319, -25.81749], [24.8946, -25.80723], [25.01718, -25.72507], [25.12266, -25.75931], [25.33076, -25.76616], [25.58543, -25.6343], [25.6643, -25.4491], [25.69661, -25.29284], [25.72702, -25.25503], [25.88571, -24.87802], [25.84295, -24.78661], [25.8515, -24.75727], [26.39409, -24.63468], [26.46346, -24.60358], [26.51667, -24.47219], [26.84165, -24.24885], [26.99749, -23.65486], [27.33768, -23.40917], [27.52393, -23.37952], [27.6066, -23.21894], [27.74154, -23.2137], [27.93539, -23.04941], [27.93729, -22.96194], [28.04752, -22.90243], [28.04562, -22.8394], [28.34874, -22.5694], [28.63287, -22.55887], [28.91889, -22.44299], [29.0151, -22.22907], [29.10881, -22.21202], [29.15268, -22.21399], [29.18974, -22.18599], [29.21955, -22.17771], [29.37703, -22.19581], [29.3533, -22.18363], [29.24648, -22.05967], [29.1974, -22.07472], [29.14501, -22.07275], [29.08495, -22.04867], [29.04108, -22.00563], [29.02191, -21.95665], [29.02191, -21.90647], [29.04023, -21.85864], [29.07763, -21.81877], [28.58114, -21.63455], [28.49942, -21.66634], [28.29416, -21.59037], [28.01669, -21.57624], [27.91407, -21.31621], [27.69171, -21.08409], [27.72972, -20.51735], [27.69361, -20.48531], [27.28865, -20.49873], [27.29831, -20.28935], [27.21278, -20.08244], [26.72246, -19.92707], [26.17227, -19.53709], [25.96226, -19.08152], [25.99837, -19.02943], [25.94326, -18.90362], [25.82353, -18.82808], [25.79217, -18.6355], [25.68859, -18.56165], [25.53465, -18.39041], [25.39972, -18.12691], [25.31799, -18.07091], [25.23909, -17.90832], [25.26433, -17.79571]]]]
24161           }
24162         }, {
24163           type: "Feature",
24164           properties: {
24165             iso1A2: "BY",
24166             iso1A3: "BLR",
24167             iso1N3: "112",
24168             wikidata: "Q184",
24169             nameEn: "Belarus",
24170             groups: ["151", "150", "UN"],
24171             callingCodes: ["375"]
24172           },
24173           geometry: {
24174             type: "MultiPolygon",
24175             coordinates: [[[[28.15217, 56.16964], [27.97865, 56.11849], [27.63065, 55.89687], [27.61683, 55.78558], [27.3541, 55.8089], [27.27804, 55.78299], [27.1559, 55.85032], [26.97153, 55.8102], [26.87448, 55.7172], [26.76872, 55.67658], [26.71802, 55.70645], [26.64888, 55.70515], [26.63231, 55.67968], [26.63167, 55.57887], [26.55094, 55.5093], [26.5522, 55.40277], [26.44937, 55.34832], [26.5709, 55.32572], [26.6714, 55.33902], [26.80929, 55.31642], [26.83266, 55.30444], [26.835, 55.28182], [26.73017, 55.24226], [26.72983, 55.21788], [26.68075, 55.19787], [26.69243, 55.16718], [26.54753, 55.14181], [26.51481, 55.16051], [26.46249, 55.12814], [26.35121, 55.1525], [26.30628, 55.12536], [26.23202, 55.10439], [26.26941, 55.08032], [26.20397, 54.99729], [26.13386, 54.98924], [26.05907, 54.94631], [25.99129, 54.95705], [25.89462, 54.93438], [25.74122, 54.80108], [25.75977, 54.57252], [25.68045, 54.5321], [25.64813, 54.48704], [25.62203, 54.4656], [25.63371, 54.42075], [25.5376, 54.33158], [25.55425, 54.31591], [25.68513, 54.31727], [25.78553, 54.23327], [25.78563, 54.15747], [25.71084, 54.16704], [25.64875, 54.1259], [25.54724, 54.14925], [25.51452, 54.17799], [25.56823, 54.25212], [25.509, 54.30267], [25.35559, 54.26544], [25.22705, 54.26271], [25.19199, 54.219], [25.0728, 54.13419], [24.991, 54.14241], [24.96894, 54.17589], [24.77131, 54.11091], [24.85311, 54.02862], [24.74279, 53.96663], [24.69185, 53.96543], [24.69652, 54.01901], [24.62275, 54.00217], [24.44411, 53.90076], [24.34128, 53.90076], [24.19638, 53.96405], [23.98837, 53.92554], [23.95098, 53.9613], [23.81309, 53.94205], [23.80543, 53.89558], [23.71726, 53.93379], [23.61677, 53.92691], [23.51284, 53.95052], [23.62004, 53.60942], [23.81995, 53.24131], [23.85657, 53.22923], [23.91393, 53.16469], [23.87548, 53.0831], [23.92184, 53.02079], [23.94689, 52.95919], [23.91805, 52.94016], [23.93763, 52.71332], [23.73615, 52.6149], [23.58296, 52.59868], [23.45112, 52.53774], [23.34141, 52.44845], [23.18196, 52.28812], [23.20071, 52.22848], [23.47859, 52.18215], [23.54314, 52.12148], [23.61, 52.11264], [23.64066, 52.07626], [23.68733, 51.9906], [23.61523, 51.92066], [23.62691, 51.78208], [23.53198, 51.74298], [23.57053, 51.55938], [23.56236, 51.53673], [23.62751, 51.50512], [23.6736, 51.50255], [23.60906, 51.62122], [23.7766, 51.66809], [23.91118, 51.63316], [23.8741, 51.59734], [23.99907, 51.58369], [24.13075, 51.66979], [24.3163, 51.75063], [24.29021, 51.80841], [24.37123, 51.88222], [24.98784, 51.91273], [25.20228, 51.97143], [25.46163, 51.92205], [25.73673, 51.91973], [25.80574, 51.94556], [25.83217, 51.92587], [26.00408, 51.92967], [26.19084, 51.86781], [26.39367, 51.87315], [26.46962, 51.80501], [26.69759, 51.82284], [26.80043, 51.75777], [26.9489, 51.73788], [26.99422, 51.76933], [27.20602, 51.77291], [27.20948, 51.66713], [27.26613, 51.65957], [27.24828, 51.60161], [27.47212, 51.61184], [27.51058, 51.5854], [27.55727, 51.63486], [27.71932, 51.60672], [27.67125, 51.50854], [27.76052, 51.47604], [27.85253, 51.62293], [27.91844, 51.61952], [27.95827, 51.56065], [28.10658, 51.57857], [28.23452, 51.66988], [28.37592, 51.54505], [28.47051, 51.59734], [28.64429, 51.5664], [28.69161, 51.44695], [28.73143, 51.46236], [28.75615, 51.41442], [28.78224, 51.45294], [28.76027, 51.48802], [28.81795, 51.55552], [28.95528, 51.59222], [28.99098, 51.56833], [29.1187, 51.65872], [29.16402, 51.64679], [29.20659, 51.56918], [29.25603, 51.57089], [29.25191, 51.49828], [29.32881, 51.37843], [29.42357, 51.4187], [29.49773, 51.39814], [29.54372, 51.48372], [29.7408, 51.53417], [29.77376, 51.4461], [30.17888, 51.51025], [30.34642, 51.42555], [30.36153, 51.33984], [30.56203, 51.25655], [30.64992, 51.35014], [30.51946, 51.59649], [30.68804, 51.82806], [30.76443, 51.89739], [30.90897, 52.00699], [30.95589, 52.07775], [31.13332, 52.1004], [31.25142, 52.04131], [31.38326, 52.12991], [31.7822, 52.11406], [31.77877, 52.18636], [31.6895, 52.1973], [31.70735, 52.26711], [31.57971, 52.32146], [31.62084, 52.33849], [31.61397, 52.48843], [31.56316, 52.51518], [31.63869, 52.55361], [31.50406, 52.69707], [31.57277, 52.71613], [31.592, 52.79011], [31.35667, 52.97854], [31.24147, 53.031], [31.32283, 53.04101], [31.33519, 53.08805], [31.3915, 53.09712], [31.36403, 53.13504], [31.40523, 53.21406], [31.56316, 53.19432], [31.62496, 53.22886], [31.787, 53.18033], [31.82373, 53.10042], [32.15368, 53.07594], [32.40773, 53.18856], [32.51725, 53.28431], [32.73257, 53.33494], [32.74968, 53.45597], [32.47777, 53.5548], [32.40499, 53.6656], [32.50112, 53.68594], [32.45717, 53.74039], [32.36663, 53.7166], [32.12621, 53.81586], [31.89137, 53.78099], [31.77028, 53.80015], [31.85019, 53.91801], [31.88744, 54.03653], [31.89599, 54.0837], [31.57002, 54.14535], [31.30791, 54.25315], [31.3177, 54.34067], [31.22945, 54.46585], [31.08543, 54.50361], [31.21399, 54.63113], [31.19339, 54.66947], [30.99187, 54.67046], [30.98226, 54.68872], [31.0262, 54.70698], [30.97127, 54.71967], [30.95479, 54.74346], [30.75165, 54.80699], [30.8264, 54.90062], [30.81759, 54.94064], [30.93144, 54.9585], [30.95754, 54.98609], [30.9081, 55.02232], [30.94243, 55.03964], [31.00972, 55.02783], [31.02071, 55.06167], [30.97369, 55.17134], [30.87944, 55.28223], [30.81946, 55.27931], [30.8257, 55.3313], [30.93144, 55.3914], [30.90123, 55.46621], [30.95204, 55.50667], [30.93419, 55.6185], [30.86003, 55.63169], [30.7845, 55.58514], [30.72957, 55.66268], [30.67464, 55.64176], [30.63344, 55.73079], [30.51037, 55.76568], [30.51346, 55.78982], [30.48257, 55.81066], [30.30987, 55.83592], [30.27776, 55.86819], [30.12136, 55.8358], [29.97975, 55.87281], [29.80672, 55.79569], [29.61446, 55.77716], [29.51283, 55.70294], [29.3604, 55.75862], [29.44692, 55.95978], [29.21717, 55.98971], [29.08299, 56.03427], [28.73418, 55.97131], [28.63668, 56.07262], [28.68337, 56.10173], [28.5529, 56.11705], [28.43068, 56.09407], [28.37987, 56.11399], [28.36888, 56.05805], [28.30571, 56.06035], [28.15217, 56.16964]]]]
24176           }
24177         }, {
24178           type: "Feature",
24179           properties: {
24180             iso1A2: "BZ",
24181             iso1A3: "BLZ",
24182             iso1N3: "084",
24183             wikidata: "Q242",
24184             nameEn: "Belize",
24185             groups: ["013", "003", "419", "019", "UN"],
24186             roadSpeedUnit: "mph",
24187             callingCodes: ["501"]
24188           },
24189           geometry: {
24190             type: "MultiPolygon",
24191             coordinates: [[[[-88.3268, 18.49048], [-88.48242, 18.49164], [-88.71505, 18.0707], [-88.8716, 17.89535], [-89.03839, 18.0067], [-89.15105, 17.95104], [-89.14985, 17.81563], [-89.15025, 17.04813], [-89.22683, 15.88619], [-89.17418, 15.90898], [-89.02415, 15.9063], [-88.95358, 15.88698], [-88.40779, 16.09624], [-86.92368, 17.61462], [-87.84815, 18.18511], [-87.85693, 18.18266], [-87.86657, 18.19971], [-87.87604, 18.18313], [-87.90671, 18.15213], [-88.03165, 18.16657], [-88.03238, 18.41778], [-88.26593, 18.47617], [-88.29909, 18.47591], [-88.3268, 18.49048]]]]
24192           }
24193         }, {
24194           type: "Feature",
24195           properties: {
24196             iso1A2: "CA",
24197             iso1A3: "CAN",
24198             iso1N3: "124",
24199             wikidata: "Q16",
24200             nameEn: "Canada",
24201             groups: ["021", "003", "019", "UN"],
24202             callingCodes: ["1"]
24203           },
24204           geometry: {
24205             type: "MultiPolygon",
24206             coordinates: [[[[-67.20349, 45.1722], [-67.19603, 45.16771], [-67.15965, 45.16179], [-67.11316, 45.11176], [-67.0216, 44.95333], [-66.96824, 44.90965], [-66.98249, 44.87071], [-66.96824, 44.83078], [-66.93432, 44.82597], [-67.16117, 44.20069], [-61.98255, 37.34815], [-56.27503, 47.39728], [-53.12387, 41.40385], [-46.37635, 57.3249], [-77.52957, 77.23408], [-68.21821, 80.48551], [-49.33696, 84.57952], [-140.97446, 84.39275], [-141.00116, 60.30648], [-140.5227, 60.22077], [-140.45648, 60.30919], [-139.98024, 60.18027], [-139.68991, 60.33693], [-139.05831, 60.35205], [-139.20603, 60.08896], [-139.05365, 59.99655], [-138.71149, 59.90728], [-138.62145, 59.76431], [-137.60623, 59.24465], [-137.4925, 58.89415], [-136.82619, 59.16198], [-136.52365, 59.16752], [-136.47323, 59.46617], [-136.33727, 59.44466], [-136.22381, 59.55526], [-136.31566, 59.59083], [-135.48007, 59.79937], [-135.03069, 59.56208], [-135.00267, 59.28745], [-134.7047, 59.2458], [-134.55699, 59.1297], [-134.48059, 59.13231], [-134.27175, 58.8634], [-133.84645, 58.73543], [-133.38523, 58.42773], [-131.8271, 56.62247], [-130.77769, 56.36185], [-130.33965, 56.10849], [-130.10173, 56.12178], [-130.00093, 56.00325], [-130.00857, 55.91344], [-130.15373, 55.74895], [-129.97513, 55.28029], [-130.08035, 55.21556], [-130.18765, 55.07744], [-130.27203, 54.97174], [-130.44184, 54.85377], [-130.64499, 54.76912], [-130.61931, 54.70835], [-133.92876, 54.62289], [-133.36909, 48.51151], [-125.03842, 48.53282], [-123.50039, 48.21223], [-123.15614, 48.35395], [-123.26565, 48.6959], [-123.0093, 48.76586], [-123.0093, 48.83186], [-123.32163, 49.00419], [-95.15355, 48.9996], [-95.15357, 49.384], [-95.12903, 49.37056], [-95.05825, 49.35311], [-95.01419, 49.35647], [-94.99532, 49.36579], [-94.95681, 49.37035], [-94.85381, 49.32492], [-94.8159, 49.32299], [-94.82487, 49.29483], [-94.77355, 49.11998], [-94.75017, 49.09931], [-94.687, 48.84077], [-94.70087, 48.8339], [-94.70486, 48.82365], [-94.69669, 48.80918], [-94.69335, 48.77883], [-94.58903, 48.71803], [-94.54885, 48.71543], [-94.53826, 48.70216], [-94.44258, 48.69223], [-94.4174, 48.71049], [-94.27153, 48.70232], [-94.25172, 48.68404], [-94.25104, 48.65729], [-94.23215, 48.65202], [-93.85769, 48.63284], [-93.83288, 48.62745], [-93.80676, 48.58232], [-93.80939, 48.52439], [-93.79267, 48.51631], [-93.66382, 48.51845], [-93.47022, 48.54357], [-93.44472, 48.59147], [-93.40693, 48.60948], [-93.39758, 48.60364], [-93.3712, 48.60599], [-93.33946, 48.62787], [-93.25391, 48.64266], [-92.94973, 48.60866], [-92.7287, 48.54005], [-92.6342, 48.54133], [-92.62747, 48.50278], [-92.69927, 48.49573], [-92.71323, 48.46081], [-92.65606, 48.43471], [-92.50712, 48.44921], [-92.45588, 48.40624], [-92.48147, 48.36609], [-92.37185, 48.22259], [-92.27167, 48.25046], [-92.30939, 48.31251], [-92.26662, 48.35651], [-92.202, 48.35252], [-92.14732, 48.36578], [-92.05339, 48.35958], [-91.98929, 48.25409], [-91.86125, 48.21278], [-91.71231, 48.19875], [-91.70451, 48.11805], [-91.55649, 48.10611], [-91.58025, 48.04339], [-91.45829, 48.07454], [-91.43248, 48.04912], [-91.25025, 48.08522], [-91.08016, 48.18096], [-90.87588, 48.2484], [-90.75045, 48.09143], [-90.56444, 48.12184], [-90.56312, 48.09488], [-90.07418, 48.11043], [-89.89974, 47.98109], [-89.77248, 48.02607], [-89.57972, 48.00023], [-89.48837, 48.01412], [-88.37033, 48.30586], [-84.85871, 46.88881], [-84.55635, 46.45974], [-84.47607, 46.45225], [-84.4481, 46.48972], [-84.42101, 46.49853], [-84.34174, 46.50683], [-84.29893, 46.49127], [-84.26351, 46.49508], [-84.2264, 46.53337], [-84.1945, 46.54061], [-84.17723, 46.52753], [-84.12885, 46.53068], [-84.11196, 46.50248], [-84.13451, 46.39218], [-84.11254, 46.32329], [-84.11615, 46.2681], [-84.09756, 46.25512], [-84.1096, 46.23987], [-83.95399, 46.05634], [-83.90453, 46.05922], [-83.83329, 46.12169], [-83.57017, 46.105], [-83.43746, 45.99749], [-83.59589, 45.82131], [-82.48419, 45.30225], [-82.42469, 42.992], [-82.4146, 42.97626], [-82.4253, 42.95423], [-82.45331, 42.93139], [-82.4826, 42.8068], [-82.46613, 42.76615], [-82.51063, 42.66025], [-82.51858, 42.611], [-82.57583, 42.5718], [-82.58873, 42.54984], [-82.64242, 42.55594], [-82.82964, 42.37355], [-83.02253, 42.33045], [-83.07837, 42.30978], [-83.09837, 42.28877], [-83.12724, 42.2376], [-83.14962, 42.04089], [-83.11184, 41.95671], [-82.67862, 41.67615], [-78.93684, 42.82887], [-78.90712, 42.89733], [-78.90905, 42.93022], [-78.93224, 42.95229], [-78.96312, 42.95509], [-78.98126, 42.97], [-79.02074, 42.98444], [-79.02424, 43.01983], [-78.99941, 43.05612], [-79.01055, 43.06659], [-79.07486, 43.07845], [-79.05671, 43.10937], [-79.06881, 43.12029], [-79.0427, 43.13934], [-79.04652, 43.16396], [-79.05384, 43.17418], [-79.05002, 43.20133], [-79.05544, 43.21224], [-79.05512, 43.25375], [-79.06921, 43.26183], [-79.25796, 43.54052], [-76.79706, 43.63099], [-76.43859, 44.09393], [-76.35324, 44.13493], [-76.31222, 44.19894], [-76.244, 44.19643], [-76.1664, 44.23051], [-76.16285, 44.28262], [-76.00018, 44.34896], [-75.95947, 44.34463], [-75.8217, 44.43176], [-75.76813, 44.51537], [-75.41441, 44.76614], [-75.2193, 44.87821], [-75.01363, 44.95608], [-74.99101, 44.98051], [-74.8447, 45.00606], [-74.66689, 45.00646], [-74.32699, 44.99029], [-73.35025, 45.00942], [-71.50067, 45.01357], [-71.48735, 45.07784], [-71.42778, 45.12624], [-71.40364, 45.21382], [-71.44252, 45.2361], [-71.37133, 45.24624], [-71.29371, 45.29996], [-71.22338, 45.25184], [-71.19723, 45.25438], [-71.14568, 45.24128], [-71.08364, 45.30623], [-71.01866, 45.31573], [-71.0107, 45.34819], [-70.95193, 45.33895], [-70.91169, 45.29849], [-70.89864, 45.2398], [-70.84816, 45.22698], [-70.80236, 45.37444], [-70.82638, 45.39828], [-70.78372, 45.43269], [-70.65383, 45.37592], [-70.62518, 45.42286], [-70.72651, 45.49771], [-70.68516, 45.56964], [-70.54019, 45.67291], [-70.38934, 45.73215], [-70.41523, 45.79497], [-70.25976, 45.89675], [-70.24694, 45.95138], [-70.31025, 45.96424], [-70.23855, 46.1453], [-70.29078, 46.18832], [-70.18547, 46.35357], [-70.05812, 46.41768], [-69.99966, 46.69543], [-69.22119, 47.46461], [-69.05148, 47.42012], [-69.05073, 47.30076], [-69.05039, 47.2456], [-68.89222, 47.1807], [-68.70125, 47.24399], [-68.60575, 47.24659], [-68.57914, 47.28431], [-68.38332, 47.28723], [-68.37458, 47.35851], [-68.23244, 47.35712], [-67.94843, 47.1925], [-67.87993, 47.10377], [-67.78578, 47.06473], [-67.78111, 45.9392], [-67.75196, 45.91814], [-67.80961, 45.87531], [-67.75654, 45.82324], [-67.80653, 45.80022], [-67.80705, 45.69528], [-67.6049, 45.60725], [-67.43815, 45.59162], [-67.42144, 45.50584], [-67.50578, 45.48971], [-67.42394, 45.37969], [-67.48201, 45.27351], [-67.34927, 45.122], [-67.29754, 45.14865], [-67.29748, 45.18173], [-67.27039, 45.1934], [-67.22751, 45.16344], [-67.20349, 45.1722]]]]
24207           }
24208         }, {
24209           type: "Feature",
24210           properties: {
24211             iso1A2: "CC",
24212             iso1A3: "CCK",
24213             iso1N3: "166",
24214             wikidata: "Q36004",
24215             nameEn: "Cocos (Keeling) Islands",
24216             country: "AU",
24217             groups: ["053", "009", "UN"],
24218             driveSide: "left",
24219             callingCodes: ["61"]
24220           },
24221           geometry: {
24222             type: "MultiPolygon",
24223             coordinates: [[[[96.61846, -10.82438], [96.02343, -12.68334], [97.93979, -12.33309], [96.61846, -10.82438]]]]
24224           }
24225         }, {
24226           type: "Feature",
24227           properties: {
24228             iso1A2: "CD",
24229             iso1A3: "COD",
24230             iso1N3: "180",
24231             wikidata: "Q974",
24232             nameEn: "Democratic Republic of the Congo",
24233             aliases: ["ZR"],
24234             groups: ["017", "202", "002", "UN"],
24235             callingCodes: ["243"]
24236           },
24237           geometry: {
24238             type: "MultiPolygon",
24239             coordinates: [[[[27.44012, 5.07349], [27.09575, 5.22305], [26.93064, 5.13535], [26.85579, 5.03887], [26.74572, 5.10685], [26.48595, 5.04984], [26.13371, 5.25594], [25.86073, 5.19455], [25.53271, 5.37431], [25.34558, 5.29101], [25.31256, 5.03668], [24.71816, 4.90509], [24.46719, 5.0915], [23.38847, 4.60013], [22.94817, 4.82392], [22.89094, 4.79321], [22.84691, 4.69887], [22.78526, 4.71423], [22.6928, 4.47285], [22.60915, 4.48821], [22.5431, 4.22041], [22.45504, 4.13039], [22.27682, 4.11347], [22.10721, 4.20723], [21.6405, 4.317], [21.55904, 4.25553], [21.25744, 4.33676], [21.21341, 4.29285], [21.11214, 4.33895], [21.08793, 4.39603], [20.90383, 4.44877], [20.60184, 4.42394], [18.62755, 3.47564], [18.63857, 3.19342], [18.10683, 2.26876], [18.08034, 1.58553], [17.85887, 1.04327], [17.86989, 0.58873], [17.95255, 0.48128], [17.93877, 0.32424], [17.81204, 0.23884], [17.66051, -0.26535], [17.72112, -0.52707], [17.32438, -0.99265], [16.97999, -1.12762], [16.70724, -1.45815], [16.50336, -1.8795], [16.16173, -2.16586], [16.22785, -2.59528], [16.1755, -3.25014], [16.21407, -3.2969], [15.89448, -3.9513], [15.53081, -4.042], [15.48121, -4.22062], [15.41785, -4.28381], [15.32693, -4.27282], [15.25411, -4.31121], [15.1978, -4.32388], [14.83101, -4.80838], [14.67948, -4.92093], [14.5059, -4.84956], [14.41499, -4.8825], [14.37366, -4.56125], [14.47284, -4.42941], [14.3957, -4.36623], [14.40672, -4.28381], [13.9108, -4.50906], [13.81162, -4.41842], [13.71794, -4.44864], [13.70417, -4.72601], [13.50305, -4.77818], [13.41764, -4.89897], [13.11182, -4.5942], [13.09648, -4.63739], [13.11195, -4.67745], [12.8733, -4.74346], [12.70868, -4.95505], [12.63465, -4.94632], [12.60251, -5.01715], [12.46297, -5.09408], [12.49815, -5.14058], [12.51589, -5.1332], [12.53586, -5.14658], [12.53599, -5.1618], [12.52301, -5.17481], [12.52318, -5.74353], [12.26557, -5.74031], [12.20376, -5.76338], [11.95767, -5.94705], [12.42245, -6.07585], [13.04371, -5.87078], [16.55507, -5.85631], [16.96282, -7.21787], [17.5828, -8.13784], [18.33635, -8.00126], [19.33698, -7.99743], [19.5469, -7.00195], [20.30218, -6.98955], [20.31846, -6.91953], [20.61689, -6.90876], [20.56263, -7.28566], [21.79824, -7.29628], [21.84856, -9.59871], [22.19039, -9.94628], [22.32604, -10.76291], [22.17954, -10.85884], [22.25951, -11.24911], [22.54205, -11.05784], [23.16602, -11.10577], [23.45631, -10.946], [23.86868, -11.02856], [24.00027, -10.89356], [24.34528, -11.06816], [24.42612, -11.44975], [25.34069, -11.19707], [25.33058, -11.65767], [26.01777, -11.91488], [26.88687, -12.01868], [27.04351, -11.61312], [27.22541, -11.60323], [27.21025, -11.76157], [27.59932, -12.22123], [28.33199, -12.41375], [29.01918, -13.41353], [29.60531, -13.21685], [29.65078, -13.41844], [29.81551, -13.44683], [29.8139, -12.14898], [29.48404, -12.23604], [29.4992, -12.43843], [29.18592, -12.37921], [28.48357, -11.87532], [28.37241, -11.57848], [28.65032, -10.65133], [28.62795, -9.92942], [28.68532, -9.78], [28.56208, -9.49122], [28.51627, -9.44726], [28.52636, -9.35379], [28.36562, -9.30091], [28.38526, -9.23393], [28.9711, -8.66935], [28.88917, -8.4831], [30.79243, -8.27382], [30.2567, -7.14121], [29.52552, -6.2731], [29.43673, -4.44845], [29.23708, -3.75856], [29.21463, -3.3514], [29.25633, -3.05471], [29.17258, -2.99385], [29.16037, -2.95457], [29.09797, -2.91935], [29.09119, -2.87871], [29.0505, -2.81774], [29.00404, -2.81978], [29.00167, -2.78523], [29.04081, -2.7416], [29.00357, -2.70596], [28.94346, -2.69124], [28.89793, -2.66111], [28.90226, -2.62385], [28.89288, -2.55848], [28.87943, -2.55165], [28.86193, -2.53185], [28.86209, -2.5231], [28.87497, -2.50887], [28.88846, -2.50493], [28.89342, -2.49017], [28.89132, -2.47557], [28.86846, -2.44866], [28.86826, -2.41888], [28.89601, -2.37321], [28.95642, -2.37321], [29.00051, -2.29001], [29.105, -2.27043], [29.17562, -2.12278], [29.11847, -1.90576], [29.24458, -1.69663], [29.24323, -1.66826], [29.36322, -1.50887], [29.45038, -1.5054], [29.53062, -1.40499], [29.59061, -1.39016], [29.58388, -0.89821], [29.63006, -0.8997], [29.62708, -0.71055], [29.67176, -0.55714], [29.67474, -0.47969], [29.65091, -0.46777], [29.72687, -0.08051], [29.7224, 0.07291], [29.77454, 0.16675], [29.81922, 0.16824], [29.87284, 0.39166], [29.97413, 0.52124], [29.95477, 0.64486], [29.98307, 0.84295], [30.1484, 0.89805], [30.22139, 0.99635], [30.24671, 1.14974], [30.48503, 1.21675], [31.30127, 2.11006], [31.28042, 2.17853], [31.20148, 2.2217], [31.1985, 2.29462], [31.12104, 2.27676], [31.07934, 2.30207], [31.06593, 2.35862], [30.96911, 2.41071], [30.91102, 2.33332], [30.83059, 2.42559], [30.74271, 2.43601], [30.75612, 2.5863], [30.8857, 2.83923], [30.8574, 2.9508], [30.77101, 3.04897], [30.84251, 3.26908], [30.93486, 3.40737], [30.94081, 3.50847], [30.85153, 3.48867], [30.85997, 3.5743], [30.80713, 3.60506], [30.78512, 3.67097], [30.56277, 3.62703], [30.57378, 3.74567], [30.55396, 3.84451], [30.47691, 3.83353], [30.27658, 3.95653], [30.22374, 3.93896], [30.1621, 4.10586], [30.06964, 4.13221], [29.79666, 4.37809], [29.82087, 4.56246], [29.49726, 4.7007], [29.43341, 4.50101], [29.22207, 4.34297], [29.03054, 4.48784], [28.8126, 4.48784], [28.6651, 4.42638], [28.20719, 4.35614], [27.79551, 4.59976], [27.76469, 4.79284], [27.65462, 4.89375], [27.56656, 4.89375], [27.44012, 5.07349]]]]
24240           }
24241         }, {
24242           type: "Feature",
24243           properties: {
24244             iso1A2: "CF",
24245             iso1A3: "CAF",
24246             iso1N3: "140",
24247             wikidata: "Q929",
24248             nameEn: "Central African Republic",
24249             groups: ["017", "202", "002", "UN"],
24250             callingCodes: ["236"]
24251           },
24252           geometry: {
24253             type: "MultiPolygon",
24254             coordinates: [[[[22.87758, 10.91915], [22.45889, 11.00246], [21.72139, 10.64136], [21.71479, 10.29932], [21.63553, 10.217], [21.52766, 10.2105], [21.34934, 9.95907], [21.26348, 9.97642], [20.82979, 9.44696], [20.36748, 9.11019], [19.06421, 9.00367], [18.86388, 8.87971], [19.11044, 8.68172], [18.79783, 8.25929], [18.67455, 8.22226], [18.62612, 8.14163], [18.64153, 8.08714], [18.6085, 8.05009], [18.02731, 8.01085], [17.93926, 7.95853], [17.67288, 7.98905], [16.8143, 7.53971], [16.6668, 7.67281], [16.658, 7.75353], [16.59415, 7.76444], [16.58315, 7.88657], [16.41583, 7.77971], [16.40703, 7.68809], [15.79942, 7.44149], [15.73118, 7.52006], [15.49743, 7.52179], [15.23397, 7.25135], [15.04717, 6.77085], [14.96311, 6.75693], [14.79966, 6.39043], [14.80122, 6.34866], [14.74206, 6.26356], [14.56149, 6.18928], [14.43073, 6.08867], [14.42917, 6.00508], [14.49455, 5.91683], [14.60974, 5.91838], [14.62375, 5.70466], [14.58951, 5.59777], [14.62531, 5.51411], [14.52724, 5.28319], [14.57083, 5.23979], [14.65489, 5.21343], [14.73383, 4.6135], [15.00825, 4.41458], [15.08609, 4.30282], [15.10644, 4.1362], [15.17482, 4.05131], [15.07686, 4.01805], [15.73522, 3.24348], [15.77725, 3.26835], [16.05449, 3.02306], [16.08252, 2.45708], [16.19357, 2.21537], [16.50126, 2.84739], [16.46701, 2.92512], [16.57598, 3.47999], [16.68283, 3.54257], [17.01746, 3.55136], [17.35649, 3.63045], [17.46876, 3.70515], [17.60966, 3.63705], [17.83421, 3.61068], [17.85842, 3.53378], [18.05656, 3.56893], [18.14902, 3.54476], [18.17323, 3.47665], [18.24148, 3.50302], [18.2723, 3.57992], [18.39558, 3.58212], [18.49245, 3.63924], [18.58711, 3.49423], [18.62755, 3.47564], [20.60184, 4.42394], [20.90383, 4.44877], [21.08793, 4.39603], [21.11214, 4.33895], [21.21341, 4.29285], [21.25744, 4.33676], [21.55904, 4.25553], [21.6405, 4.317], [22.10721, 4.20723], [22.27682, 4.11347], [22.45504, 4.13039], [22.5431, 4.22041], [22.60915, 4.48821], [22.6928, 4.47285], [22.78526, 4.71423], [22.84691, 4.69887], [22.89094, 4.79321], [22.94817, 4.82392], [23.38847, 4.60013], [24.46719, 5.0915], [24.71816, 4.90509], [25.31256, 5.03668], [25.34558, 5.29101], [25.53271, 5.37431], [25.86073, 5.19455], [26.13371, 5.25594], [26.48595, 5.04984], [26.74572, 5.10685], [26.85579, 5.03887], [26.93064, 5.13535], [27.09575, 5.22305], [27.44012, 5.07349], [27.26886, 5.25876], [27.23017, 5.37167], [27.28621, 5.56382], [27.22705, 5.62889], [27.22705, 5.71254], [26.51721, 6.09655], [26.58259, 6.1987], [26.32729, 6.36272], [26.38022, 6.63493], [25.90076, 7.09549], [25.37461, 7.33024], [25.35281, 7.42595], [25.20337, 7.50312], [25.20649, 7.61115], [25.29214, 7.66675], [25.25319, 7.8487], [24.98855, 7.96588], [24.85156, 8.16933], [24.35965, 8.26177], [24.13238, 8.36959], [24.25691, 8.69288], [23.51905, 8.71749], [23.59065, 8.99743], [23.44744, 8.99128], [23.4848, 9.16959], [23.56263, 9.19418], [23.64358, 9.28637], [23.64981, 9.44303], [23.62179, 9.53823], [23.69155, 9.67566], [23.67164, 9.86923], [23.3128, 10.45214], [23.02221, 10.69235], [22.87758, 10.91915]]]]
24255           }
24256         }, {
24257           type: "Feature",
24258           properties: {
24259             iso1A2: "CG",
24260             iso1A3: "COG",
24261             iso1N3: "178",
24262             wikidata: "Q971",
24263             nameEn: "Republic of the Congo",
24264             groups: ["017", "202", "002", "UN"],
24265             callingCodes: ["242"]
24266           },
24267           geometry: {
24268             type: "MultiPolygon",
24269             coordinates: [[[[18.62755, 3.47564], [18.58711, 3.49423], [18.49245, 3.63924], [18.39558, 3.58212], [18.2723, 3.57992], [18.24148, 3.50302], [18.17323, 3.47665], [18.14902, 3.54476], [18.05656, 3.56893], [17.85842, 3.53378], [17.83421, 3.61068], [17.60966, 3.63705], [17.46876, 3.70515], [17.35649, 3.63045], [17.01746, 3.55136], [16.68283, 3.54257], [16.57598, 3.47999], [16.46701, 2.92512], [16.50126, 2.84739], [16.19357, 2.21537], [16.15568, 2.18955], [16.08563, 2.19733], [16.05294, 1.9811], [16.14634, 1.70259], [16.02647, 1.65591], [16.02959, 1.76483], [15.48942, 1.98265], [15.34776, 1.91264], [15.22634, 2.03243], [15.00996, 1.98887], [14.61145, 2.17866], [13.29457, 2.16106], [13.13461, 1.57238], [13.25447, 1.32339], [13.15519, 1.23368], [13.89582, 1.4261], [14.25186, 1.39842], [14.48179, 0.9152], [14.26066, 0.57255], [14.10909, 0.58563], [13.88648, 0.26652], [13.90632, -0.2287], [14.06862, -0.20826], [14.2165, -0.38261], [14.41887, -0.44799], [14.52569, -0.57818], [14.41838, -1.89412], [14.25932, -1.97624], [14.23518, -2.15671], [14.16202, -2.23916], [14.23829, -2.33715], [14.10442, -2.49268], [13.85846, -2.46935], [13.92073, -2.35581], [13.75884, -2.09293], [13.47977, -2.43224], [13.02759, -2.33098], [12.82172, -1.91091], [12.61312, -1.8129], [12.44656, -1.92025], [12.47925, -2.32626], [12.04895, -2.41704], [11.96866, -2.33559], [11.74605, -2.39936], [11.57637, -2.33379], [11.64487, -2.61865], [11.5359, -2.85654], [11.64798, -2.81146], [11.80365, -3.00424], [11.70558, -3.0773], [11.70227, -3.17465], [11.96554, -3.30267], [11.8318, -3.5812], [11.92719, -3.62768], [11.87083, -3.71571], [11.68608, -3.68942], [11.57949, -3.52798], [11.48764, -3.51089], [11.22301, -3.69888], [11.12647, -3.94169], [10.75913, -4.39519], [11.50888, -5.33417], [12.00924, -5.02627], [12.16068, -4.90089], [12.20901, -4.75642], [12.25587, -4.79437], [12.32324, -4.78415], [12.40964, -4.60609], [12.64835, -4.55937], [12.76844, -4.38709], [12.87096, -4.40315], [12.91489, -4.47907], [13.09648, -4.63739], [13.11182, -4.5942], [13.41764, -4.89897], [13.50305, -4.77818], [13.70417, -4.72601], [13.71794, -4.44864], [13.81162, -4.41842], [13.9108, -4.50906], [14.40672, -4.28381], [14.3957, -4.36623], [14.47284, -4.42941], [14.37366, -4.56125], [14.41499, -4.8825], [14.5059, -4.84956], [14.67948, -4.92093], [14.83101, -4.80838], [15.1978, -4.32388], [15.25411, -4.31121], [15.32693, -4.27282], [15.41785, -4.28381], [15.48121, -4.22062], [15.53081, -4.042], [15.89448, -3.9513], [16.21407, -3.2969], [16.1755, -3.25014], [16.22785, -2.59528], [16.16173, -2.16586], [16.50336, -1.8795], [16.70724, -1.45815], [16.97999, -1.12762], [17.32438, -0.99265], [17.72112, -0.52707], [17.66051, -0.26535], [17.81204, 0.23884], [17.93877, 0.32424], [17.95255, 0.48128], [17.86989, 0.58873], [17.85887, 1.04327], [18.08034, 1.58553], [18.10683, 2.26876], [18.63857, 3.19342], [18.62755, 3.47564]]]]
24270           }
24271         }, {
24272           type: "Feature",
24273           properties: {
24274             iso1A2: "CH",
24275             iso1A3: "CHE",
24276             iso1N3: "756",
24277             wikidata: "Q39",
24278             nameEn: "Switzerland",
24279             groups: ["155", "150", "UN"],
24280             callingCodes: ["41"]
24281           },
24282           geometry: {
24283             type: "MultiPolygon",
24284             coordinates: [[[[8.72809, 47.69282], [8.72617, 47.69651], [8.73671, 47.7169], [8.70543, 47.73121], [8.74251, 47.75168], [8.71778, 47.76571], [8.68985, 47.75686], [8.68022, 47.78599], [8.65292, 47.80066], [8.64425, 47.76398], [8.62408, 47.7626], [8.61657, 47.79998], [8.56415, 47.80633], [8.56814, 47.78001], [8.48868, 47.77215], [8.45771, 47.7493], [8.44807, 47.72426], [8.40569, 47.69855], [8.4211, 47.68407], [8.40473, 47.67499], [8.41346, 47.66676], [8.42264, 47.66667], [8.44711, 47.65379], [8.4667, 47.65747], [8.46605, 47.64103], [8.49656, 47.64709], [8.5322, 47.64687], [8.52801, 47.66059], [8.56141, 47.67088], [8.57683, 47.66158], [8.6052, 47.67258], [8.61113, 47.66332], [8.62884, 47.65098], [8.62049, 47.63757], [8.60412, 47.63735], [8.61471, 47.64514], [8.60701, 47.65271], [8.59545, 47.64298], [8.60348, 47.61204], [8.57586, 47.59537], [8.55756, 47.62394], [8.51686, 47.63476], [8.50747, 47.61897], [8.45578, 47.60121], [8.46637, 47.58389], [8.48949, 47.588], [8.49431, 47.58107], [8.43235, 47.56617], [8.39477, 47.57826], [8.38273, 47.56608], [8.32735, 47.57133], [8.30277, 47.58607], [8.29524, 47.5919], [8.29722, 47.60603], [8.2824, 47.61225], [8.26313, 47.6103], [8.25863, 47.61571], [8.23809, 47.61204], [8.22577, 47.60385], [8.22011, 47.6181], [8.20617, 47.62141], [8.19378, 47.61636], [8.1652, 47.5945], [8.14947, 47.59558], [8.13823, 47.59147], [8.13662, 47.58432], [8.11543, 47.5841], [8.10395, 47.57918], [8.10002, 47.56504], [8.08557, 47.55768], [8.06663, 47.56374], [8.04383, 47.55443], [8.02136, 47.55096], [8.00113, 47.55616], [7.97581, 47.55493], [7.95682, 47.55789], [7.94494, 47.54511], [7.91251, 47.55031], [7.90673, 47.57674], [7.88664, 47.58854], [7.84412, 47.5841], [7.81901, 47.58798], [7.79486, 47.55691], [7.75261, 47.54599], [7.71961, 47.54219], [7.69642, 47.53297], [7.68101, 47.53232], [7.6656, 47.53752], [7.66174, 47.54554], [7.65083, 47.54662], [7.63338, 47.56256], [7.67655, 47.56435], [7.68904, 47.57133], [7.67115, 47.5871], [7.68486, 47.59601], [7.69385, 47.60099], [7.68229, 47.59905], [7.67395, 47.59212], [7.64599, 47.59695], [7.64213, 47.5944], [7.64309, 47.59151], [7.61929, 47.57683], [7.60459, 47.57869], [7.60523, 47.58519], [7.58945, 47.59017], [7.58386, 47.57536], [7.56684, 47.57785], [7.56548, 47.57617], [7.55689, 47.57232], [7.55652, 47.56779], [7.53634, 47.55553], [7.52831, 47.55347], [7.51723, 47.54578], [7.50873, 47.54546], [7.49691, 47.53821], [7.50588, 47.52856], [7.51904, 47.53515], [7.53199, 47.5284], [7.5229, 47.51644], [7.49804, 47.51798], [7.51076, 47.49651], [7.47534, 47.47932], [7.43356, 47.49712], [7.42923, 47.48628], [7.4583, 47.47216], [7.4462, 47.46264], [7.43088, 47.45846], [7.40308, 47.43638], [7.35603, 47.43432], [7.33526, 47.44186], [7.24669, 47.4205], [7.17026, 47.44312], [7.19583, 47.49455], [7.16249, 47.49025], [7.12781, 47.50371], [7.07425, 47.48863], [7.0231, 47.50522], [6.98425, 47.49432], [7.0024, 47.45264], [6.93953, 47.43388], [6.93744, 47.40714], [6.88542, 47.37262], [6.87959, 47.35335], [7.03125, 47.36996], [7.0564, 47.35134], [7.05305, 47.33304], [6.94316, 47.28747], [6.95108, 47.26428], [6.9508, 47.24338], [6.8489, 47.15933], [6.76788, 47.1208], [6.68823, 47.06616], [6.71531, 47.0494], [6.43341, 46.92703], [6.46456, 46.88865], [6.43216, 46.80336], [6.45209, 46.77502], [6.38351, 46.73171], [6.27135, 46.68251], [6.11084, 46.57649], [6.1567, 46.54402], [6.07269, 46.46244], [6.08427, 46.44305], [6.06407, 46.41676], [6.09926, 46.40768], [6.15016, 46.3778], [6.15985, 46.37721], [6.16987, 46.36759], [6.15738, 46.3491], [6.13876, 46.33844], [6.1198, 46.31157], [6.11697, 46.29547], [6.1013, 46.28512], [6.11926, 46.2634], [6.12446, 46.25059], [6.10071, 46.23772], [6.08563, 46.24651], [6.07072, 46.24085], [6.0633, 46.24583], [6.05029, 46.23518], [6.04602, 46.23127], [6.03342, 46.2383], [6.02461, 46.23313], [5.97542, 46.21525], [5.96515, 46.19638], [5.99573, 46.18587], [5.98846, 46.17046], [5.98188, 46.17392], [5.97508, 46.15863], [5.9641, 46.14412], [5.95781, 46.12925], [5.97893, 46.13303], [5.9871, 46.14499], [6.01791, 46.14228], [6.03614, 46.13712], [6.04564, 46.14031], [6.05203, 46.15191], [6.07491, 46.14879], [6.09199, 46.15191], [6.09926, 46.14373], [6.13397, 46.1406], [6.15305, 46.15194], [6.18116, 46.16187], [6.18871, 46.16644], [6.18707, 46.17999], [6.19552, 46.18401], [6.19807, 46.18369], [6.20539, 46.19163], [6.21114, 46.1927], [6.21273, 46.19409], [6.21603, 46.19507], [6.21844, 46.19837], [6.22222, 46.19888], [6.22175, 46.20045], [6.23544, 46.20714], [6.23913, 46.20511], [6.24821, 46.20531], [6.26007, 46.21165], [6.27694, 46.21566], [6.29663, 46.22688], [6.31041, 46.24417], [6.29474, 46.26221], [6.26749, 46.24745], [6.24952, 46.26255], [6.23775, 46.27822], [6.25137, 46.29014], [6.24826, 46.30175], [6.21981, 46.31304], [6.25432, 46.3632], [6.53358, 46.45431], [6.82312, 46.42661], [6.8024, 46.39171], [6.77152, 46.34784], [6.86052, 46.28512], [6.78968, 46.14058], [6.89321, 46.12548], [6.87868, 46.03855], [6.93862, 46.06502], [7.00946, 45.9944], [7.04151, 45.92435], [7.10685, 45.85653], [7.56343, 45.97421], [7.85949, 45.91485], [7.9049, 45.99945], [7.98881, 45.99867], [8.02906, 46.10331], [8.11383, 46.11577], [8.16866, 46.17817], [8.08814, 46.26692], [8.31162, 46.38044], [8.30648, 46.41587], [8.42464, 46.46367], [8.46317, 46.43712], [8.45032, 46.26869], [8.62242, 46.12112], [8.75697, 46.10395], [8.80778, 46.10085], [8.85617, 46.0748], [8.79414, 46.00913], [8.78585, 45.98973], [8.79362, 45.99207], [8.8319, 45.9879], [8.85121, 45.97239], [8.86688, 45.96135], [8.88904, 45.95465], [8.93649, 45.86775], [8.94372, 45.86587], [8.93504, 45.86245], [8.91129, 45.8388], [8.94737, 45.84285], [8.9621, 45.83707], [8.99663, 45.83466], [9.00324, 45.82055], [9.0298, 45.82127], [9.03279, 45.82865], [9.03793, 45.83548], [9.03505, 45.83976], [9.04059, 45.8464], [9.04546, 45.84968], [9.06642, 45.8761], [9.09065, 45.89906], [8.99257, 45.9698], [9.01618, 46.04928], [9.24503, 46.23616], [9.29226, 46.32717], [9.25502, 46.43743], [9.28136, 46.49685], [9.36128, 46.5081], [9.40487, 46.46621], [9.45936, 46.50873], [9.46117, 46.37481], [9.57015, 46.2958], [9.71273, 46.29266], [9.73086, 46.35071], [9.95249, 46.38045], [10.07055, 46.21668], [10.14439, 46.22992], [10.17862, 46.25626], [10.10506, 46.3372], [10.165, 46.41051], [10.03715, 46.44479], [10.10307, 46.61003], [10.23674, 46.63484], [10.25309, 46.57432], [10.46136, 46.53164], [10.49375, 46.62049], [10.44686, 46.64162], [10.40475, 46.63671], [10.38659, 46.67847], [10.47197, 46.85698], [10.48376, 46.93891], [10.36933, 47.00212], [10.30031, 46.92093], [10.24128, 46.93147], [10.22675, 46.86942], [10.10715, 46.84296], [9.98058, 46.91434], [9.88266, 46.93343], [9.87935, 47.01337], [9.60717, 47.06091], [9.55721, 47.04762], [9.54041, 47.06495], [9.47548, 47.05257], [9.47139, 47.06402], [9.51362, 47.08505], [9.52089, 47.10019], [9.51044, 47.13727], [9.48774, 47.17402], [9.4891, 47.19346], [9.50318, 47.22153], [9.52406, 47.24959], [9.53116, 47.27029], [9.54773, 47.2809], [9.55857, 47.29919], [9.58513, 47.31334], [9.59978, 47.34671], [9.62476, 47.36639], [9.65427, 47.36824], [9.66243, 47.37136], [9.6711, 47.37824], [9.67445, 47.38429], [9.67334, 47.39191], [9.6629, 47.39591], [9.65136, 47.40504], [9.65043, 47.41937], [9.6446, 47.43233], [9.64483, 47.43842], [9.65863, 47.44847], [9.65728, 47.45383], [9.6423, 47.45599], [9.62475, 47.45685], [9.62158, 47.45858], [9.60841, 47.47178], [9.60484, 47.46358], [9.60205, 47.46165], [9.59482, 47.46305], [9.58208, 47.48344], [9.56312, 47.49495], [9.55125, 47.53629], [9.25619, 47.65939], [9.18203, 47.65598], [9.17593, 47.65399], [9.1755, 47.65584], [9.1705, 47.65513], [9.15181, 47.66904], [9.13845, 47.66389], [9.09891, 47.67801], [9.02093, 47.6868], [8.94093, 47.65596], [8.89946, 47.64769], [8.87625, 47.65441], [8.87383, 47.67045], [8.85065, 47.68209], [8.86989, 47.70504], [8.82002, 47.71458], [8.80663, 47.73821], [8.77309, 47.72059], [8.76965, 47.7075], [8.79966, 47.70222], [8.79511, 47.67462], [8.75856, 47.68969], [8.72809, 47.69282]], [[8.95861, 45.96485], [8.96668, 45.98436], [8.97741, 45.98317], [8.97604, 45.96151], [8.95861, 45.96485]], [[8.70847, 47.68904], [8.68985, 47.69552], [8.66837, 47.68437], [8.65769, 47.68928], [8.67508, 47.6979], [8.66416, 47.71367], [8.70237, 47.71453], [8.71773, 47.69088], [8.70847, 47.68904]]]]
24285           }
24286         }, {
24287           type: "Feature",
24288           properties: {
24289             iso1A2: "CI",
24290             iso1A3: "CIV",
24291             iso1N3: "384",
24292             wikidata: "Q1008",
24293             nameEn: "C\xF4te d'Ivoire",
24294             groups: ["011", "202", "002", "UN"],
24295             callingCodes: ["225"]
24296           },
24297           geometry: {
24298             type: "MultiPolygon",
24299             coordinates: [[[[-7.52774, 3.7105], [-3.34019, 4.17519], [-3.10675, 5.08515], [-3.11073, 5.12675], [-3.063, 5.13665], [-2.96554, 5.10397], [-2.95261, 5.12477], [-2.75502, 5.10657], [-2.73074, 5.1364], [-2.77625, 5.34621], [-2.72737, 5.34789], [-2.76614, 5.60963], [-2.85378, 5.65156], [-2.93132, 5.62137], [-2.96671, 5.6415], [-2.95323, 5.71865], [-3.01896, 5.71697], [-3.25999, 6.62521], [-3.21954, 6.74407], [-3.23327, 6.81744], [-2.95438, 7.23737], [-2.97822, 7.27165], [-2.92339, 7.60847], [-2.79467, 7.86002], [-2.78395, 7.94974], [-2.74819, 7.92613], [-2.67787, 8.02055], [-2.61232, 8.02645], [-2.62901, 8.11495], [-2.49037, 8.20872], [-2.58243, 8.7789], [-2.66357, 9.01771], [-2.77799, 9.04949], [-2.69814, 9.22717], [-2.68802, 9.49343], [-2.76494, 9.40778], [-2.93012, 9.57403], [-3.00765, 9.74019], [-3.16609, 9.85147], [-3.19306, 9.93781], [-3.27228, 9.84981], [-3.31779, 9.91125], [-3.69703, 9.94279], [-4.25999, 9.76012], [-4.31392, 9.60062], [-4.6426, 9.70696], [-4.96621, 9.89132], [-4.96453, 9.99923], [-5.12465, 10.29788], [-5.39602, 10.2929], [-5.51058, 10.43177], [-5.65135, 10.46767], [-5.78124, 10.43952], [-5.99478, 10.19694], [-6.18851, 10.24244], [-6.1731, 10.46983], [-6.24795, 10.74248], [-6.325, 10.68624], [-6.40646, 10.69922], [-6.42847, 10.5694], [-6.52974, 10.59104], [-6.63541, 10.66893], [-6.68164, 10.35074], [-6.93921, 10.35291], [-7.01186, 10.25111], [-6.97444, 10.21644], [-7.00966, 10.15794], [-7.0603, 10.14711], [-7.13331, 10.24877], [-7.3707, 10.24677], [-7.44555, 10.44602], [-7.52261, 10.4655], [-7.54462, 10.40921], [-7.63048, 10.46334], [-7.92107, 10.15577], [-7.97971, 10.17117], [-8.01225, 10.1021], [-8.11921, 10.04577], [-8.15652, 9.94288], [-8.09434, 9.86936], [-8.14657, 9.55062], [-8.03463, 9.39604], [-7.85056, 9.41812], [-7.90777, 9.20456], [-7.73862, 9.08422], [-7.92518, 8.99332], [-7.95503, 8.81146], [-7.69882, 8.66148], [-7.65653, 8.36873], [-7.92518, 8.50652], [-8.22991, 8.48438], [-8.2411, 8.24196], [-8.062, 8.16071], [-7.98675, 8.20134], [-7.99919, 8.11023], [-7.94695, 8.00925], [-8.06449, 8.04989], [-8.13414, 7.87991], [-8.09931, 7.78626], [-8.21374, 7.54466], [-8.4003, 7.6285], [-8.47114, 7.55676], [-8.41935, 7.51203], [-8.37458, 7.25794], [-8.29249, 7.1691], [-8.31736, 6.82837], [-8.59456, 6.50612], [-8.48652, 6.43797], [-8.45666, 6.49977], [-8.38453, 6.35887], [-8.3298, 6.36381], [-8.17557, 6.28222], [-8.00642, 6.31684], [-7.90692, 6.27728], [-7.83478, 6.20309], [-7.8497, 6.08932], [-7.79747, 6.07696], [-7.78254, 5.99037], [-7.70294, 5.90625], [-7.67309, 5.94337], [-7.48155, 5.80974], [-7.46165, 5.84934], [-7.43677, 5.84687], [-7.43926, 5.74787], [-7.37209, 5.61173], [-7.43428, 5.42355], [-7.36463, 5.32944], [-7.46165, 5.26256], [-7.48901, 5.14118], [-7.55369, 5.08667], [-7.53876, 4.94294], [-7.59349, 4.8909], [-7.53259, 4.35145], [-7.52774, 3.7105]]]]
24300           }
24301         }, {
24302           type: "Feature",
24303           properties: {
24304             iso1A2: "CK",
24305             iso1A3: "COK",
24306             iso1N3: "184",
24307             wikidata: "Q26988",
24308             nameEn: "Cook Islands",
24309             country: "NZ",
24310             groups: ["061", "009", "UN"],
24311             driveSide: "left",
24312             callingCodes: ["682"]
24313           },
24314           geometry: {
24315             type: "MultiPolygon",
24316             coordinates: [[[[-168.15106, -10.26955], [-156.45576, -31.75456], [-156.48634, -15.52824], [-156.50903, -7.4975], [-168.15106, -10.26955]]]]
24317           }
24318         }, {
24319           type: "Feature",
24320           properties: {
24321             iso1A2: "CL",
24322             iso1A3: "CHL",
24323             iso1N3: "152",
24324             wikidata: "Q298",
24325             nameEn: "Chile",
24326             groups: ["005", "419", "019", "UN"],
24327             callingCodes: ["56"]
24328           },
24329           geometry: {
24330             type: "MultiPolygon",
24331             coordinates: [[[[-68.60702, -52.65781], [-68.41683, -52.33516], [-69.97824, -52.00845], [-71.99889, -51.98018], [-72.33873, -51.59954], [-72.31343, -50.58411], [-73.15765, -50.78337], [-73.55259, -49.92488], [-73.45156, -49.79461], [-73.09655, -49.14342], [-72.56894, -48.81116], [-72.54042, -48.52392], [-72.27662, -48.28727], [-72.50478, -47.80586], [-71.94152, -47.13595], [-71.68577, -46.55385], [-71.75614, -45.61611], [-71.35687, -45.22075], [-72.06985, -44.81756], [-71.26418, -44.75684], [-71.16436, -44.46244], [-71.81318, -44.38097], [-71.64206, -43.64774], [-72.14828, -42.85321], [-72.15541, -42.15941], [-71.74901, -42.11711], [-71.92726, -40.72714], [-71.37826, -38.91474], [-70.89532, -38.6923], [-71.24279, -37.20264], [-70.95047, -36.4321], [-70.38008, -36.02375], [-70.49416, -35.24145], [-69.87386, -34.13344], [-69.88099, -33.34489], [-70.55832, -31.51559], [-70.14479, -30.36595], [-69.8596, -30.26131], [-69.99507, -29.28351], [-69.80969, -29.07185], [-69.66709, -28.44055], [-69.22504, -27.95042], [-68.77586, -27.16029], [-68.43363, -27.08414], [-68.27677, -26.90626], [-68.59048, -26.49861], [-68.56909, -26.28146], [-68.38372, -26.15353], [-68.57622, -25.32505], [-68.38372, -25.08636], [-68.56909, -24.69831], [-68.24825, -24.42596], [-67.33563, -24.04237], [-66.99632, -22.99839], [-67.18382, -22.81525], [-67.54284, -22.89771], [-67.85114, -22.87076], [-68.18816, -21.28614], [-68.40403, -20.94562], [-68.53957, -20.91542], [-68.55383, -20.7355], [-68.44023, -20.62701], [-68.7276, -20.46178], [-68.74273, -20.08817], [-68.57132, -20.03134], [-68.54611, -19.84651], [-68.66761, -19.72118], [-68.41218, -19.40499], [-68.61989, -19.27584], [-68.80602, -19.08355], [-68.87082, -19.06003], [-68.94987, -18.93302], [-69.07432, -18.28259], [-69.14807, -18.16893], [-69.07496, -18.03715], [-69.28671, -17.94844], [-69.34126, -17.72753], [-69.46623, -17.60518], [-69.46897, -17.4988], [-69.66483, -17.65083], [-69.79087, -17.65563], [-69.82868, -17.72048], [-69.75305, -17.94605], [-69.81607, -18.12582], [-69.96732, -18.25992], [-70.16394, -18.31737], [-70.31267, -18.31258], [-70.378, -18.3495], [-70.59118, -18.35072], [-113.52687, -26.52828], [-68.11646, -58.14883], [-66.07313, -55.19618], [-67.11046, -54.94199], [-67.46182, -54.92205], [-68.01394, -54.8753], [-68.60733, -54.9125], [-68.60702, -52.65781]]]]
24332           }
24333         }, {
24334           type: "Feature",
24335           properties: {
24336             iso1A2: "CM",
24337             iso1A3: "CMR",
24338             iso1N3: "120",
24339             wikidata: "Q1009",
24340             nameEn: "Cameroon",
24341             groups: ["017", "202", "002", "UN"],
24342             callingCodes: ["237"]
24343           },
24344           geometry: {
24345             type: "MultiPolygon",
24346             coordinates: [[[[14.83314, 12.62963], [14.55058, 12.78256], [14.56101, 12.91036], [14.46881, 13.08259], [14.08251, 13.0797], [14.20204, 12.53405], [14.17523, 12.41916], [14.22215, 12.36533], [14.4843, 12.35223], [14.6474, 12.17466], [14.61612, 11.7798], [14.55207, 11.72001], [14.64591, 11.66166], [14.6124, 11.51283], [14.17821, 11.23831], [13.97489, 11.30258], [13.78945, 11.00154], [13.7403, 11.00593], [13.70753, 10.94451], [13.73434, 10.9255], [13.54964, 10.61236], [13.5705, 10.53183], [13.43644, 10.13326], [13.34111, 10.12299], [13.25025, 10.03647], [13.25323, 10.00127], [13.286, 9.9822], [13.27409, 9.93232], [13.24132, 9.91031], [13.25025, 9.86042], [13.29941, 9.8296], [13.25472, 9.76795], [13.22642, 9.57266], [13.02385, 9.49334], [12.85628, 9.36698], [12.91958, 9.33905], [12.90022, 9.11411], [12.81085, 8.91992], [12.79, 8.75361], [12.71701, 8.7595], [12.68722, 8.65938], [12.44146, 8.6152], [12.4489, 8.52536], [12.26123, 8.43696], [12.24782, 8.17904], [12.19271, 8.10826], [12.20909, 7.97553], [11.99908, 7.67302], [12.01844, 7.52981], [11.93205, 7.47812], [11.84864, 7.26098], [11.87396, 7.09398], [11.63117, 6.9905], [11.55818, 6.86186], [11.57755, 6.74059], [11.51499, 6.60892], [11.42264, 6.5882], [11.42041, 6.53789], [11.09495, 6.51717], [11.09644, 6.68437], [10.94302, 6.69325], [10.8179, 6.83377], [10.83727, 6.9358], [10.60789, 7.06885], [10.59746, 7.14719], [10.57214, 7.16345], [10.53639, 6.93432], [10.21466, 6.88996], [10.15135, 7.03781], [9.86314, 6.77756], [9.77824, 6.79088], [9.70674, 6.51717], [9.51757, 6.43874], [8.84209, 5.82562], [8.88156, 5.78857], [8.83687, 5.68483], [8.92029, 5.58403], [8.78027, 5.1243], [8.60302, 4.87353], [8.34397, 4.30689], [9.22018, 3.72052], [9.81162, 2.33797], [9.82123, 2.35097], [9.83754, 2.32428], [9.83238, 2.29079], [9.84716, 2.24676], [9.89012, 2.20457], [9.90749, 2.20049], [9.991, 2.16561], [11.3561, 2.17217], [11.37116, 2.29975], [13.28534, 2.25716], [13.29457, 2.16106], [14.61145, 2.17866], [15.00996, 1.98887], [15.22634, 2.03243], [15.34776, 1.91264], [15.48942, 1.98265], [16.02959, 1.76483], [16.02647, 1.65591], [16.14634, 1.70259], [16.05294, 1.9811], [16.08563, 2.19733], [16.15568, 2.18955], [16.19357, 2.21537], [16.08252, 2.45708], [16.05449, 3.02306], [15.77725, 3.26835], [15.73522, 3.24348], [15.07686, 4.01805], [15.17482, 4.05131], [15.10644, 4.1362], [15.08609, 4.30282], [15.00825, 4.41458], [14.73383, 4.6135], [14.65489, 5.21343], [14.57083, 5.23979], [14.52724, 5.28319], [14.62531, 5.51411], [14.58951, 5.59777], [14.62375, 5.70466], [14.60974, 5.91838], [14.49455, 5.91683], [14.42917, 6.00508], [14.43073, 6.08867], [14.56149, 6.18928], [14.74206, 6.26356], [14.80122, 6.34866], [14.79966, 6.39043], [14.96311, 6.75693], [15.04717, 6.77085], [15.23397, 7.25135], [15.49743, 7.52179], [15.56964, 7.58936], [15.59272, 7.7696], [15.50743, 7.79302], [15.20426, 8.50892], [15.09484, 8.65982], [14.83566, 8.80557], [14.35707, 9.19611], [14.37094, 9.2954], [13.97544, 9.6365], [14.01793, 9.73169], [14.1317, 9.82413], [14.20411, 10.00055], [14.4673, 10.00264], [14.80082, 9.93818], [14.95722, 9.97926], [15.05999, 9.94845], [15.14043, 9.99246], [15.24618, 9.99246], [15.41408, 9.92876], [15.68761, 9.99344], [15.50535, 10.1098], [15.30874, 10.31063], [15.23724, 10.47764], [15.14936, 10.53915], [15.15532, 10.62846], [15.06737, 10.80921], [15.09127, 10.87431], [15.04957, 11.02347], [15.10021, 11.04101], [15.0585, 11.40481], [15.13149, 11.5537], [15.06595, 11.71126], [15.11579, 11.79313], [15.04808, 11.8731], [15.05786, 12.0608], [15.0349, 12.10698], [15.00146, 12.1223], [14.96952, 12.0925], [14.89019, 12.16593], [14.90827, 12.3269], [14.83314, 12.62963]]]]
24347           }
24348         }, {
24349           type: "Feature",
24350           properties: {
24351             iso1A2: "CN",
24352             iso1A3: "CHN",
24353             iso1N3: "156",
24354             wikidata: "Q148",
24355             nameEn: "People's Republic of China"
24356           },
24357           geometry: null
24358         }, {
24359           type: "Feature",
24360           properties: {
24361             iso1A2: "CO",
24362             iso1A3: "COL",
24363             iso1N3: "170",
24364             wikidata: "Q739",
24365             nameEn: "Colombia",
24366             groups: ["005", "419", "019", "UN"],
24367             callingCodes: ["57"]
24368           },
24369           geometry: {
24370             type: "MultiPolygon",
24371             coordinates: [[[[-71.19849, 12.65801], [-81.58685, 18.0025], [-82.06974, 14.49418], [-82.56142, 11.91792], [-78.79327, 9.93766], [-77.58292, 9.22278], [-77.32389, 8.81247], [-77.45064, 8.49991], [-77.17257, 7.97422], [-77.57185, 7.51147], [-77.72514, 7.72348], [-77.72157, 7.47612], [-77.81426, 7.48319], [-77.89178, 7.22681], [-78.06168, 7.07793], [-82.12561, 4.00341], [-78.87137, 1.47457], [-78.42749, 1.15389], [-77.85677, 0.80197], [-77.7148, 0.85003], [-77.68613, 0.83029], [-77.66416, 0.81604], [-77.67815, 0.73863], [-77.49984, 0.64476], [-77.52001, 0.40782], [-76.89177, 0.24736], [-76.4094, 0.24015], [-76.41215, 0.38228], [-76.23441, 0.42294], [-75.82927, 0.09578], [-75.25764, -0.11943], [-75.18513, -0.0308], [-74.42701, -0.50218], [-74.26675, -0.97229], [-73.65312, -1.26222], [-72.92587, -2.44514], [-71.75223, -2.15058], [-70.94377, -2.23142], [-70.04609, -2.73906], [-70.71396, -3.7921], [-70.52393, -3.87553], [-70.3374, -3.79505], [-69.94708, -4.2431], [-69.43395, -1.42219], [-69.4215, -1.01853], [-69.59796, -0.75136], [-69.603, -0.51947], [-70.03658, -0.19681], [-70.04162, 0.55437], [-69.47696, 0.71065], [-69.20976, 0.57958], [-69.14422, 0.84172], [-69.26017, 1.06856], [-69.82987, 1.07864], [-69.83491, 1.69353], [-69.53746, 1.76408], [-69.38621, 1.70865], [-68.18128, 1.72881], [-68.26699, 1.83463], [-68.18632, 2.00091], [-67.9292, 1.82455], [-67.40488, 2.22258], [-67.299, 1.87494], [-67.15784, 1.80439], [-67.08222, 1.17441], [-66.85795, 1.22998], [-67.21967, 2.35778], [-67.65696, 2.81691], [-67.85862, 2.79173], [-67.85862, 2.86727], [-67.30945, 3.38393], [-67.50067, 3.75812], [-67.62671, 3.74303], [-67.85358, 4.53249], [-67.83341, 5.31104], [-67.59141, 5.5369], [-67.63914, 5.64963], [-67.58558, 5.84537], [-67.43513, 5.98835], [-67.4625, 6.20625], [-67.60654, 6.2891], [-69.41843, 6.1072], [-70.10716, 6.96516], [-70.7596, 7.09799], [-71.03941, 6.98163], [-71.37234, 7.01588], [-71.42212, 7.03854], [-71.44118, 7.02116], [-71.82441, 7.04314], [-72.04895, 7.03837], [-72.19437, 7.37034], [-72.43132, 7.40034], [-72.47415, 7.48928], [-72.45321, 7.57232], [-72.47827, 7.65604], [-72.46763, 7.79518], [-72.44454, 7.86031], [-72.46183, 7.90682], [-72.45806, 7.91141], [-72.47042, 7.92306], [-72.48183, 7.92909], [-72.48801, 7.94329], [-72.47213, 7.96106], [-72.39137, 8.03534], [-72.35163, 8.01163], [-72.36987, 8.19976], [-72.4042, 8.36513], [-72.65474, 8.61428], [-72.77415, 9.10165], [-72.94052, 9.10663], [-73.02119, 9.27584], [-73.36905, 9.16636], [-72.98085, 9.85253], [-72.88002, 10.44309], [-72.4767, 11.1117], [-72.24983, 11.14138], [-71.9675, 11.65536], [-71.3275, 11.85], [-70.92579, 11.96275], [-71.19849, 12.65801]]]]
24372           }
24373         }, {
24374           type: "Feature",
24375           properties: {
24376             iso1A2: "CP",
24377             iso1A3: "CPT",
24378             wikidata: "Q161258",
24379             nameEn: "Clipperton Island",
24380             country: "FR",
24381             groups: ["013", "003", "019", "UN"],
24382             isoStatus: "excRes"
24383           },
24384           geometry: {
24385             type: "MultiPolygon",
24386             coordinates: [[[[-110.36279, 9.79626], [-108.755, 9.84085], [-109.04145, 11.13245], [-110.36279, 9.79626]]]]
24387           }
24388         }, {
24389           type: "Feature",
24390           properties: {
24391             iso1A2: "CR",
24392             iso1A3: "CRI",
24393             iso1N3: "188",
24394             wikidata: "Q800",
24395             nameEn: "Costa Rica",
24396             groups: ["013", "003", "419", "019", "UN"],
24397             callingCodes: ["506"]
24398           },
24399           geometry: {
24400             type: "MultiPolygon",
24401             coordinates: [[[[-83.68276, 11.01562], [-83.66597, 10.79916], [-83.90838, 10.71161], [-84.68197, 11.07568], [-84.92439, 10.9497], [-85.60529, 11.22607], [-85.71223, 11.06868], [-86.14524, 11.09059], [-87.41779, 5.02401], [-82.94503, 7.93865], [-82.89978, 8.04083], [-82.89137, 8.05755], [-82.88641, 8.10219], [-82.9388, 8.26634], [-83.05209, 8.33394], [-82.93056, 8.43465], [-82.8679, 8.44042], [-82.8382, 8.48117], [-82.83322, 8.52464], [-82.83975, 8.54755], [-82.82739, 8.60153], [-82.8794, 8.6981], [-82.92068, 8.74832], [-82.91377, 8.774], [-82.88253, 8.83331], [-82.72126, 8.97125], [-82.93516, 9.07687], [-82.93516, 9.46741], [-82.84871, 9.4973], [-82.87919, 9.62645], [-82.77206, 9.59573], [-82.66667, 9.49746], [-82.61345, 9.49881], [-82.56507, 9.57279], [-82.51044, 9.65379], [-83.54024, 10.96805], [-83.68276, 11.01562]]]]
24402           }
24403         }, {
24404           type: "Feature",
24405           properties: {
24406             iso1A2: "CU",
24407             iso1A3: "CUB",
24408             iso1N3: "192",
24409             wikidata: "Q241",
24410             nameEn: "Cuba",
24411             groups: ["029", "003", "419", "019", "UN"],
24412             callingCodes: ["53"]
24413           },
24414           geometry: {
24415             type: "MultiPolygon",
24416             coordinates: [[[[-73.62304, 20.6935], [-82.02215, 24.23074], [-85.77883, 21.92705], [-74.81171, 18.82201], [-73.62304, 20.6935]]]]
24417           }
24418         }, {
24419           type: "Feature",
24420           properties: {
24421             iso1A2: "CV",
24422             iso1A3: "CPV",
24423             iso1N3: "132",
24424             wikidata: "Q1011",
24425             nameEn: "Cape Verde",
24426             groups: ["Q105472", "011", "202", "002", "UN"],
24427             callingCodes: ["238"]
24428           },
24429           geometry: {
24430             type: "MultiPolygon",
24431             coordinates: [[[[-28.81604, 14.57305], [-20.39702, 14.12816], [-23.37101, 19.134], [-28.81604, 14.57305]]]]
24432           }
24433         }, {
24434           type: "Feature",
24435           properties: {
24436             iso1A2: "CW",
24437             iso1A3: "CUW",
24438             iso1N3: "531",
24439             wikidata: "Q25279",
24440             nameEn: "Cura\xE7ao",
24441             aliases: ["NL-CW"],
24442             country: "NL",
24443             groups: ["Q1451600", "029", "003", "419", "019", "UN"],
24444             callingCodes: ["599"]
24445           },
24446           geometry: {
24447             type: "MultiPolygon",
24448             coordinates: [[[[-68.90012, 12.62309], [-69.59009, 12.46019], [-68.99639, 11.79035], [-68.33524, 11.78151], [-68.90012, 12.62309]]]]
24449           }
24450         }, {
24451           type: "Feature",
24452           properties: {
24453             iso1A2: "CX",
24454             iso1A3: "CXR",
24455             iso1N3: "162",
24456             wikidata: "Q31063",
24457             nameEn: "Christmas Island",
24458             country: "AU",
24459             groups: ["053", "009", "UN"],
24460             driveSide: "left",
24461             callingCodes: ["61"]
24462           },
24463           geometry: {
24464             type: "MultiPolygon",
24465             coordinates: [[[[105.66835, -9.31927], [104.67494, -11.2566], [106.66176, -11.14349], [105.66835, -9.31927]]]]
24466           }
24467         }, {
24468           type: "Feature",
24469           properties: {
24470             iso1A2: "CY",
24471             iso1A3: "CYP",
24472             iso1N3: "196",
24473             wikidata: "Q229",
24474             nameEn: "Republic of Cyprus",
24475             groups: ["Q644636", "EU", "145", "142", "UN"],
24476             driveSide: "left",
24477             callingCodes: ["357"]
24478           },
24479           geometry: {
24480             type: "MultiPolygon",
24481             coordinates: [[[[32.46489, 35.48584], [30.15137, 34.08517], [32.74412, 34.43926], [32.75515, 34.64985], [32.76136, 34.68318], [32.79433, 34.67883], [32.82717, 34.70622], [32.86014, 34.70585], [32.86167, 34.68734], [32.9068, 34.66102], [32.91398, 34.67343], [32.93043, 34.67091], [32.92807, 34.66736], [32.93449, 34.66241], [32.93693, 34.67027], [32.94379, 34.67111], [32.94683, 34.67907], [32.95539, 34.68471], [32.99135, 34.68061], [32.98668, 34.67268], [32.99014, 34.65518], [32.97736, 34.65277], [32.97079, 34.66112], [32.95325, 34.66462], [32.94796, 34.6587], [32.94976, 34.65204], [32.95471, 34.64528], [32.95323, 34.64075], [32.95891, 34.62919], [32.96718, 34.63446], [32.96968, 34.64046], [33.0138, 34.64424], [33.26744, 34.49942], [33.83531, 34.73974], [33.70575, 34.97947], [33.70639, 34.99303], [33.71514, 35.00294], [33.69731, 35.01754], [33.69938, 35.03123], [33.67678, 35.03866], [33.63765, 35.03869], [33.61215, 35.0527], [33.59658, 35.03635], [33.567, 35.04803], [33.57478, 35.06049], [33.53975, 35.08151], [33.48915, 35.06594], [33.47666, 35.00701], [33.45256, 35.00288], [33.45178, 35.02078], [33.47825, 35.04103], [33.48136, 35.0636], [33.46813, 35.10564], [33.41675, 35.16325], [33.4076, 35.20062], [33.38575, 35.2018], [33.37248, 35.18698], [33.3717, 35.1788], [33.36569, 35.17479], [33.35612, 35.17402], [33.35596, 35.17942], [33.34964, 35.17803], [33.35056, 35.18328], [33.31955, 35.18096], [33.3072, 35.16816], [33.27068, 35.16815], [33.15138, 35.19504], [33.11105, 35.15639], [33.08249, 35.17319], [33.01192, 35.15639], [32.94471, 35.09422], [32.86406, 35.1043], [32.85733, 35.07742], [32.70779, 35.14127], [32.70947, 35.18328], [32.64864, 35.19967], [32.60361, 35.16647], [32.46489, 35.48584]]], [[[33.74144, 35.01053], [33.7492, 35.01319], [33.74983, 35.02274], [33.74265, 35.02329], [33.73781, 35.02181], [33.7343, 35.01178], [33.74144, 35.01053]]], [[[33.77312, 34.9976], [33.75994, 35.00113], [33.75682, 34.99916], [33.76605, 34.99543], [33.76738, 34.99188], [33.7778, 34.98981], [33.77843, 34.988], [33.78149, 34.98854], [33.78318, 34.98699], [33.78571, 34.98951], [33.78917, 34.98854], [33.79191, 34.98914], [33.78516, 34.99582], [33.77553, 34.99518], [33.77312, 34.9976]]]]
24482           }
24483         }, {
24484           type: "Feature",
24485           properties: {
24486             iso1A2: "CZ",
24487             iso1A3: "CZE",
24488             iso1N3: "203",
24489             wikidata: "Q213",
24490             nameEn: "Czechia",
24491             groups: ["EU", "151", "150", "UN"],
24492             callingCodes: ["420"]
24493           },
24494           geometry: {
24495             type: "MultiPolygon",
24496             coordinates: [[[[14.82803, 50.86966], [14.79139, 50.81438], [14.70661, 50.84096], [14.61993, 50.86049], [14.63434, 50.8883], [14.65259, 50.90513], [14.64802, 50.93241], [14.58024, 50.91443], [14.56374, 50.922], [14.59702, 50.96148], [14.59908, 50.98685], [14.58215, 50.99306], [14.56432, 51.01008], [14.53438, 51.00374], [14.53321, 51.01679], [14.49873, 51.02242], [14.50809, 51.0427], [14.49991, 51.04692], [14.49154, 51.04382], [14.49202, 51.02286], [14.45827, 51.03712], [14.41335, 51.02086], [14.30098, 51.05515], [14.25665, 50.98935], [14.28776, 50.97718], [14.32353, 50.98556], [14.32793, 50.97379], [14.30251, 50.96606], [14.31422, 50.95243], [14.39848, 50.93866], [14.38691, 50.89907], [14.30098, 50.88448], [14.27123, 50.89386], [14.24314, 50.88761], [14.22331, 50.86049], [14.02982, 50.80662], [13.98864, 50.8177], [13.89113, 50.78533], [13.89444, 50.74142], [13.82942, 50.7251], [13.76316, 50.73487], [13.70204, 50.71771], [13.65977, 50.73096], [13.52474, 50.70394], [13.53748, 50.67654], [13.5226, 50.64721], [13.49742, 50.63133], [13.46413, 50.60102], [13.42189, 50.61243], [13.37485, 50.64931], [13.37805, 50.627], [13.32264, 50.60317], [13.32594, 50.58009], [13.29454, 50.57904], [13.25158, 50.59268], [13.19043, 50.50237], [13.13424, 50.51709], [13.08301, 50.50132], [13.0312, 50.50944], [13.02038, 50.4734], [13.02147, 50.44763], [12.98433, 50.42016], [12.94058, 50.40944], [12.82465, 50.45738], [12.73476, 50.43237], [12.73044, 50.42268], [12.70731, 50.39948], [12.67261, 50.41949], [12.51356, 50.39694], [12.48747, 50.37278], [12.49214, 50.35228], [12.48256, 50.34784], [12.46643, 50.35527], [12.43722, 50.33774], [12.43371, 50.32506], [12.39924, 50.32302], [12.40158, 50.29521], [12.36594, 50.28289], [12.35425, 50.23993], [12.33263, 50.24367], [12.32445, 50.20442], [12.33847, 50.19432], [12.32596, 50.17146], [12.29232, 50.17524], [12.28063, 50.19544], [12.28755, 50.22429], [12.23943, 50.24594], [12.24791, 50.25525], [12.26953, 50.25189], [12.25119, 50.27079], [12.20823, 50.2729], [12.18013, 50.32146], [12.10907, 50.32041], [12.13716, 50.27396], [12.09287, 50.25032], [12.19335, 50.19997], [12.21484, 50.16399], [12.1917, 50.13434], [12.2073, 50.10315], [12.23709, 50.10213], [12.27433, 50.0771], [12.26111, 50.06331], [12.30798, 50.05719], [12.49908, 49.97305], [12.47264, 49.94222], [12.55197, 49.92094], [12.48256, 49.83575], [12.46603, 49.78882], [12.40489, 49.76321], [12.4462, 49.70233], [12.52553, 49.68415], [12.53544, 49.61888], [12.56188, 49.6146], [12.60155, 49.52887], [12.64782, 49.52565], [12.64121, 49.47628], [12.669, 49.42935], [12.71227, 49.42363], [12.75854, 49.3989], [12.78168, 49.34618], [12.88414, 49.33541], [12.88249, 49.35479], [12.94859, 49.34079], [13.03618, 49.30417], [13.02957, 49.27399], [13.05883, 49.26259], [13.17665, 49.16713], [13.17019, 49.14339], [13.20405, 49.12303], [13.23689, 49.11412], [13.28242, 49.1228], [13.39479, 49.04812], [13.40802, 48.98851], [13.50221, 48.93752], [13.50552, 48.97441], [13.58319, 48.96899], [13.61624, 48.9462], [13.67739, 48.87886], [13.73854, 48.88538], [13.76994, 48.83537], [13.78977, 48.83319], [13.8096, 48.77877], [13.84023, 48.76988], [14.06151, 48.66873], [14.01482, 48.63788], [14.09104, 48.5943], [14.20691, 48.5898], [14.33909, 48.55852], [14.43076, 48.58855], [14.4587, 48.64695], [14.56139, 48.60429], [14.60808, 48.62881], [14.66762, 48.58215], [14.71794, 48.59794], [14.72756, 48.69502], [14.80584, 48.73489], [14.80821, 48.77711], [14.81545, 48.7874], [14.94773, 48.76268], [14.95641, 48.75915], [14.9758, 48.76857], [14.98112, 48.77524], [14.9782, 48.7766], [14.98032, 48.77959], [14.95072, 48.79101], [14.98917, 48.90082], [14.97612, 48.96983], [14.99878, 49.01444], [15.15534, 48.99056], [15.16358, 48.94278], [15.26177, 48.95766], [15.28305, 48.98831], [15.34823, 48.98444], [15.48027, 48.94481], [15.51357, 48.91549], [15.61622, 48.89541], [15.6921, 48.85973], [15.75341, 48.8516], [15.78087, 48.87644], [15.84404, 48.86921], [16.06034, 48.75436], [16.37345, 48.729], [16.40915, 48.74576], [16.46134, 48.80865], [16.67008, 48.77699], [16.68518, 48.7281], [16.71883, 48.73806], [16.79779, 48.70998], [16.90354, 48.71541], [16.93955, 48.60371], [17.00215, 48.70887], [17.11202, 48.82925], [17.19355, 48.87602], [17.29054, 48.85546], [17.3853, 48.80936], [17.45671, 48.85004], [17.5295, 48.81117], [17.7094, 48.86721], [17.73126, 48.87885], [17.77944, 48.92318], [17.87831, 48.92679], [17.91814, 49.01784], [18.06885, 49.03157], [18.1104, 49.08624], [18.15022, 49.24518], [18.18456, 49.28909], [18.36446, 49.3267], [18.4139, 49.36517], [18.4084, 49.40003], [18.44686, 49.39467], [18.54848, 49.47059], [18.53063, 49.49022], [18.57183, 49.51162], [18.6144, 49.49824], [18.67757, 49.50895], [18.74761, 49.492], [18.84521, 49.51672], [18.84786, 49.5446], [18.80479, 49.6815], [18.72838, 49.68163], [18.69817, 49.70473], [18.62676, 49.71983], [18.62943, 49.74603], [18.62645, 49.75002], [18.61368, 49.75426], [18.61278, 49.7618], [18.57183, 49.83334], [18.60341, 49.86256], [18.57045, 49.87849], [18.57697, 49.91565], [18.54299, 49.92537], [18.54495, 49.9079], [18.53423, 49.89906], [18.41604, 49.93498], [18.33562, 49.94747], [18.33278, 49.92415], [18.31914, 49.91565], [18.27794, 49.93863], [18.27107, 49.96779], [18.21752, 49.97309], [18.20241, 49.99958], [18.10628, 50.00223], [18.07898, 50.04535], [18.03212, 50.06574], [18.00396, 50.04954], [18.04585, 50.03311], [18.04585, 50.01194], [18.00191, 50.01723], [17.86886, 49.97452], [17.77669, 50.02253], [17.7506, 50.07896], [17.6888, 50.12037], [17.66683, 50.10275], [17.59404, 50.16437], [17.70528, 50.18812], [17.76296, 50.23382], [17.72176, 50.25665], [17.74648, 50.29966], [17.69292, 50.32859], [17.67764, 50.28977], [17.58889, 50.27837], [17.3702, 50.28123], [17.34548, 50.2628], [17.34273, 50.32947], [17.27681, 50.32246], [17.19991, 50.3654], [17.19579, 50.38817], [17.14498, 50.38117], [17.1224, 50.39494], [16.89229, 50.45117], [16.85933, 50.41093], [16.90877, 50.38642], [16.94448, 50.31281], [16.99803, 50.30316], [17.02138, 50.27772], [16.99803, 50.25753], [17.02825, 50.23118], [17.00353, 50.21449], [16.98018, 50.24172], [16.8456, 50.20834], [16.7014, 50.09659], [16.63137, 50.1142], [16.55446, 50.16613], [16.56407, 50.21009], [16.42674, 50.32509], [16.39379, 50.3207], [16.3622, 50.34875], [16.36495, 50.37679], [16.30289, 50.38292], [16.28118, 50.36891], [16.22821, 50.41054], [16.21585, 50.40627], [16.19526, 50.43291], [16.31413, 50.50274], [16.34572, 50.49575], [16.44597, 50.58041], [16.33611, 50.66579], [16.23174, 50.67101], [16.20839, 50.63096], [16.10265, 50.66405], [16.02437, 50.60046], [15.98317, 50.61528], [16.0175, 50.63009], [15.97219, 50.69799], [15.87331, 50.67188], [15.81683, 50.75666], [15.73186, 50.73885], [15.43798, 50.80833], [15.3803, 50.77187], [15.36656, 50.83956], [15.2773, 50.8907], [15.27043, 50.97724], [15.2361, 50.99886], [15.1743, 50.9833], [15.16744, 51.01959], [15.11937, 50.99021], [15.10152, 51.01095], [15.06218, 51.02269], [15.03895, 51.0123], [15.02433, 51.0242], [14.96419, 50.99108], [15.01088, 50.97984], [14.99852, 50.86817], [14.82803, 50.86966]]]]
24497           }
24498         }, {
24499           type: "Feature",
24500           properties: {
24501             iso1A2: "DE",
24502             iso1A3: "DEU",
24503             iso1N3: "276",
24504             wikidata: "Q183",
24505             nameEn: "Germany",
24506             groups: ["EU", "155", "150", "UN"],
24507             callingCodes: ["49"]
24508           },
24509           geometry: {
24510             type: "MultiPolygon",
24511             coordinates: [[[[8.70847, 47.68904], [8.71773, 47.69088], [8.70237, 47.71453], [8.66416, 47.71367], [8.67508, 47.6979], [8.65769, 47.68928], [8.66837, 47.68437], [8.68985, 47.69552], [8.70847, 47.68904]]], [[[8.72617, 47.69651], [8.72809, 47.69282], [8.75856, 47.68969], [8.79511, 47.67462], [8.79966, 47.70222], [8.76965, 47.7075], [8.77309, 47.72059], [8.80663, 47.73821], [8.82002, 47.71458], [8.86989, 47.70504], [8.85065, 47.68209], [8.87383, 47.67045], [8.87625, 47.65441], [8.89946, 47.64769], [8.94093, 47.65596], [9.02093, 47.6868], [9.09891, 47.67801], [9.13845, 47.66389], [9.15181, 47.66904], [9.1705, 47.65513], [9.1755, 47.65584], [9.17593, 47.65399], [9.18203, 47.65598], [9.25619, 47.65939], [9.55125, 47.53629], [9.72736, 47.53457], [9.76748, 47.5934], [9.80254, 47.59419], [9.82591, 47.58158], [9.8189, 47.54688], [9.87499, 47.52953], [9.87733, 47.54688], [9.92407, 47.53111], [9.96029, 47.53899], [10.00003, 47.48216], [10.03859, 47.48927], [10.07131, 47.45531], [10.09001, 47.46005], [10.1052, 47.4316], [10.06897, 47.40709], [10.09819, 47.35724], [10.11805, 47.37228], [10.16362, 47.36674], [10.17648, 47.38889], [10.2127, 47.38019], [10.22774, 47.38904], [10.23757, 47.37609], [10.19998, 47.32832], [10.2147, 47.31014], [10.17648, 47.29149], [10.17531, 47.27167], [10.23257, 47.27088], [10.33424, 47.30813], [10.39851, 47.37623], [10.4324, 47.38494], [10.4359, 47.41183], [10.47446, 47.43318], [10.46278, 47.47901], [10.44291, 47.48453], [10.4324, 47.50111], [10.44992, 47.5524], [10.43473, 47.58394], [10.47329, 47.58552], [10.48849, 47.54057], [10.56912, 47.53584], [10.60337, 47.56755], [10.63456, 47.5591], [10.68832, 47.55752], [10.6965, 47.54253], [10.7596, 47.53228], [10.77596, 47.51729], [10.88814, 47.53701], [10.91268, 47.51334], [10.86945, 47.5015], [10.87061, 47.4786], [10.90918, 47.48571], [10.93839, 47.48018], [10.92437, 47.46991], [10.98513, 47.42882], [10.97111, 47.41617], [10.97111, 47.39561], [11.11835, 47.39719], [11.12536, 47.41222], [11.20482, 47.43198], [11.25157, 47.43277], [11.22002, 47.3964], [11.27844, 47.39956], [11.29597, 47.42566], [11.33804, 47.44937], [11.4175, 47.44621], [11.38128, 47.47465], [11.4362, 47.51413], [11.52618, 47.50939], [11.58578, 47.52281], [11.58811, 47.55515], [11.60681, 47.57881], [11.63934, 47.59202], [11.84052, 47.58354], [11.85572, 47.60166], [12.0088, 47.62451], [12.02282, 47.61033], [12.05788, 47.61742], [12.13734, 47.60639], [12.17824, 47.61506], [12.18145, 47.61019], [12.17737, 47.60121], [12.18568, 47.6049], [12.20398, 47.60667], [12.20801, 47.61082], [12.19895, 47.64085], [12.18507, 47.65984], [12.18347, 47.66663], [12.16769, 47.68167], [12.16217, 47.70105], [12.18303, 47.70065], [12.22571, 47.71776], [12.2542, 47.7433], [12.26238, 47.73544], [12.24017, 47.69534], [12.26004, 47.67725], [12.27991, 47.68827], [12.336, 47.69534], [12.37222, 47.68433], [12.43883, 47.6977], [12.44117, 47.6741], [12.50076, 47.62293], [12.53816, 47.63553], [12.57438, 47.63238], [12.6071, 47.6741], [12.7357, 47.6787], [12.77777, 47.66689], [12.76492, 47.64485], [12.82101, 47.61493], [12.77427, 47.58025], [12.80699, 47.54477], [12.84672, 47.54556], [12.85256, 47.52741], [12.9624, 47.47452], [12.98344, 47.48716], [12.9998, 47.46267], [13.04537, 47.49426], [13.03252, 47.53373], [13.05355, 47.56291], [13.04537, 47.58183], [13.06641, 47.58577], [13.06407, 47.60075], [13.09562, 47.63304], [13.07692, 47.68814], [13.01382, 47.72116], [12.98578, 47.7078], [12.92969, 47.71094], [12.91333, 47.7178], [12.90274, 47.72513], [12.91711, 47.74026], [12.9353, 47.74788], [12.94371, 47.76281], [12.93202, 47.77302], [12.96311, 47.79957], [12.98543, 47.82896], [13.00588, 47.84374], [12.94163, 47.92927], [12.93886, 47.94046], [12.93642, 47.94436], [12.93419, 47.94063], [12.92668, 47.93879], [12.91985, 47.94069], [12.9211, 47.95135], [12.91683, 47.95647], [12.87476, 47.96195], [12.8549, 48.01122], [12.76141, 48.07373], [12.74973, 48.10885], [12.7617, 48.12796], [12.78595, 48.12445], [12.80676, 48.14979], [12.82673, 48.15245], [12.8362, 48.15876], [12.836, 48.1647], [12.84475, 48.16556], [12.87126, 48.20318], [12.95306, 48.20629], [13.02083, 48.25689], [13.0851, 48.27711], [13.126, 48.27867], [13.18093, 48.29577], [13.26039, 48.29422], [13.30897, 48.31575], [13.40709, 48.37292], [13.43929, 48.43386], [13.42527, 48.45711], [13.45727, 48.51092], [13.43695, 48.55776], [13.45214, 48.56472], [13.46967, 48.55157], [13.50663, 48.57506], [13.50131, 48.58091], [13.51291, 48.59023], [13.57535, 48.55912], [13.59705, 48.57013], [13.62508, 48.55501], [13.65186, 48.55092], [13.66113, 48.53558], [13.72802, 48.51208], [13.74816, 48.53058], [13.7513, 48.5624], [13.76921, 48.55324], [13.80519, 48.58026], [13.80038, 48.59487], [13.82609, 48.62345], [13.81901, 48.6761], [13.81283, 48.68426], [13.81791, 48.69832], [13.79337, 48.71375], [13.81863, 48.73257], [13.82266, 48.75544], [13.84023, 48.76988], [13.8096, 48.77877], [13.78977, 48.83319], [13.76994, 48.83537], [13.73854, 48.88538], [13.67739, 48.87886], [13.61624, 48.9462], [13.58319, 48.96899], [13.50552, 48.97441], [13.50221, 48.93752], [13.40802, 48.98851], [13.39479, 49.04812], [13.28242, 49.1228], [13.23689, 49.11412], [13.20405, 49.12303], [13.17019, 49.14339], [13.17665, 49.16713], [13.05883, 49.26259], [13.02957, 49.27399], [13.03618, 49.30417], [12.94859, 49.34079], [12.88249, 49.35479], [12.88414, 49.33541], [12.78168, 49.34618], [12.75854, 49.3989], [12.71227, 49.42363], [12.669, 49.42935], [12.64121, 49.47628], [12.64782, 49.52565], [12.60155, 49.52887], [12.56188, 49.6146], [12.53544, 49.61888], [12.52553, 49.68415], [12.4462, 49.70233], [12.40489, 49.76321], [12.46603, 49.78882], [12.48256, 49.83575], [12.55197, 49.92094], [12.47264, 49.94222], [12.49908, 49.97305], [12.30798, 50.05719], [12.26111, 50.06331], [12.27433, 50.0771], [12.23709, 50.10213], [12.2073, 50.10315], [12.1917, 50.13434], [12.21484, 50.16399], [12.19335, 50.19997], [12.09287, 50.25032], [12.13716, 50.27396], [12.10907, 50.32041], [12.18013, 50.32146], [12.20823, 50.2729], [12.25119, 50.27079], [12.26953, 50.25189], [12.24791, 50.25525], [12.23943, 50.24594], [12.28755, 50.22429], [12.28063, 50.19544], [12.29232, 50.17524], [12.32596, 50.17146], [12.33847, 50.19432], [12.32445, 50.20442], [12.33263, 50.24367], [12.35425, 50.23993], [12.36594, 50.28289], [12.40158, 50.29521], [12.39924, 50.32302], [12.43371, 50.32506], [12.43722, 50.33774], [12.46643, 50.35527], [12.48256, 50.34784], [12.49214, 50.35228], [12.48747, 50.37278], [12.51356, 50.39694], [12.67261, 50.41949], [12.70731, 50.39948], [12.73044, 50.42268], [12.73476, 50.43237], [12.82465, 50.45738], [12.94058, 50.40944], [12.98433, 50.42016], [13.02147, 50.44763], [13.02038, 50.4734], [13.0312, 50.50944], [13.08301, 50.50132], [13.13424, 50.51709], [13.19043, 50.50237], [13.25158, 50.59268], [13.29454, 50.57904], [13.32594, 50.58009], [13.32264, 50.60317], [13.37805, 50.627], [13.37485, 50.64931], [13.42189, 50.61243], [13.46413, 50.60102], [13.49742, 50.63133], [13.5226, 50.64721], [13.53748, 50.67654], [13.52474, 50.70394], [13.65977, 50.73096], [13.70204, 50.71771], [13.76316, 50.73487], [13.82942, 50.7251], [13.89444, 50.74142], [13.89113, 50.78533], [13.98864, 50.8177], [14.02982, 50.80662], [14.22331, 50.86049], [14.24314, 50.88761], [14.27123, 50.89386], [14.30098, 50.88448], [14.38691, 50.89907], [14.39848, 50.93866], [14.31422, 50.95243], [14.30251, 50.96606], [14.32793, 50.97379], [14.32353, 50.98556], [14.28776, 50.97718], [14.25665, 50.98935], [14.30098, 51.05515], [14.41335, 51.02086], [14.45827, 51.03712], [14.49202, 51.02286], [14.49154, 51.04382], [14.49991, 51.04692], [14.50809, 51.0427], [14.49873, 51.02242], [14.53321, 51.01679], [14.53438, 51.00374], [14.56432, 51.01008], [14.58215, 50.99306], [14.59908, 50.98685], [14.59702, 50.96148], [14.56374, 50.922], [14.58024, 50.91443], [14.64802, 50.93241], [14.65259, 50.90513], [14.63434, 50.8883], [14.61993, 50.86049], [14.70661, 50.84096], [14.79139, 50.81438], [14.82803, 50.86966], [14.81664, 50.88148], [14.89681, 50.9422], [14.89252, 50.94999], [14.92942, 50.99744], [14.95529, 51.04552], [14.97938, 51.07742], [14.98229, 51.11354], [14.99689, 51.12205], [14.99079, 51.14284], [14.99646, 51.14365], [15.00083, 51.14974], [14.99414, 51.15813], [14.99311, 51.16249], [15.0047, 51.16874], [15.01242, 51.21285], [15.04288, 51.28387], [14.98008, 51.33449], [14.96899, 51.38367], [14.9652, 51.44793], [14.94749, 51.47155], [14.73219, 51.52922], [14.72652, 51.53902], [14.73047, 51.54606], [14.71125, 51.56209], [14.7727, 51.61263], [14.75759, 51.62318], [14.75392, 51.67445], [14.69065, 51.70842], [14.66386, 51.73282], [14.64625, 51.79472], [14.60493, 51.80473], [14.59089, 51.83302], [14.6588, 51.88359], [14.6933, 51.9044], [14.70601, 51.92944], [14.7177, 51.94048], [14.72163, 51.95188], [14.71836, 51.95606], [14.7139, 51.95643], [14.70488, 51.97679], [14.71339, 52.00337], [14.76026, 52.06624], [14.72971, 52.09167], [14.6917, 52.10283], [14.67683, 52.13936], [14.70616, 52.16927], [14.68344, 52.19612], [14.71319, 52.22144], [14.70139, 52.25038], [14.58149, 52.28007], [14.56378, 52.33838], [14.55228, 52.35264], [14.54423, 52.42568], [14.63056, 52.48993], [14.60081, 52.53116], [14.6289, 52.57136], [14.61073, 52.59847], [14.22071, 52.81175], [14.13806, 52.82392], [14.12256, 52.84311], [14.15873, 52.87715], [14.14056, 52.95786], [14.25954, 53.00264], [14.35044, 53.05829], [14.38679, 53.13669], [14.36696, 53.16444], [14.37853, 53.20405], [14.40662, 53.21098], [14.45125, 53.26241], [14.44133, 53.27427], [14.4215, 53.27724], [14.35209, 53.49506], [14.3273, 53.50587], [14.30416, 53.55499], [14.31904, 53.61581], [14.2853, 53.63392], [14.28477, 53.65955], [14.27133, 53.66613], [14.2836, 53.67721], [14.26782, 53.69866], [14.27249, 53.74464], [14.21323, 53.8664], [14.20823, 53.90776], [14.18544, 53.91258], [14.20647, 53.91671], [14.22634, 53.9291], [14.20811, 54.12784], [13.93395, 54.84044], [12.85844, 54.82438], [11.90309, 54.38543], [11.00303, 54.63689], [10.31111, 54.65968], [10.16755, 54.73883], [9.89314, 54.84171], [9.73563, 54.8247], [9.61187, 54.85548], [9.62734, 54.88057], [9.58937, 54.88785], [9.4659, 54.83131], [9.43155, 54.82586], [9.41213, 54.84254], [9.38532, 54.83968], [9.36496, 54.81749], [9.33849, 54.80233], [9.32771, 54.80602], [9.2474, 54.8112], [9.23445, 54.83432], [9.24631, 54.84726], [9.20571, 54.85841], [9.14275, 54.87421], [9.04629, 54.87249], [8.92795, 54.90452], [8.81178, 54.90518], [8.76387, 54.8948], [8.63979, 54.91069], [8.55769, 54.91837], [8.45719, 55.06747], [8.02459, 55.09613], [5.45168, 54.20039], [6.91025, 53.44221], [7.00198, 53.32672], [7.19052, 53.31866], [7.21679, 53.20058], [7.22681, 53.18165], [7.17898, 53.13817], [7.21694, 53.00742], [7.07253, 52.81083], [7.04557, 52.63318], [6.77307, 52.65375], [6.71641, 52.62905], [6.69507, 52.488], [6.94293, 52.43597], [6.99041, 52.47235], [7.03417, 52.40237], [7.07044, 52.37805], [7.02703, 52.27941], [7.06365, 52.23789], [7.03729, 52.22695], [6.9897, 52.2271], [6.97189, 52.20329], [6.83984, 52.11728], [6.76117, 52.11895], [6.68128, 52.05052], [6.83035, 51.9905], [6.82357, 51.96711], [6.72319, 51.89518], [6.68386, 51.91861], [6.58556, 51.89386], [6.50231, 51.86313], [6.47179, 51.85395], [6.38815, 51.87257], [6.40704, 51.82771], [6.30593, 51.84998], [6.29872, 51.86801], [6.21443, 51.86801], [6.15349, 51.90439], [6.11551, 51.89769], [6.16902, 51.84094], [6.10337, 51.84829], [6.06705, 51.86136], [5.99848, 51.83195], [5.94568, 51.82786], [5.98665, 51.76944], [5.95003, 51.7493], [6.04091, 51.71821], [6.02767, 51.6742], [6.11759, 51.65609], [6.09055, 51.60564], [6.18017, 51.54096], [6.21724, 51.48568], [6.20654, 51.40049], [6.22641, 51.39948], [6.22674, 51.36135], [6.16977, 51.33169], [6.07889, 51.24432], [6.07889, 51.17038], [6.17384, 51.19589], [6.16706, 51.15677], [5.98292, 51.07469], [5.9541, 51.03496], [5.9134, 51.06736], [5.86735, 51.05182], [5.87849, 51.01969], [5.90493, 51.00198], [5.90296, 50.97356], [5.95282, 50.98728], [6.02697, 50.98303], [6.01615, 50.93367], [6.09297, 50.92066], [6.07486, 50.89307], [6.08805, 50.87223], [6.07693, 50.86025], [6.07431, 50.84674], [6.05702, 50.85179], [6.05623, 50.8572], [6.01921, 50.84435], [6.02328, 50.81694], [6.00462, 50.80065], [5.98404, 50.80988], [5.97497, 50.79992], [6.02624, 50.77453], [6.01976, 50.75398], [6.03889, 50.74618], [6.0326, 50.72647], [6.0406, 50.71848], [6.04428, 50.72861], [6.11707, 50.72231], [6.17852, 50.6245], [6.26957, 50.62444], [6.2476, 50.60392], [6.24888, 50.59869], [6.24005, 50.58732], [6.22581, 50.5907], [6.20281, 50.56952], [6.17739, 50.55875], [6.17802, 50.54179], [6.19735, 50.53576], [6.19579, 50.5313], [6.18716, 50.52653], [6.19193, 50.5212], [6.20599, 50.52089], [6.22335, 50.49578], [6.26637, 50.50272], [6.30809, 50.50058], [6.3465, 50.48833], [6.34005, 50.46083], [6.37219, 50.45397], [6.36852, 50.40776], [6.34406, 50.37994], [6.3688, 50.35898], [6.40785, 50.33557], [6.40641, 50.32425], [6.35701, 50.31139], [6.32488, 50.32333], [6.29949, 50.30887], [6.28797, 50.27458], [6.208, 50.25179], [6.16853, 50.2234], [6.18364, 50.20815], [6.18739, 50.1822], [6.14588, 50.17106], [6.14132, 50.14971], [6.15298, 50.14126], [6.1379, 50.12964], [6.12055, 50.09171], [6.11274, 50.05916], [6.13458, 50.04141], [6.13044, 50.02929], [6.14666, 50.02207], [6.13794, 50.01466], [6.13273, 50.02019], [6.1295, 50.01849], [6.13806, 50.01056], [6.14948, 50.00908], [6.14147, 49.99563], [6.1701, 49.98518], [6.16466, 49.97086], [6.17872, 49.9537], [6.18554, 49.95622], [6.18045, 49.96611], [6.19089, 49.96991], [6.19856, 49.95053], [6.22094, 49.94955], [6.22608, 49.929], [6.21882, 49.92403], [6.22926, 49.92096], [6.23496, 49.89972], [6.26146, 49.88203], [6.28874, 49.87592], [6.29692, 49.86685], [6.30963, 49.87021], [6.32303, 49.85133], [6.32098, 49.83728], [6.33585, 49.83785], [6.34267, 49.84974], [6.36576, 49.85032], [6.40022, 49.82029], [6.42521, 49.81591], [6.42905, 49.81091], [6.44131, 49.81443], [6.45425, 49.81164], [6.47111, 49.82263], [6.48718, 49.81267], [6.50647, 49.80916], [6.51215, 49.80124], [6.52121, 49.81338], [6.53122, 49.80666], [6.52169, 49.79787], [6.50534, 49.78952], [6.51669, 49.78336], [6.51056, 49.77515], [6.51828, 49.76855], [6.51646, 49.75961], [6.50174, 49.75292], [6.50193, 49.73291], [6.51805, 49.72425], [6.51397, 49.72058], [6.50261, 49.72718], [6.49535, 49.72645], [6.49694, 49.72205], [6.5042, 49.71808], [6.50647, 49.71353], [6.49785, 49.71118], [6.48014, 49.69767], [6.46048, 49.69092], [6.44654, 49.67799], [6.42937, 49.66857], [6.42726, 49.66078], [6.43768, 49.66021], [6.4413, 49.65722], [6.41861, 49.61723], [6.39822, 49.60081], [6.385, 49.59946], [6.37464, 49.58886], [6.38342, 49.5799], [6.38024, 49.57593], [6.36676, 49.57813], [6.35825, 49.57053], [6.38228, 49.55855], [6.38072, 49.55171], [6.35666, 49.52931], [6.36788, 49.50377], [6.36907, 49.48931], [6.36778, 49.46937], [6.38352, 49.46463], [6.39168, 49.4667], [6.40274, 49.46546], [6.42432, 49.47683], [6.55404, 49.42464], [6.533, 49.40748], [6.60091, 49.36864], [6.58807, 49.35358], [6.572, 49.35027], [6.60186, 49.31055], [6.66583, 49.28065], [6.69274, 49.21661], [6.71843, 49.2208], [6.73256, 49.20486], [6.71137, 49.18808], [6.73765, 49.16375], [6.78265, 49.16793], [6.83385, 49.15162], [6.84703, 49.15734], [6.86225, 49.18185], [6.85016, 49.19354], [6.85119, 49.20038], [6.83555, 49.21249], [6.85939, 49.22376], [6.89298, 49.20863], [6.91875, 49.22261], [6.93831, 49.2223], [6.94028, 49.21641], [6.95963, 49.203], [6.97273, 49.2099], [7.01318, 49.19018], [7.03459, 49.19096], [7.0274, 49.17042], [7.03178, 49.15734], [7.04662, 49.13724], [7.04409, 49.12123], [7.04843, 49.11422], [7.05548, 49.11185], [7.06642, 49.11415], [7.07162, 49.1255], [7.09007, 49.13094], [7.07859, 49.15031], [7.10715, 49.15631], [7.10384, 49.13787], [7.12504, 49.14253], [7.1358, 49.1282], [7.1593, 49.1204], [7.23473, 49.12971], [7.29514, 49.11426], [7.3195, 49.14231], [7.35995, 49.14399], [7.3662, 49.17308], [7.44052, 49.18354], [7.44455, 49.16765], [7.49473, 49.17], [7.49172, 49.13915], [7.53012, 49.09818], [7.56416, 49.08136], [7.62575, 49.07654], [7.63618, 49.05428], [7.75948, 49.04562], [7.79557, 49.06583], [7.86386, 49.03499], [7.93641, 49.05544], [7.97783, 49.03161], [8.14189, 48.97833], [8.22604, 48.97352], [8.20031, 48.95856], [8.19989, 48.95825], [8.12813, 48.87985], [8.10253, 48.81829], [8.06802, 48.78957], [8.0326, 48.79017], [8.01534, 48.76085], [7.96994, 48.75606], [7.96812, 48.72491], [7.89002, 48.66317], [7.84098, 48.64217], [7.80057, 48.5857], [7.80167, 48.54758], [7.80647, 48.51239], [7.76833, 48.48945], [7.73109, 48.39192], [7.74562, 48.32736], [7.69022, 48.30018], [7.6648, 48.22219], [7.57137, 48.12292], [7.56966, 48.03265], [7.62302, 47.97898], [7.55673, 47.87371], [7.52921, 47.77747], [7.54761, 47.72912], [7.53722, 47.71635], [7.51266, 47.70197], [7.51915, 47.68335], [7.52067, 47.66437], [7.53384, 47.65115], [7.5591, 47.63849], [7.57423, 47.61628], [7.58851, 47.60794], [7.59301, 47.60058], [7.58945, 47.59017], [7.60523, 47.58519], [7.60459, 47.57869], [7.61929, 47.57683], [7.64309, 47.59151], [7.64213, 47.5944], [7.64599, 47.59695], [7.67395, 47.59212], [7.68229, 47.59905], [7.69385, 47.60099], [7.68486, 47.59601], [7.67115, 47.5871], [7.68904, 47.57133], [7.67655, 47.56435], [7.63338, 47.56256], [7.65083, 47.54662], [7.66174, 47.54554], [7.6656, 47.53752], [7.68101, 47.53232], [7.69642, 47.53297], [7.71961, 47.54219], [7.75261, 47.54599], [7.79486, 47.55691], [7.81901, 47.58798], [7.84412, 47.5841], [7.88664, 47.58854], [7.90673, 47.57674], [7.91251, 47.55031], [7.94494, 47.54511], [7.95682, 47.55789], [7.97581, 47.55493], [8.00113, 47.55616], [8.02136, 47.55096], [8.04383, 47.55443], [8.06663, 47.56374], [8.08557, 47.55768], [8.10002, 47.56504], [8.10395, 47.57918], [8.11543, 47.5841], [8.13662, 47.58432], [8.13823, 47.59147], [8.14947, 47.59558], [8.1652, 47.5945], [8.19378, 47.61636], [8.20617, 47.62141], [8.22011, 47.6181], [8.22577, 47.60385], [8.23809, 47.61204], [8.25863, 47.61571], [8.26313, 47.6103], [8.2824, 47.61225], [8.29722, 47.60603], [8.29524, 47.5919], [8.30277, 47.58607], [8.32735, 47.57133], [8.35512, 47.57014], [8.38273, 47.56608], [8.39477, 47.57826], [8.43235, 47.56617], [8.49431, 47.58107], [8.48949, 47.588], [8.46637, 47.58389], [8.45578, 47.60121], [8.50747, 47.61897], [8.51686, 47.63476], [8.55756, 47.62394], [8.57586, 47.59537], [8.60348, 47.61204], [8.59545, 47.64298], [8.60701, 47.65271], [8.61471, 47.64514], [8.60412, 47.63735], [8.62049, 47.63757], [8.62884, 47.65098], [8.61113, 47.66332], [8.6052, 47.67258], [8.57683, 47.66158], [8.56141, 47.67088], [8.52801, 47.66059], [8.5322, 47.64687], [8.49656, 47.64709], [8.46605, 47.64103], [8.4667, 47.65747], [8.44711, 47.65379], [8.42264, 47.66667], [8.41346, 47.66676], [8.40473, 47.67499], [8.4211, 47.68407], [8.40569, 47.69855], [8.44807, 47.72426], [8.45771, 47.7493], [8.48868, 47.77215], [8.56814, 47.78001], [8.56415, 47.80633], [8.61657, 47.79998], [8.62408, 47.7626], [8.64425, 47.76398], [8.65292, 47.80066], [8.68022, 47.78599], [8.68985, 47.75686], [8.71778, 47.76571], [8.74251, 47.75168], [8.70543, 47.73121], [8.73671, 47.7169], [8.72617, 47.69651]]]]
24512           }
24513         }, {
24514           type: "Feature",
24515           properties: {
24516             iso1A2: "DG",
24517             iso1A3: "DGA",
24518             wikidata: "Q184851",
24519             nameEn: "Diego Garcia",
24520             country: "GB",
24521             groups: ["IO", "BOTS", "014", "202", "002", "UN"],
24522             isoStatus: "excRes",
24523             callingCodes: ["246"]
24524           },
24525           geometry: {
24526             type: "MultiPolygon",
24527             coordinates: [[[[73.14823, -7.76302], [73.09982, -6.07324], [71.43792, -7.73904], [73.14823, -7.76302]]]]
24528           }
24529         }, {
24530           type: "Feature",
24531           properties: {
24532             iso1A2: "DJ",
24533             iso1A3: "DJI",
24534             iso1N3: "262",
24535             wikidata: "Q977",
24536             nameEn: "Djibouti",
24537             groups: ["014", "202", "002", "UN"],
24538             callingCodes: ["253"]
24539           },
24540           geometry: {
24541             type: "MultiPolygon",
24542             coordinates: [[[[43.90659, 12.3823], [43.90659, 12.3823], [43.32909, 12.59711], [43.29075, 12.79154], [42.86195, 12.58747], [42.7996, 12.42629], [42.6957, 12.36201], [42.46941, 12.52661], [42.4037, 12.46478], [41.95461, 11.81157], [41.82878, 11.72361], [41.77727, 11.49902], [41.8096, 11.33606], [41.80056, 10.97127], [42.06302, 10.92599], [42.13691, 10.97586], [42.42669, 10.98493], [42.62989, 11.09711], [42.75111, 11.06992], [42.79037, 10.98493], [42.95776, 10.98533], [43.90659, 12.3823]]]]
24543           }
24544         }, {
24545           type: "Feature",
24546           properties: {
24547             iso1A2: "DK",
24548             iso1A3: "DNK",
24549             iso1N3: "208",
24550             wikidata: "Q756617",
24551             nameEn: "Kingdom of Denmark"
24552           },
24553           geometry: null
24554         }, {
24555           type: "Feature",
24556           properties: {
24557             iso1A2: "DM",
24558             iso1A3: "DMA",
24559             iso1N3: "212",
24560             wikidata: "Q784",
24561             nameEn: "Dominica",
24562             groups: ["029", "003", "419", "019", "UN"],
24563             driveSide: "left",
24564             roadSpeedUnit: "mph",
24565             callingCodes: ["1 767"]
24566           },
24567           geometry: {
24568             type: "MultiPolygon",
24569             coordinates: [[[[-61.32485, 14.91445], [-60.86656, 15.82603], [-61.95646, 15.5094], [-61.32485, 14.91445]]]]
24570           }
24571         }, {
24572           type: "Feature",
24573           properties: {
24574             iso1A2: "DO",
24575             iso1A3: "DOM",
24576             iso1N3: "214",
24577             wikidata: "Q786",
24578             nameEn: "Dominican Republic",
24579             groups: ["029", "003", "419", "019", "UN"],
24580             callingCodes: ["1 809", "1 829", "1 849"]
24581           },
24582           geometry: {
24583             type: "MultiPolygon",
24584             coordinates: [[[[-67.87844, 21.7938], [-72.38946, 20.27111], [-71.77419, 19.73128], [-71.75865, 19.70231], [-71.7429, 19.58445], [-71.71449, 19.55364], [-71.71268, 19.53374], [-71.6802, 19.45008], [-71.69448, 19.37866], [-71.77766, 19.33823], [-71.73229, 19.26686], [-71.62642, 19.21212], [-71.65337, 19.11759], [-71.69938, 19.10916], [-71.71088, 19.08353], [-71.74088, 19.0437], [-71.88102, 18.95007], [-71.77766, 18.95007], [-71.72624, 18.87802], [-71.71885, 18.78423], [-71.82556, 18.62551], [-71.95412, 18.64939], [-72.00201, 18.62312], [-71.88102, 18.50125], [-71.90875, 18.45821], [-71.69952, 18.34101], [-71.78271, 18.18302], [-71.75465, 18.14405], [-71.74994, 18.11115], [-71.73783, 18.07177], [-71.75671, 18.03456], [-72.29523, 17.48026], [-68.39466, 16.14167], [-67.87844, 21.7938]]]]
24585           }
24586         }, {
24587           type: "Feature",
24588           properties: {
24589             iso1A2: "DZ",
24590             iso1A3: "DZA",
24591             iso1N3: "012",
24592             wikidata: "Q262",
24593             nameEn: "Algeria",
24594             groups: ["015", "002", "UN"],
24595             callingCodes: ["213"]
24596           },
24597           geometry: {
24598             type: "MultiPolygon",
24599             coordinates: [[[[8.59123, 37.14286], [5.10072, 39.89531], [-2.27707, 35.35051], [-2.21248, 35.08532], [-2.21445, 35.04378], [-2.04734, 34.93218], [-1.97833, 34.93218], [-1.97469, 34.886], [-1.73707, 34.74226], [-1.84569, 34.61907], [-1.69788, 34.48056], [-1.78042, 34.39018], [-1.64666, 34.10405], [-1.73494, 33.71721], [-1.59508, 33.59929], [-1.67067, 33.27084], [-1.46249, 33.0499], [-1.54244, 32.95499], [-1.37794, 32.73628], [-0.9912, 32.52467], [-1.24998, 32.32993], [-1.24453, 32.1917], [-1.15735, 32.12096], [-1.22829, 32.07832], [-2.46166, 32.16603], [-2.93873, 32.06557], [-2.82784, 31.79459], [-3.66314, 31.6339], [-3.66386, 31.39202], [-3.77647, 31.31912], [-3.77103, 31.14984], [-3.54944, 31.0503], [-3.65418, 30.85566], [-3.64735, 30.67539], [-4.31774, 30.53229], [-4.6058, 30.28343], [-5.21671, 29.95253], [-5.58831, 29.48103], [-5.72121, 29.52322], [-5.75616, 29.61407], [-6.69965, 29.51623], [-6.78351, 29.44634], [-6.95824, 29.50924], [-7.61585, 29.36252], [-8.6715, 28.71194], [-8.66879, 27.6666], [-8.66674, 27.31569], [-4.83423, 24.99935], [1.15698, 21.12843], [1.20992, 20.73533], [3.24648, 19.81703], [3.12501, 19.1366], [3.36082, 18.9745], [4.26651, 19.14224], [5.8153, 19.45101], [7.38361, 20.79165], [7.48273, 20.87258], [11.96886, 23.51735], [11.62498, 24.26669], [11.41061, 24.21456], [10.85323, 24.5595], [10.33159, 24.5465], [10.02432, 24.98124], [10.03146, 25.35635], [9.38834, 26.19288], [9.51696, 26.39148], [9.89569, 26.57696], [9.78136, 29.40961], [9.3876, 30.16738], [9.55544, 30.23971], [9.07483, 32.07865], [8.35999, 32.50101], [8.31895, 32.83483], [8.1179, 33.05086], [8.11433, 33.10175], [7.83028, 33.18851], [7.73687, 33.42114], [7.54088, 33.7726], [7.52851, 34.06493], [7.66174, 34.20167], [7.74207, 34.16492], [7.81242, 34.21841], [7.86264, 34.3987], [8.20482, 34.57575], [8.29655, 34.72798], [8.25189, 34.92009], [8.30727, 34.95378], [8.3555, 35.10007], [8.47318, 35.23376], [8.30329, 35.29884], [8.36086, 35.47774], [8.35371, 35.66373], [8.26472, 35.73669], [8.2626, 35.91733], [8.40731, 36.42208], [8.18936, 36.44939], [8.16167, 36.48817], [8.47609, 36.66607], [8.46537, 36.7706], [8.57613, 36.78062], [8.67706, 36.8364], [8.62972, 36.86499], [8.64044, 36.9401], [8.59123, 37.14286]]]]
24600           }
24601         }, {
24602           type: "Feature",
24603           properties: {
24604             iso1A2: "EA",
24605             wikidata: "Q28868874",
24606             nameEn: "Ceuta, Melilla",
24607             country: "ES",
24608             level: "territory",
24609             isoStatus: "excRes"
24610           },
24611           geometry: null
24612         }, {
24613           type: "Feature",
24614           properties: {
24615             iso1A2: "EC",
24616             iso1A3: "ECU",
24617             iso1N3: "218",
24618             wikidata: "Q736",
24619             nameEn: "Ecuador"
24620           },
24621           geometry: null
24622         }, {
24623           type: "Feature",
24624           properties: {
24625             iso1A2: "EE",
24626             iso1A3: "EST",
24627             iso1N3: "233",
24628             wikidata: "Q191",
24629             nameEn: "Estonia",
24630             aliases: ["EW"],
24631             groups: ["EU", "154", "150", "UN"],
24632             callingCodes: ["372"]
24633           },
24634           geometry: {
24635             type: "MultiPolygon",
24636             coordinates: [[[[26.32936, 60.00121], [20.5104, 59.15546], [19.84909, 57.57876], [22.80496, 57.87798], [23.20055, 57.56697], [24.26221, 57.91787], [24.3579, 57.87471], [25.19484, 58.0831], [25.28237, 57.98539], [25.29581, 58.08288], [25.73499, 57.90193], [26.05949, 57.84744], [26.0324, 57.79037], [26.02456, 57.78342], [26.027, 57.78158], [26.0266, 57.77441], [26.02069, 57.77169], [26.02415, 57.76865], [26.03332, 57.7718], [26.0543, 57.76105], [26.08098, 57.76619], [26.2029, 57.7206], [26.1866, 57.6849], [26.29253, 57.59244], [26.46527, 57.56885], [26.54675, 57.51813], [26.90364, 57.62823], [27.34698, 57.52242], [27.31919, 57.57672], [27.40393, 57.62125], [27.3746, 57.66834], [27.52615, 57.72843], [27.50171, 57.78842], [27.56689, 57.83356], [27.78526, 57.83963], [27.81841, 57.89244], [27.67282, 57.92627], [27.62393, 58.09462], [27.48541, 58.22615], [27.55489, 58.39525], [27.36366, 58.78381], [27.74429, 58.98351], [27.80482, 59.1116], [27.87978, 59.18097], [27.90911, 59.24353], [28.00689, 59.28351], [28.14215, 59.28934], [28.19284, 59.35791], [28.20537, 59.36491], [28.21137, 59.38058], [28.19061, 59.39962], [28.04187, 59.47017], [27.85643, 59.58538], [26.90044, 59.63819], [26.32936, 60.00121]]]]
24637           }
24638         }, {
24639           type: "Feature",
24640           properties: {
24641             iso1A2: "EG",
24642             iso1A3: "EGY",
24643             iso1N3: "818",
24644             wikidata: "Q79",
24645             nameEn: "Egypt",
24646             groups: ["015", "002", "UN"],
24647             callingCodes: ["20"]
24648           },
24649           geometry: {
24650             type: "MultiPolygon",
24651             coordinates: [[[[33.62659, 31.82938], [26.92891, 33.39516], [24.8458, 31.39877], [25.01077, 30.73861], [24.71117, 30.17441], [24.99968, 29.24574], [24.99885, 21.99535], [33.17563, 22.00405], [34.0765, 22.00501], [37.8565, 22.00903], [34.4454, 27.91479], [34.8812, 29.36878], [34.92298, 29.45305], [34.26742, 31.21998], [34.24012, 31.29591], [34.23572, 31.2966], [34.21853, 31.32363], [34.052, 31.46619], [33.62659, 31.82938]]]]
24652           }
24653         }, {
24654           type: "Feature",
24655           properties: {
24656             iso1A2: "EH",
24657             iso1A3: "ESH",
24658             iso1N3: "732",
24659             wikidata: "Q6250",
24660             nameEn: "Western Sahara",
24661             groups: ["015", "002"],
24662             callingCodes: ["212"]
24663           },
24664           geometry: {
24665             type: "MultiPolygon",
24666             coordinates: [[[[-8.66879, 27.6666], [-8.77527, 27.66663], [-8.71787, 26.9898], [-9.08698, 26.98639], [-9.56957, 26.90042], [-9.81998, 26.71379], [-10.68417, 26.90984], [-11.35695, 26.8505], [-11.23622, 26.72023], [-11.38635, 26.611], [-11.62052, 26.05229], [-12.06001, 26.04442], [-12.12281, 25.13682], [-12.92147, 24.39502], [-13.00628, 24.01923], [-13.75627, 23.77231], [-14.10361, 22.75501], [-14.1291, 22.41636], [-14.48112, 22.00886], [-14.47329, 21.63839], [-14.78487, 21.36587], [-16.44269, 21.39745], [-16.9978, 21.36239], [-17.02707, 21.34022], [-17.21511, 21.34226], [-17.35589, 20.80492], [-17.0471, 20.76408], [-17.0695, 20.85742], [-17.06781, 20.92697], [-17.0396, 20.9961], [-17.0357, 21.05368], [-16.99806, 21.12142], [-16.95474, 21.33997], [-13.01525, 21.33343], [-13.08438, 22.53866], [-13.15313, 22.75649], [-13.10753, 22.89493], [-13.00412, 23.02297], [-12.5741, 23.28975], [-12.36213, 23.3187], [-12.14969, 23.41935], [-12.00251, 23.4538], [-12.0002, 25.9986], [-8.66721, 25.99918], [-8.66674, 27.31569], [-8.66879, 27.6666]]]]
24667           }
24668         }, {
24669           type: "Feature",
24670           properties: {
24671             iso1A2: "ER",
24672             iso1A3: "ERI",
24673             iso1N3: "232",
24674             wikidata: "Q986",
24675             nameEn: "Eritrea",
24676             groups: ["014", "202", "002", "UN"],
24677             callingCodes: ["291"]
24678           },
24679           geometry: {
24680             type: "MultiPolygon",
24681             coordinates: [[[[40.99158, 15.81743], [39.63762, 18.37348], [38.57727, 17.98125], [38.45916, 17.87167], [38.37133, 17.66269], [38.13362, 17.53906], [37.50967, 17.32199], [37.42694, 17.04041], [36.99777, 17.07172], [36.92193, 16.23451], [36.76371, 15.80831], [36.69761, 15.75323], [36.54276, 15.23478], [36.44337, 15.14963], [36.54376, 14.25597], [36.56536, 14.26177], [36.55659, 14.28237], [36.63364, 14.31172], [36.85787, 14.32201], [37.01622, 14.2561], [37.09486, 14.27155], [37.13206, 14.40746], [37.3106, 14.44657], [37.47319, 14.2149], [37.528, 14.18413], [37.91287, 14.89447], [38.0364, 14.72745], [38.25562, 14.67287], [38.3533, 14.51323], [38.45748, 14.41445], [38.78306, 14.4754], [38.98058, 14.54895], [39.02834, 14.63717], [39.16074, 14.65187], [39.14772, 14.61827], [39.19547, 14.56996], [39.23888, 14.56365], [39.26927, 14.48801], [39.2302, 14.44598], [39.2519, 14.40393], [39.37685, 14.54402], [39.52756, 14.49011], [39.50585, 14.55735], [39.58182, 14.60987], [39.76632, 14.54264], [39.9443, 14.41024], [40.07236, 14.54264], [40.14649, 14.53969], [40.21128, 14.39342], [40.25686, 14.41445], [40.9167, 14.11152], [41.25097, 13.60787], [41.62864, 13.38626], [42.05841, 12.80912], [42.21469, 12.75832], [42.2798, 12.6355], [42.4037, 12.46478], [42.46941, 12.52661], [42.6957, 12.36201], [42.7996, 12.42629], [42.86195, 12.58747], [43.29075, 12.79154], [40.99158, 15.81743]]]]
24682           }
24683         }, {
24684           type: "Feature",
24685           properties: {
24686             iso1A2: "ES",
24687             iso1A3: "ESP",
24688             iso1N3: "724",
24689             wikidata: "Q29",
24690             nameEn: "Spain"
24691           },
24692           geometry: null
24693         }, {
24694           type: "Feature",
24695           properties: {
24696             iso1A2: "ET",
24697             iso1A3: "ETH",
24698             iso1N3: "231",
24699             wikidata: "Q115",
24700             nameEn: "Ethiopia",
24701             groups: ["014", "202", "002", "UN"],
24702             callingCodes: ["251"]
24703           },
24704           geometry: {
24705             type: "MultiPolygon",
24706             coordinates: [[[[42.4037, 12.46478], [42.2798, 12.6355], [42.21469, 12.75832], [42.05841, 12.80912], [41.62864, 13.38626], [41.25097, 13.60787], [40.9167, 14.11152], [40.25686, 14.41445], [40.21128, 14.39342], [40.14649, 14.53969], [40.07236, 14.54264], [39.9443, 14.41024], [39.76632, 14.54264], [39.58182, 14.60987], [39.50585, 14.55735], [39.52756, 14.49011], [39.37685, 14.54402], [39.2519, 14.40393], [39.2302, 14.44598], [39.26927, 14.48801], [39.23888, 14.56365], [39.19547, 14.56996], [39.14772, 14.61827], [39.16074, 14.65187], [39.02834, 14.63717], [38.98058, 14.54895], [38.78306, 14.4754], [38.45748, 14.41445], [38.3533, 14.51323], [38.25562, 14.67287], [38.0364, 14.72745], [37.91287, 14.89447], [37.528, 14.18413], [37.47319, 14.2149], [37.3106, 14.44657], [37.13206, 14.40746], [37.09486, 14.27155], [37.01622, 14.2561], [36.85787, 14.32201], [36.63364, 14.31172], [36.55659, 14.28237], [36.56536, 14.26177], [36.54376, 14.25597], [36.44653, 13.95666], [36.48824, 13.83954], [36.38993, 13.56459], [36.24545, 13.36759], [36.13374, 12.92665], [36.16651, 12.88019], [36.14268, 12.70879], [36.01458, 12.72478], [35.70476, 12.67101], [35.24302, 11.91132], [35.11492, 11.85156], [35.05832, 11.71158], [35.09556, 11.56278], [34.95704, 11.24448], [35.01215, 11.19626], [34.93172, 10.95946], [34.97789, 10.91559], [34.97491, 10.86147], [34.86916, 10.78832], [34.86618, 10.74588], [34.77532, 10.69027], [34.77383, 10.74588], [34.59062, 10.89072], [34.4372, 10.781], [34.2823, 10.53508], [34.34783, 10.23914], [34.32102, 10.11599], [34.22718, 10.02506], [34.20484, 9.9033], [34.13186, 9.7492], [34.08717, 9.55243], [34.10229, 9.50238], [34.14304, 9.04654], [34.14453, 8.60204], [34.01346, 8.50041], [33.89579, 8.4842], [33.87195, 8.41938], [33.71407, 8.3678], [33.66938, 8.44442], [33.54575, 8.47094], [33.3119, 8.45474], [33.19721, 8.40317], [33.1853, 8.29264], [33.18083, 8.13047], [33.08401, 8.05822], [33.0006, 7.90333], [33.04944, 7.78989], [33.24637, 7.77939], [33.32531, 7.71297], [33.44745, 7.7543], [33.71407, 7.65983], [33.87642, 7.5491], [34.02984, 7.36449], [34.03878, 7.27437], [34.01495, 7.25664], [34.19369, 7.12807], [34.19369, 7.04382], [34.35753, 6.91963], [34.47669, 6.91076], [34.53925, 6.82794], [34.53776, 6.74808], [34.65096, 6.72589], [34.77459, 6.5957], [34.87736, 6.60161], [35.01738, 6.46991], [34.96227, 6.26415], [35.00546, 5.89387], [35.12611, 5.68937], [35.13058, 5.62118], [35.31188, 5.50106], [35.29938, 5.34042], [35.50792, 5.42431], [35.8576, 5.33413], [35.81968, 5.10757], [35.82118, 4.77382], [35.9419, 4.61933], [35.95449, 4.53244], [36.03924, 4.44406], [36.84474, 4.44518], [37.07724, 4.33503], [38.14168, 3.62487], [38.45812, 3.60445], [38.52336, 3.62551], [38.91938, 3.51198], [39.07736, 3.5267], [39.19954, 3.47834], [39.49444, 3.45521], [39.51551, 3.40895], [39.55132, 3.39634], [39.58339, 3.47434], [39.76808, 3.67058], [39.86043, 3.86974], [40.77498, 4.27683], [41.1754, 3.94079], [41.89488, 3.97375], [42.07619, 4.17667], [42.55853, 4.20518], [42.84526, 4.28357], [42.97746, 4.44032], [43.04177, 4.57923], [43.40263, 4.79289], [44.02436, 4.9451], [44.98104, 4.91821], [47.97917, 8.00124], [47.92477, 8.00111], [46.99339, 7.9989], [44.19222, 8.93028], [43.32613, 9.59205], [43.23518, 9.84605], [43.0937, 9.90579], [42.87643, 10.18441], [42.69452, 10.62672], [42.95776, 10.98533], [42.79037, 10.98493], [42.75111, 11.06992], [42.62989, 11.09711], [42.42669, 10.98493], [42.13691, 10.97586], [42.06302, 10.92599], [41.80056, 10.97127], [41.8096, 11.33606], [41.77727, 11.49902], [41.82878, 11.72361], [41.95461, 11.81157], [42.4037, 12.46478]]]]
24707           }
24708         }, {
24709           type: "Feature",
24710           properties: {
24711             iso1A2: "EU",
24712             iso1A3: "EUE",
24713             wikidata: "Q458",
24714             nameEn: "European Union",
24715             level: "union",
24716             isoStatus: "excRes"
24717           },
24718           geometry: null
24719         }, {
24720           type: "Feature",
24721           properties: {
24722             iso1A2: "FI",
24723             iso1A3: "FIN",
24724             iso1N3: "246",
24725             wikidata: "Q33",
24726             nameEn: "Finland",
24727             aliases: ["SF"]
24728           },
24729           geometry: null
24730         }, {
24731           type: "Feature",
24732           properties: {
24733             iso1A2: "FJ",
24734             iso1A3: "FJI",
24735             iso1N3: "242",
24736             wikidata: "Q712",
24737             nameEn: "Fiji",
24738             groups: ["054", "009", "UN"],
24739             driveSide: "left",
24740             callingCodes: ["679"]
24741           },
24742           geometry: {
24743             type: "MultiPolygon",
24744             coordinates: [[[[174.245, -23.1974], [179.99999, -22.5], [179.99999, -11.5], [174, -11.5], [174.245, -23.1974]]], [[[-176.76826, -14.95183], [-180, -14.96041], [-180, -22.90585], [-176.74538, -22.89767], [-176.76826, -14.95183]]]]
24745           }
24746         }, {
24747           type: "Feature",
24748           properties: {
24749             iso1A2: "FK",
24750             iso1A3: "FLK",
24751             iso1N3: "238",
24752             wikidata: "Q9648",
24753             nameEn: "Falkland Islands",
24754             country: "GB",
24755             groups: ["BOTS", "005", "419", "019", "UN"],
24756             driveSide: "left",
24757             roadSpeedUnit: "mph",
24758             roadHeightUnit: "ft",
24759             callingCodes: ["500"]
24760           },
24761           geometry: {
24762             type: "MultiPolygon",
24763             coordinates: [[[[-63.67376, -55.11859], [-54.56126, -51.26248], [-61.26735, -50.63919], [-63.67376, -55.11859]]]]
24764           }
24765         }, {
24766           type: "Feature",
24767           properties: {
24768             iso1A2: "FM",
24769             iso1A3: "FSM",
24770             iso1N3: "583",
24771             wikidata: "Q702",
24772             nameEn: "Federated States of Micronesia",
24773             groups: ["057", "009", "UN"],
24774             roadSpeedUnit: "mph",
24775             roadHeightUnit: "ft",
24776             callingCodes: ["691"]
24777           },
24778           geometry: {
24779             type: "MultiPolygon",
24780             coordinates: [[[[138.20583, 13.3783], [136.27107, 6.73747], [156.88247, -1.39237], [165.19726, 6.22546], [138.20583, 13.3783]]]]
24781           }
24782         }, {
24783           type: "Feature",
24784           properties: {
24785             iso1A2: "FO",
24786             iso1A3: "FRO",
24787             iso1N3: "234",
24788             wikidata: "Q4628",
24789             nameEn: "Faroe Islands",
24790             country: "DK",
24791             groups: ["154", "150", "UN"],
24792             callingCodes: ["298"]
24793           },
24794           geometry: {
24795             type: "MultiPolygon",
24796             coordinates: [[[[-8.51774, 62.35338], [-6.51083, 60.95272], [-5.70102, 62.77194], [-8.51774, 62.35338]]]]
24797           }
24798         }, {
24799           type: "Feature",
24800           properties: {
24801             iso1A2: "FR",
24802             iso1A3: "FRA",
24803             iso1N3: "250",
24804             wikidata: "Q142",
24805             nameEn: "France"
24806           },
24807           geometry: null
24808         }, {
24809           type: "Feature",
24810           properties: {
24811             iso1A2: "FX",
24812             iso1A3: "FXX",
24813             iso1N3: "249",
24814             wikidata: "Q212429",
24815             nameEn: "Metropolitan France",
24816             country: "FR",
24817             groups: ["EU", "155", "150", "UN"],
24818             isoStatus: "excRes",
24819             callingCodes: ["33"]
24820           },
24821           geometry: {
24822             type: "MultiPolygon",
24823             coordinates: [[[[2.55904, 51.07014], [2.18458, 51.52087], [1.17405, 50.74239], [-2.02963, 49.91866], [-2.09454, 49.46288], [-1.83944, 49.23037], [-2.00491, 48.86706], [-2.65349, 49.15373], [-6.28985, 48.93406], [-1.81005, 43.59738], [-1.77289, 43.38957], [-1.79319, 43.37497], [-1.78332, 43.36399], [-1.78714, 43.35476], [-1.77068, 43.34396], [-1.75334, 43.34107], [-1.75079, 43.3317], [-1.7397, 43.32979], [-1.73074, 43.29481], [-1.69407, 43.31378], [-1.62481, 43.30726], [-1.63052, 43.28591], [-1.61341, 43.25269], [-1.57674, 43.25269], [-1.55963, 43.28828], [-1.50992, 43.29481], [-1.45289, 43.27049], [-1.40942, 43.27272], [-1.3758, 43.24511], [-1.41562, 43.12815], [-1.47555, 43.08372], [-1.44067, 43.047], [-1.35272, 43.02658], [-1.34419, 43.09665], [-1.32209, 43.1127], [-1.27118, 43.11961], [-1.30052, 43.09581], [-1.30531, 43.06859], [-1.25244, 43.04164], [-1.22881, 43.05534], [-1.10333, 43.0059], [-1.00963, 42.99279], [-0.97133, 42.96239], [-0.81652, 42.95166], [-0.75478, 42.96916], [-0.72037, 42.92541], [-0.73422, 42.91228], [-0.72608, 42.89318], [-0.69837, 42.87945], [-0.67637, 42.88303], [-0.55497, 42.77846], [-0.50863, 42.82713], [-0.44334, 42.79939], [-0.41319, 42.80776], [-0.38833, 42.80132], [-0.3122, 42.84788], [-0.17939, 42.78974], [-0.16141, 42.79535], [-0.10519, 42.72761], [-0.02468, 42.68513], [0.17569, 42.73424], [0.25336, 42.7174], [0.29407, 42.67431], [0.36251, 42.72282], [0.40214, 42.69779], [0.67873, 42.69458], [0.65421, 42.75872], [0.66121, 42.84021], [0.711, 42.86372], [0.93089, 42.79154], [0.96166, 42.80629], [0.98292, 42.78754], [1.0804, 42.78569], [1.15928, 42.71407], [1.35562, 42.71944], [1.44197, 42.60217], [1.47986, 42.61346], [1.46718, 42.63296], [1.48043, 42.65203], [1.50867, 42.64483], [1.55418, 42.65669], [1.60085, 42.62703], [1.63485, 42.62957], [1.6625, 42.61982], [1.68267, 42.62533], [1.73452, 42.61515], [1.72588, 42.59098], [1.7858, 42.57698], [1.73683, 42.55492], [1.72515, 42.50338], [1.76335, 42.48863], [1.83037, 42.48395], [1.88853, 42.4501], [1.93663, 42.45439], [1.94292, 42.44316], [1.94061, 42.43333], [1.94084, 42.43039], [1.9574, 42.42401], [1.96482, 42.37787], [2.00488, 42.35399], [2.06241, 42.35906], [2.11621, 42.38393], [2.12789, 42.41291], [2.16599, 42.42314], [2.20578, 42.41633], [2.25551, 42.43757], [2.38504, 42.39977], [2.43299, 42.39423], [2.43508, 42.37568], [2.48457, 42.33933], [2.54382, 42.33406], [2.55516, 42.35351], [2.57934, 42.35808], [2.6747, 42.33974], [2.65311, 42.38771], [2.72056, 42.42298], [2.75497, 42.42578], [2.77464, 42.41046], [2.84335, 42.45724], [2.85675, 42.45444], [2.86983, 42.46843], [2.88413, 42.45938], [2.92107, 42.4573], [2.94283, 42.48174], [2.96518, 42.46692], [3.03734, 42.47363], [3.08167, 42.42748], [3.10027, 42.42621], [3.11379, 42.43646], [3.17156, 42.43545], [3.75438, 42.33445], [7.60802, 41.05927], [10.09675, 41.44089], [9.56115, 43.20816], [7.50102, 43.51859], [7.42422, 43.72209], [7.40903, 43.7296], [7.41113, 43.73156], [7.41291, 43.73168], [7.41298, 43.73311], [7.41233, 43.73439], [7.42062, 43.73977], [7.42299, 43.74176], [7.42443, 43.74087], [7.42809, 43.74396], [7.43013, 43.74895], [7.43624, 43.75014], [7.43708, 43.75197], [7.4389, 43.75151], [7.4379, 43.74963], [7.47823, 43.73341], [7.53006, 43.78405], [7.50423, 43.84345], [7.49355, 43.86551], [7.51162, 43.88301], [7.56075, 43.89932], [7.56858, 43.94506], [7.60771, 43.95772], [7.65266, 43.9763], [7.66848, 43.99943], [7.6597, 44.03009], [7.72508, 44.07578], [7.66878, 44.12795], [7.68694, 44.17487], [7.63245, 44.17877], [7.62155, 44.14881], [7.36364, 44.11882], [7.34547, 44.14359], [7.27827, 44.1462], [7.16929, 44.20352], [7.00764, 44.23736], [6.98221, 44.28289], [6.89171, 44.36637], [6.88784, 44.42043], [6.94504, 44.43112], [6.86233, 44.49834], [6.85507, 44.53072], [6.96042, 44.62129], [6.95133, 44.66264], [7.00582, 44.69364], [7.07484, 44.68073], [7.00401, 44.78782], [7.02217, 44.82519], [6.93499, 44.8664], [6.90774, 44.84322], [6.75518, 44.89915], [6.74519, 44.93661], [6.74791, 45.01939], [6.66981, 45.02324], [6.62803, 45.11175], [6.7697, 45.16044], [6.85144, 45.13226], [6.96706, 45.20841], [7.07074, 45.21228], [7.13115, 45.25386], [7.10572, 45.32924], [7.18019, 45.40071], [7.00037, 45.509], [6.98948, 45.63869], [6.80785, 45.71864], [6.80785, 45.83265], [6.95315, 45.85163], [7.04151, 45.92435], [7.00946, 45.9944], [6.93862, 46.06502], [6.87868, 46.03855], [6.89321, 46.12548], [6.78968, 46.14058], [6.86052, 46.28512], [6.77152, 46.34784], [6.8024, 46.39171], [6.82312, 46.42661], [6.53358, 46.45431], [6.25432, 46.3632], [6.21981, 46.31304], [6.24826, 46.30175], [6.25137, 46.29014], [6.23775, 46.27822], [6.24952, 46.26255], [6.26749, 46.24745], [6.29474, 46.26221], [6.31041, 46.24417], [6.29663, 46.22688], [6.27694, 46.21566], [6.26007, 46.21165], [6.24821, 46.20531], [6.23913, 46.20511], [6.23544, 46.20714], [6.22175, 46.20045], [6.22222, 46.19888], [6.21844, 46.19837], [6.21603, 46.19507], [6.21273, 46.19409], [6.21114, 46.1927], [6.20539, 46.19163], [6.19807, 46.18369], [6.19552, 46.18401], [6.18707, 46.17999], [6.18871, 46.16644], [6.18116, 46.16187], [6.15305, 46.15194], [6.13397, 46.1406], [6.09926, 46.14373], [6.09199, 46.15191], [6.07491, 46.14879], [6.05203, 46.15191], [6.04564, 46.14031], [6.03614, 46.13712], [6.01791, 46.14228], [5.9871, 46.14499], [5.97893, 46.13303], [5.95781, 46.12925], [5.9641, 46.14412], [5.97508, 46.15863], [5.98188, 46.17392], [5.98846, 46.17046], [5.99573, 46.18587], [5.96515, 46.19638], [5.97542, 46.21525], [6.02461, 46.23313], [6.03342, 46.2383], [6.04602, 46.23127], [6.05029, 46.23518], [6.0633, 46.24583], [6.07072, 46.24085], [6.08563, 46.24651], [6.10071, 46.23772], [6.12446, 46.25059], [6.11926, 46.2634], [6.1013, 46.28512], [6.11697, 46.29547], [6.1198, 46.31157], [6.13876, 46.33844], [6.15738, 46.3491], [6.16987, 46.36759], [6.15985, 46.37721], [6.15016, 46.3778], [6.09926, 46.40768], [6.06407, 46.41676], [6.08427, 46.44305], [6.07269, 46.46244], [6.1567, 46.54402], [6.11084, 46.57649], [6.27135, 46.68251], [6.38351, 46.73171], [6.45209, 46.77502], [6.43216, 46.80336], [6.46456, 46.88865], [6.43341, 46.92703], [6.71531, 47.0494], [6.68823, 47.06616], [6.76788, 47.1208], [6.8489, 47.15933], [6.9508, 47.24338], [6.95108, 47.26428], [6.94316, 47.28747], [7.05305, 47.33304], [7.0564, 47.35134], [7.03125, 47.36996], [6.87959, 47.35335], [6.88542, 47.37262], [6.93744, 47.40714], [6.93953, 47.43388], [7.0024, 47.45264], [6.98425, 47.49432], [7.0231, 47.50522], [7.07425, 47.48863], [7.12781, 47.50371], [7.16249, 47.49025], [7.19583, 47.49455], [7.17026, 47.44312], [7.24669, 47.4205], [7.33526, 47.44186], [7.35603, 47.43432], [7.40308, 47.43638], [7.43088, 47.45846], [7.4462, 47.46264], [7.4583, 47.47216], [7.42923, 47.48628], [7.43356, 47.49712], [7.47534, 47.47932], [7.51076, 47.49651], [7.49804, 47.51798], [7.5229, 47.51644], [7.53199, 47.5284], [7.51904, 47.53515], [7.50588, 47.52856], [7.49691, 47.53821], [7.50873, 47.54546], [7.51723, 47.54578], [7.52831, 47.55347], [7.53634, 47.55553], [7.55652, 47.56779], [7.55689, 47.57232], [7.56548, 47.57617], [7.56684, 47.57785], [7.58386, 47.57536], [7.58945, 47.59017], [7.59301, 47.60058], [7.58851, 47.60794], [7.57423, 47.61628], [7.5591, 47.63849], [7.53384, 47.65115], [7.52067, 47.66437], [7.51915, 47.68335], [7.51266, 47.70197], [7.53722, 47.71635], [7.54761, 47.72912], [7.52921, 47.77747], [7.55673, 47.87371], [7.62302, 47.97898], [7.56966, 48.03265], [7.57137, 48.12292], [7.6648, 48.22219], [7.69022, 48.30018], [7.74562, 48.32736], [7.73109, 48.39192], [7.76833, 48.48945], [7.80647, 48.51239], [7.80167, 48.54758], [7.80057, 48.5857], [7.84098, 48.64217], [7.89002, 48.66317], [7.96812, 48.72491], [7.96994, 48.75606], [8.01534, 48.76085], [8.0326, 48.79017], [8.06802, 48.78957], [8.10253, 48.81829], [8.12813, 48.87985], [8.19989, 48.95825], [8.20031, 48.95856], [8.22604, 48.97352], [8.14189, 48.97833], [7.97783, 49.03161], [7.93641, 49.05544], [7.86386, 49.03499], [7.79557, 49.06583], [7.75948, 49.04562], [7.63618, 49.05428], [7.62575, 49.07654], [7.56416, 49.08136], [7.53012, 49.09818], [7.49172, 49.13915], [7.49473, 49.17], [7.44455, 49.16765], [7.44052, 49.18354], [7.3662, 49.17308], [7.35995, 49.14399], [7.3195, 49.14231], [7.29514, 49.11426], [7.23473, 49.12971], [7.1593, 49.1204], [7.1358, 49.1282], [7.12504, 49.14253], [7.10384, 49.13787], [7.10715, 49.15631], [7.07859, 49.15031], [7.09007, 49.13094], [7.07162, 49.1255], [7.06642, 49.11415], [7.05548, 49.11185], [7.04843, 49.11422], [7.04409, 49.12123], [7.04662, 49.13724], [7.03178, 49.15734], [7.0274, 49.17042], [7.03459, 49.19096], [7.01318, 49.19018], [6.97273, 49.2099], [6.95963, 49.203], [6.94028, 49.21641], [6.93831, 49.2223], [6.91875, 49.22261], [6.89298, 49.20863], [6.85939, 49.22376], [6.83555, 49.21249], [6.85119, 49.20038], [6.85016, 49.19354], [6.86225, 49.18185], [6.84703, 49.15734], [6.83385, 49.15162], [6.78265, 49.16793], [6.73765, 49.16375], [6.71137, 49.18808], [6.73256, 49.20486], [6.71843, 49.2208], [6.69274, 49.21661], [6.66583, 49.28065], [6.60186, 49.31055], [6.572, 49.35027], [6.58807, 49.35358], [6.60091, 49.36864], [6.533, 49.40748], [6.55404, 49.42464], [6.42432, 49.47683], [6.40274, 49.46546], [6.39168, 49.4667], [6.38352, 49.46463], [6.36778, 49.46937], [6.3687, 49.4593], [6.28818, 49.48465], [6.27875, 49.503], [6.25029, 49.50609], [6.2409, 49.51408], [6.19543, 49.50536], [6.17386, 49.50934], [6.15366, 49.50226], [6.16115, 49.49297], [6.14321, 49.48796], [6.12814, 49.49365], [6.12346, 49.4735], [6.10325, 49.4707], [6.09845, 49.46351], [6.10072, 49.45268], [6.08373, 49.45594], [6.07887, 49.46399], [6.05553, 49.46663], [6.04176, 49.44801], [6.02743, 49.44845], [6.02648, 49.45451], [5.97693, 49.45513], [5.96876, 49.49053], [5.94224, 49.49608], [5.94128, 49.50034], [5.86571, 49.50015], [5.83389, 49.52152], [5.83467, 49.52717], [5.84466, 49.53027], [5.83648, 49.5425], [5.81664, 49.53775], [5.80871, 49.5425], [5.81838, 49.54777], [5.79195, 49.55228], [5.77435, 49.56298], [5.7577, 49.55915], [5.75649, 49.54321], [5.64505, 49.55146], [5.60909, 49.51228], [5.55001, 49.52729], [5.46541, 49.49825], [5.46734, 49.52648], [5.43713, 49.5707], [5.3974, 49.61596], [5.34837, 49.62889], [5.33851, 49.61599], [5.3137, 49.61225], [5.30214, 49.63055], [5.33039, 49.6555], [5.31465, 49.66846], [5.26232, 49.69456], [5.14545, 49.70287], [5.09249, 49.76193], [4.96714, 49.79872], [4.85464, 49.78995], [4.86965, 49.82271], [4.85134, 49.86457], [4.88529, 49.9236], [4.78827, 49.95609], [4.8382, 50.06738], [4.88602, 50.15182], [4.83279, 50.15331], [4.82438, 50.16878], [4.75237, 50.11314], [4.70064, 50.09384], [4.68695, 49.99685], [4.5414, 49.96911], [4.51098, 49.94659], [4.43488, 49.94122], [4.35051, 49.95315], [4.31963, 49.97043], [4.20532, 49.95803], [4.14239, 49.98034], [4.13508, 50.01976], [4.16294, 50.04719], [4.23101, 50.06945], [4.20147, 50.13535], [4.13561, 50.13078], [4.16014, 50.19239], [4.15524, 50.21103], [4.21945, 50.25539], [4.20651, 50.27333], [4.17861, 50.27443], [4.17347, 50.28838], [4.15524, 50.2833], [4.16808, 50.25786], [4.13665, 50.25609], [4.11954, 50.30425], [4.10957, 50.30234], [4.10237, 50.31247], [4.0689, 50.3254], [4.0268, 50.35793], [3.96771, 50.34989], [3.90781, 50.32814], [3.84314, 50.35219], [3.73911, 50.34809], [3.70987, 50.3191], [3.71009, 50.30305], [3.66976, 50.34563], [3.65709, 50.36873], [3.67262, 50.38663], [3.67494, 50.40239], [3.66153, 50.45165], [3.64426, 50.46275], [3.61014, 50.49568], [3.58361, 50.49049], [3.5683, 50.50192], [3.49509, 50.48885], [3.51564, 50.5256], [3.47385, 50.53397], [3.44629, 50.51009], [3.37693, 50.49538], [3.28575, 50.52724], [3.2729, 50.60718], [3.23951, 50.6585], [3.264, 50.67668], [3.2536, 50.68977], [3.26141, 50.69151], [3.26063, 50.70086], [3.24593, 50.71389], [3.22042, 50.71019], [3.20845, 50.71662], [3.19017, 50.72569], [3.20064, 50.73547], [3.18811, 50.74025], [3.18339, 50.74981], [3.16476, 50.76843], [3.15017, 50.79031], [3.1257, 50.78603], [3.11987, 50.79188], [3.11206, 50.79416], [3.10614, 50.78303], [3.09163, 50.77717], [3.04314, 50.77674], [3.00537, 50.76588], [2.96778, 50.75242], [2.95019, 50.75138], [2.90873, 50.702], [2.91036, 50.6939], [2.90069, 50.69263], [2.88504, 50.70656], [2.87937, 50.70298], [2.86985, 50.7033], [2.8483, 50.72276], [2.81056, 50.71773], [2.71165, 50.81295], [2.63331, 50.81457], [2.59093, 50.91751], [2.63074, 50.94746], [2.57551, 51.00326], [2.55904, 51.07014]], [[1.99838, 42.44682], [1.98378, 42.44697], [1.96125, 42.45364], [1.95606, 42.45785], [1.96215, 42.47854], [1.97003, 42.48081], [1.97227, 42.48487], [1.97697, 42.48568], [1.98022, 42.49569], [1.98916, 42.49351], [1.99766, 42.4858], [1.98579, 42.47486], [1.99216, 42.46208], [2.01564, 42.45171], [1.99838, 42.44682]]]]
24824           }
24825         }, {
24826           type: "Feature",
24827           properties: {
24828             iso1A2: "GA",
24829             iso1A3: "GAB",
24830             iso1N3: "266",
24831             wikidata: "Q1000",
24832             nameEn: "Gabon",
24833             groups: ["017", "202", "002", "UN"],
24834             callingCodes: ["241"]
24835           },
24836           geometry: {
24837             type: "MultiPolygon",
24838             coordinates: [[[[13.29457, 2.16106], [13.28534, 2.25716], [11.37116, 2.29975], [11.3561, 2.17217], [11.35307, 1.00251], [9.79648, 1.0019], [9.75065, 1.06753], [9.66433, 1.06723], [7.24416, -0.64092], [10.75913, -4.39519], [11.12647, -3.94169], [11.22301, -3.69888], [11.48764, -3.51089], [11.57949, -3.52798], [11.68608, -3.68942], [11.87083, -3.71571], [11.92719, -3.62768], [11.8318, -3.5812], [11.96554, -3.30267], [11.70227, -3.17465], [11.70558, -3.0773], [11.80365, -3.00424], [11.64798, -2.81146], [11.5359, -2.85654], [11.64487, -2.61865], [11.57637, -2.33379], [11.74605, -2.39936], [11.96866, -2.33559], [12.04895, -2.41704], [12.47925, -2.32626], [12.44656, -1.92025], [12.61312, -1.8129], [12.82172, -1.91091], [13.02759, -2.33098], [13.47977, -2.43224], [13.75884, -2.09293], [13.92073, -2.35581], [13.85846, -2.46935], [14.10442, -2.49268], [14.23829, -2.33715], [14.16202, -2.23916], [14.23518, -2.15671], [14.25932, -1.97624], [14.41838, -1.89412], [14.52569, -0.57818], [14.41887, -0.44799], [14.2165, -0.38261], [14.06862, -0.20826], [13.90632, -0.2287], [13.88648, 0.26652], [14.10909, 0.58563], [14.26066, 0.57255], [14.48179, 0.9152], [14.25186, 1.39842], [13.89582, 1.4261], [13.15519, 1.23368], [13.25447, 1.32339], [13.13461, 1.57238], [13.29457, 2.16106]]]]
24839           }
24840         }, {
24841           type: "Feature",
24842           properties: {
24843             iso1A2: "GB",
24844             iso1A3: "GBR",
24845             iso1N3: "826",
24846             wikidata: "Q145",
24847             ccTLD: ".uk",
24848             nameEn: "United Kingdom",
24849             aliases: ["UK"]
24850           },
24851           geometry: null
24852         }, {
24853           type: "Feature",
24854           properties: {
24855             iso1A2: "GD",
24856             iso1A3: "GRD",
24857             iso1N3: "308",
24858             wikidata: "Q769",
24859             nameEn: "Grenada",
24860             aliases: ["WG"],
24861             groups: ["029", "003", "419", "019", "UN"],
24862             driveSide: "left",
24863             roadSpeedUnit: "mph",
24864             callingCodes: ["1 473"]
24865           },
24866           geometry: {
24867             type: "MultiPolygon",
24868             coordinates: [[[[-62.64026, 12.69984], [-61.77886, 11.36496], [-59.94058, 12.34011], [-62.64026, 12.69984]]]]
24869           }
24870         }, {
24871           type: "Feature",
24872           properties: {
24873             iso1A2: "GE",
24874             iso1A3: "GEO",
24875             iso1N3: "268",
24876             wikidata: "Q230",
24877             nameEn: "Georgia",
24878             groups: ["145", "142", "UN"],
24879             callingCodes: ["995"]
24880           },
24881           geometry: {
24882             type: "MultiPolygon",
24883             coordinates: [[[[46.42738, 41.91323], [45.61676, 42.20768], [45.78692, 42.48358], [45.36501, 42.55268], [45.15318, 42.70598], [44.88754, 42.74934], [44.80941, 42.61277], [44.70002, 42.74679], [44.54202, 42.75699], [43.95517, 42.55396], [43.73119, 42.62043], [43.81453, 42.74297], [43.0419, 43.02413], [43.03322, 43.08883], [42.75889, 43.19651], [42.66667, 43.13917], [42.40563, 43.23226], [41.64935, 43.22331], [40.65957, 43.56212], [40.10657, 43.57344], [40.04445, 43.47776], [40.03312, 43.44262], [40.01007, 43.42411], [40.01552, 43.42025], [40.00853, 43.40578], [40.0078, 43.38551], [39.81147, 43.06294], [40.89217, 41.72528], [41.54366, 41.52185], [41.7148, 41.4932], [41.7124, 41.47417], [41.81939, 41.43621], [41.95134, 41.52466], [42.26387, 41.49346], [42.51772, 41.43606], [42.59202, 41.58183], [42.72794, 41.59714], [42.84471, 41.58912], [42.78995, 41.50126], [42.84899, 41.47265], [42.8785, 41.50516], [43.02956, 41.37891], [43.21707, 41.30331], [43.13373, 41.25503], [43.1945, 41.25242], [43.23096, 41.17536], [43.36118, 41.2028], [43.44973, 41.17666], [43.4717, 41.12611], [43.67712, 41.13398], [43.74717, 41.1117], [43.84835, 41.16329], [44.16591, 41.19141], [44.18148, 41.24644], [44.32139, 41.2079], [44.34337, 41.20312], [44.34417, 41.2382], [44.46791, 41.18204], [44.59322, 41.1933], [44.61462, 41.24018], [44.72814, 41.20338], [44.82084, 41.21513], [44.87887, 41.20195], [44.89911, 41.21366], [44.84358, 41.23088], [44.81749, 41.23488], [44.80053, 41.25949], [44.81437, 41.30371], [44.93493, 41.25685], [45.0133, 41.29747], [45.09867, 41.34065], [45.1797, 41.42231], [45.26285, 41.46433], [45.31352, 41.47168], [45.4006, 41.42402], [45.45973, 41.45898], [45.68389, 41.3539], [45.71035, 41.36208], [45.75705, 41.35157], [45.69946, 41.29545], [45.80842, 41.2229], [45.95786, 41.17956], [46.13221, 41.19479], [46.27698, 41.19011], [46.37661, 41.10805], [46.456, 41.09984], [46.48558, 41.0576], [46.55096, 41.1104], [46.63969, 41.09515], [46.66148, 41.20533], [46.72375, 41.28609], [46.63658, 41.37727], [46.4669, 41.43331], [46.40307, 41.48464], [46.33925, 41.4963], [46.29794, 41.5724], [46.34126, 41.57454], [46.34039, 41.5947], [46.3253, 41.60912], [46.28182, 41.60089], [46.26531, 41.63339], [46.24429, 41.59883], [46.19759, 41.62327], [46.17891, 41.72094], [46.20538, 41.77205], [46.23962, 41.75811], [46.30863, 41.79133], [46.3984, 41.84399], [46.42738, 41.91323]]]]
24884           }
24885         }, {
24886           type: "Feature",
24887           properties: {
24888             iso1A2: "GF",
24889             iso1A3: "GUF",
24890             iso1N3: "254",
24891             wikidata: "Q3769",
24892             nameEn: "French Guiana",
24893             country: "FR",
24894             groups: ["Q3320166", "EU", "005", "419", "019", "UN"],
24895             callingCodes: ["594"]
24896           },
24897           geometry: {
24898             type: "MultiPolygon",
24899             coordinates: [[[[-51.35485, 4.8383], [-53.7094, 6.2264], [-54.01074, 5.68785], [-54.01877, 5.52789], [-54.26916, 5.26909], [-54.4717, 4.91964], [-54.38444, 4.13222], [-54.19367, 3.84387], [-54.05128, 3.63557], [-53.98914, 3.627], [-53.9849, 3.58697], [-54.28534, 2.67798], [-54.42864, 2.42442], [-54.6084, 2.32856], [-54.16286, 2.10779], [-53.78743, 2.34412], [-52.96539, 2.1881], [-52.6906, 2.37298], [-52.31787, 3.17896], [-51.85573, 3.83427], [-51.82312, 3.85825], [-51.79599, 3.89336], [-51.61983, 4.14596], [-51.63798, 4.51394], [-51.35485, 4.8383]]]]
24900           }
24901         }, {
24902           type: "Feature",
24903           properties: {
24904             iso1A2: "GG",
24905             iso1A3: "GGY",
24906             iso1N3: "831",
24907             wikidata: "Q25230",
24908             nameEn: "Bailiwick of Guernsey",
24909             country: "GB"
24910           },
24911           geometry: null
24912         }, {
24913           type: "Feature",
24914           properties: {
24915             iso1A2: "GH",
24916             iso1A3: "GHA",
24917             iso1N3: "288",
24918             wikidata: "Q117",
24919             nameEn: "Ghana",
24920             groups: ["011", "202", "002", "UN"],
24921             callingCodes: ["233"]
24922           },
24923           geometry: {
24924             type: "MultiPolygon",
24925             coordinates: [[[[-0.13493, 11.14075], [-0.27374, 11.17157], [-0.28566, 11.12713], [-0.35955, 11.07801], [-0.38219, 11.12596], [-0.42391, 11.11661], [-0.44298, 11.04292], [-0.61937, 10.91305], [-0.67143, 10.99811], [-2.83373, 11.0067], [-2.94232, 10.64281], [-2.83108, 10.40252], [-2.74174, 9.83172], [-2.76534, 9.56589], [-2.68802, 9.49343], [-2.69814, 9.22717], [-2.77799, 9.04949], [-2.66357, 9.01771], [-2.58243, 8.7789], [-2.49037, 8.20872], [-2.62901, 8.11495], [-2.61232, 8.02645], [-2.67787, 8.02055], [-2.74819, 7.92613], [-2.78395, 7.94974], [-2.79467, 7.86002], [-2.92339, 7.60847], [-2.97822, 7.27165], [-2.95438, 7.23737], [-3.23327, 6.81744], [-3.21954, 6.74407], [-3.25999, 6.62521], [-3.01896, 5.71697], [-2.95323, 5.71865], [-2.96671, 5.6415], [-2.93132, 5.62137], [-2.85378, 5.65156], [-2.76614, 5.60963], [-2.72737, 5.34789], [-2.77625, 5.34621], [-2.73074, 5.1364], [-2.75502, 5.10657], [-2.95261, 5.12477], [-2.96554, 5.10397], [-3.063, 5.13665], [-3.11073, 5.12675], [-3.10675, 5.08515], [-3.34019, 4.17519], [1.07031, 5.15655], [1.27574, 5.93551], [1.19771, 6.11522], [1.19966, 6.17069], [1.09187, 6.17074], [1.05969, 6.22998], [1.03108, 6.24064], [0.99652, 6.33779], [0.89283, 6.33779], [0.71048, 6.53083], [0.74862, 6.56517], [0.63659, 6.63857], [0.6497, 6.73682], [0.58176, 6.76049], [0.57406, 6.80348], [0.52853, 6.82921], [0.56508, 6.92971], [0.52098, 6.94391], [0.52217, 6.9723], [0.59606, 7.01252], [0.65327, 7.31643], [0.62943, 7.41099], [0.57223, 7.39326], [0.52455, 7.45354], [0.51979, 7.58706], [0.58295, 7.62368], [0.62943, 7.85751], [0.58891, 8.12779], [0.6056, 8.13959], [0.61156, 8.18324], [0.5913, 8.19622], [0.63897, 8.25873], [0.73432, 8.29529], [0.64731, 8.48866], [0.47211, 8.59945], [0.37319, 8.75262], [0.52455, 8.87746], [0.45424, 9.04581], [0.56388, 9.40697], [0.49118, 9.48339], [0.36485, 9.49749], [0.33148, 9.44812], [0.25758, 9.42696], [0.2254, 9.47869], [0.31241, 9.50337], [0.30406, 9.521], [0.2409, 9.52335], [0.23851, 9.57389], [0.38153, 9.58682], [0.36008, 9.6256], [0.29334, 9.59387], [0.26712, 9.66437], [0.28261, 9.69022], [0.32313, 9.6491], [0.34816, 9.66907], [0.34816, 9.71607], [0.32075, 9.72781], [0.36366, 10.03309], [0.41252, 10.02018], [0.41371, 10.06361], [0.35293, 10.09412], [0.39584, 10.31112], [0.33028, 10.30408], [0.29453, 10.41546], [0.18846, 10.4096], [0.12886, 10.53149], [-0.05945, 10.63458], [-0.09141, 10.7147], [-0.07327, 10.71845], [-0.07183, 10.76794], [-0.0228, 10.81916], [-0.02685, 10.8783], [-908e-5, 10.91644], [-63e-4, 10.96417], [0.03355, 10.9807], [0.02395, 11.06229], [342e-5, 11.08317], [-514e-5, 11.10763], [-0.0275, 11.11202], [-0.05733, 11.08628], [-0.14462, 11.10811], [-0.13493, 11.14075]]]]
24926           }
24927         }, {
24928           type: "Feature",
24929           properties: {
24930             iso1A2: "GI",
24931             iso1A3: "GIB",
24932             iso1N3: "292",
24933             wikidata: "Q1410",
24934             nameEn: "Gibraltar",
24935             country: "GB",
24936             groups: ["Q12837", "BOTS", "039", "150", "UN"],
24937             callingCodes: ["350"]
24938           },
24939           geometry: {
24940             type: "MultiPolygon",
24941             coordinates: [[[[-5.34064, 36.03744], [-5.27801, 36.14942], [-5.33822, 36.15272], [-5.34536, 36.15501], [-5.40526, 36.15488], [-5.34064, 36.03744]]]]
24942           }
24943         }, {
24944           type: "Feature",
24945           properties: {
24946             iso1A2: "GL",
24947             iso1A3: "GRL",
24948             iso1N3: "304",
24949             wikidata: "Q223",
24950             nameEn: "Greenland",
24951             country: "DK",
24952             groups: ["Q1451600", "021", "003", "019", "UN"],
24953             callingCodes: ["299"]
24954           },
24955           geometry: {
24956             type: "MultiPolygon",
24957             coordinates: [[[[-49.33696, 84.57952], [-68.21821, 80.48551], [-77.52957, 77.23408], [-46.37635, 57.3249], [-9.68082, 72.73731], [-5.7106, 84.28058], [-49.33696, 84.57952]]]]
24958           }
24959         }, {
24960           type: "Feature",
24961           properties: {
24962             iso1A2: "GM",
24963             iso1A3: "GMB",
24964             iso1N3: "270",
24965             wikidata: "Q1005",
24966             nameEn: "The Gambia",
24967             groups: ["011", "202", "002", "UN"],
24968             callingCodes: ["220"]
24969           },
24970           geometry: {
24971             type: "MultiPolygon",
24972             coordinates: [[[[-15.14917, 13.57989], [-14.36795, 13.23033], [-13.79409, 13.34472], [-13.8955, 13.59126], [-14.34721, 13.46578], [-14.93719, 13.80173], [-15.36504, 13.79313], [-15.47902, 13.58758], [-17.43598, 13.59273], [-17.43966, 13.04579], [-16.74676, 13.06025], [-16.69343, 13.16791], [-15.80355, 13.16729], [-15.80478, 13.34832], [-15.26908, 13.37768], [-15.14917, 13.57989]]]]
24973           }
24974         }, {
24975           type: "Feature",
24976           properties: {
24977             iso1A2: "GN",
24978             iso1A3: "GIN",
24979             iso1N3: "324",
24980             wikidata: "Q1006",
24981             nameEn: "Guinea",
24982             groups: ["011", "202", "002", "UN"],
24983             callingCodes: ["224"]
24984           },
24985           geometry: {
24986             type: "MultiPolygon",
24987             coordinates: [[[[-11.37536, 12.40788], [-11.46267, 12.44559], [-11.91331, 12.42008], [-12.35415, 12.32758], [-12.87336, 12.51892], [-13.06603, 12.49342], [-13.05296, 12.64003], [-13.70523, 12.68013], [-13.7039, 12.60313], [-13.65089, 12.49515], [-13.64168, 12.42764], [-13.70851, 12.24978], [-13.92745, 12.24077], [-13.94589, 12.16869], [-13.7039, 12.00869], [-13.7039, 11.70195], [-14.09799, 11.63649], [-14.26623, 11.67486], [-14.31513, 11.60713], [-14.51173, 11.49708], [-14.66677, 11.51188], [-14.77786, 11.36323], [-14.95993, 10.99244], [-15.07174, 10.89557], [-15.96748, 10.162], [-14.36218, 8.64107], [-13.29911, 9.04245], [-13.18586, 9.0925], [-13.08953, 9.0409], [-12.94095, 9.26335], [-12.76788, 9.3133], [-12.47254, 9.86834], [-12.24262, 9.92386], [-12.12634, 9.87203], [-11.91023, 9.93927], [-11.89624, 9.99763], [-11.2118, 10.00098], [-10.6534, 9.29919], [-10.74484, 9.07998], [-10.5783, 9.06386], [-10.56197, 8.81225], [-10.47707, 8.67669], [-10.61422, 8.5314], [-10.70565, 8.29235], [-10.63934, 8.35326], [-10.54891, 8.31174], [-10.37257, 8.48941], [-10.27575, 8.48711], [-10.203, 8.47991], [-10.14579, 8.52665], [-10.05375, 8.50697], [-10.05873, 8.42578], [-9.77763, 8.54633], [-9.47415, 8.35195], [-9.50898, 8.18455], [-9.41445, 8.02448], [-9.44928, 7.9284], [-9.35724, 7.74111], [-9.37465, 7.62032], [-9.48161, 7.37122], [-9.41943, 7.41809], [-9.305, 7.42056], [-9.20798, 7.38109], [-9.18311, 7.30461], [-9.09107, 7.1985], [-8.93435, 7.2824], [-8.85724, 7.26019], [-8.8448, 7.35149], [-8.72789, 7.51429], [-8.67814, 7.69428], [-8.55874, 7.70167], [-8.55874, 7.62525], [-8.47114, 7.55676], [-8.4003, 7.6285], [-8.21374, 7.54466], [-8.09931, 7.78626], [-8.13414, 7.87991], [-8.06449, 8.04989], [-7.94695, 8.00925], [-7.99919, 8.11023], [-7.98675, 8.20134], [-8.062, 8.16071], [-8.2411, 8.24196], [-8.22991, 8.48438], [-7.92518, 8.50652], [-7.65653, 8.36873], [-7.69882, 8.66148], [-7.95503, 8.81146], [-7.92518, 8.99332], [-7.73862, 9.08422], [-7.90777, 9.20456], [-7.85056, 9.41812], [-8.03463, 9.39604], [-8.14657, 9.55062], [-8.09434, 9.86936], [-8.15652, 9.94288], [-8.11921, 10.04577], [-8.01225, 10.1021], [-7.97971, 10.17117], [-7.9578, 10.2703], [-8.10207, 10.44649], [-8.22711, 10.41722], [-8.32614, 10.69273], [-8.2667, 10.91762], [-8.35083, 11.06234], [-8.66923, 10.99397], [-8.40058, 11.37466], [-8.80854, 11.66715], [-8.94784, 12.34842], [-9.13689, 12.50875], [-9.38067, 12.48446], [-9.32097, 12.29009], [-9.63938, 12.18312], [-9.714, 12.0226], [-10.30604, 12.24634], [-10.71897, 11.91552], [-10.80355, 12.1053], [-10.99758, 12.24634], [-11.24136, 12.01286], [-11.50006, 12.17826], [-11.37536, 12.40788]]]]
24988           }
24989         }, {
24990           type: "Feature",
24991           properties: {
24992             iso1A2: "GP",
24993             iso1A3: "GLP",
24994             iso1N3: "312",
24995             wikidata: "Q17012",
24996             nameEn: "Guadeloupe",
24997             country: "FR",
24998             groups: ["Q3320166", "EU", "029", "003", "419", "019", "UN"],
24999             callingCodes: ["590"]
25000           },
25001           geometry: {
25002             type: "MultiPolygon",
25003             coordinates: [[[[-60.03183, 16.1129], [-61.60296, 16.73066], [-63.00549, 15.26166], [-60.03183, 16.1129]]]]
25004           }
25005         }, {
25006           type: "Feature",
25007           properties: {
25008             iso1A2: "GQ",
25009             iso1A3: "GNQ",
25010             iso1N3: "226",
25011             wikidata: "Q983",
25012             nameEn: "Equatorial Guinea",
25013             groups: ["017", "202", "002", "UN"],
25014             callingCodes: ["240"]
25015           },
25016           geometry: {
25017             type: "MultiPolygon",
25018             coordinates: [[[[9.22018, 3.72052], [8.34397, 4.30689], [7.71762, 0.6674], [3.35016, -3.29031], [9.66433, 1.06723], [9.75065, 1.06753], [9.79648, 1.0019], [11.35307, 1.00251], [11.3561, 2.17217], [9.991, 2.16561], [9.90749, 2.20049], [9.89012, 2.20457], [9.84716, 2.24676], [9.83238, 2.29079], [9.83754, 2.32428], [9.82123, 2.35097], [9.81162, 2.33797], [9.22018, 3.72052]]]]
25019           }
25020         }, {
25021           type: "Feature",
25022           properties: {
25023             iso1A2: "GR",
25024             iso1A3: "GRC",
25025             iso1N3: "300",
25026             wikidata: "Q41",
25027             nameEn: "Greece",
25028             aliases: ["EL"],
25029             groups: ["EU", "039", "150", "UN"],
25030             callingCodes: ["30"]
25031           },
25032           geometry: {
25033             type: "MultiPolygon",
25034             coordinates: [[[[26.03489, 40.73051], [26.0754, 40.72772], [26.08638, 40.73214], [26.12495, 40.74283], [26.12854, 40.77339], [26.15685, 40.80709], [26.21351, 40.83298], [26.20856, 40.86048], [26.26169, 40.9168], [26.29441, 40.89119], [26.28623, 40.93005], [26.32259, 40.94042], [26.35894, 40.94292], [26.33297, 40.98388], [26.3606, 41.02027], [26.31928, 41.07386], [26.32259, 41.24929], [26.39861, 41.25053], [26.5209, 41.33993], [26.5837, 41.32131], [26.62997, 41.34613], [26.61767, 41.42281], [26.59742, 41.48058], [26.59196, 41.60491], [26.5209, 41.62592], [26.47958, 41.67037], [26.35957, 41.71149], [26.30255, 41.70925], [26.2654, 41.71544], [26.22888, 41.74139], [26.21325, 41.73223], [26.16841, 41.74858], [26.06148, 41.70345], [26.07083, 41.64584], [26.15146, 41.60828], [26.14328, 41.55496], [26.17951, 41.55409], [26.176, 41.50072], [26.14796, 41.47533], [26.20288, 41.43943], [26.16548, 41.42278], [26.12926, 41.35878], [25.87919, 41.30526], [25.8266, 41.34563], [25.70507, 41.29209], [25.66183, 41.31316], [25.61042, 41.30614], [25.55082, 41.31667], [25.52394, 41.2798], [25.48187, 41.28506], [25.28322, 41.23411], [25.11611, 41.34212], [24.942, 41.38685], [24.90928, 41.40876], [24.86136, 41.39298], [24.82514, 41.4035], [24.8041, 41.34913], [24.71529, 41.41928], [24.61129, 41.42278], [24.52599, 41.56808], [24.30513, 41.51297], [24.27124, 41.57682], [24.18126, 41.51735], [24.10063, 41.54796], [24.06323, 41.53222], [24.06908, 41.46132], [23.96975, 41.44118], [23.91483, 41.47971], [23.89613, 41.45257], [23.80148, 41.43943], [23.76525, 41.40175], [23.67644, 41.41139], [23.63203, 41.37632], [23.52453, 41.40262], [23.40416, 41.39999], [23.33639, 41.36317], [23.31301, 41.40525], [23.22771, 41.37106], [23.21953, 41.33773], [23.1833, 41.31755], [22.93334, 41.34104], [22.81199, 41.3398], [22.76408, 41.32225], [22.74538, 41.16321], [22.71266, 41.13945], [22.65306, 41.18168], [22.62852, 41.14385], [22.58295, 41.11568], [22.5549, 41.13065], [22.42285, 41.11921], [22.26744, 41.16409], [22.17629, 41.15969], [22.1424, 41.12449], [22.06527, 41.15617], [21.90869, 41.09191], [21.91102, 41.04786], [21.7556, 40.92525], [21.69601, 40.9429], [21.57448, 40.86076], [21.53007, 40.90759], [21.41555, 40.9173], [21.35595, 40.87578], [21.25779, 40.86165], [21.21105, 40.8855], [21.15262, 40.85546], [20.97887, 40.85475], [20.98396, 40.79109], [20.95752, 40.76982], [20.98134, 40.76046], [21.05833, 40.66586], [21.03932, 40.56299], [20.96908, 40.51526], [20.94925, 40.46625], [20.83688, 40.47882], [20.7906, 40.42726], [20.78234, 40.35803], [20.71789, 40.27739], [20.67162, 40.09433], [20.62566, 40.0897], [20.61081, 40.07866], [20.55593, 40.06524], [20.51297, 40.08168], [20.48487, 40.06271], [20.42373, 40.06777], [20.37911, 39.99058], [20.31135, 39.99438], [20.41546, 39.82832], [20.41475, 39.81437], [20.38572, 39.78516], [20.30804, 39.81563], [20.29152, 39.80421], [20.31961, 39.72799], [20.27412, 39.69884], [20.22707, 39.67459], [20.22376, 39.64532], [20.15988, 39.652], [20.12956, 39.65805], [20.05189, 39.69112], [20.00957, 39.69227], [19.98042, 39.6504], [19.92466, 39.69533], [19.97622, 39.78684], [19.95905, 39.82857], [19.0384, 40.35325], [19.20409, 39.7532], [22.5213, 33.45682], [29.73302, 35.92555], [29.69611, 36.10365], [29.61805, 36.14179], [29.61002, 36.1731], [29.48192, 36.18377], [29.30783, 36.01033], [28.23708, 36.56812], [27.95037, 36.46155], [27.89482, 36.69898], [27.46117, 36.53789], [27.24613, 36.71622], [27.45627, 36.9008], [27.20312, 36.94571], [27.14757, 37.32], [26.95583, 37.64989], [26.99377, 37.69034], [27.16428, 37.72343], [27.05537, 37.9131], [26.21136, 38.17558], [26.24183, 38.44695], [26.32173, 38.48731], [26.21136, 38.65436], [26.61814, 38.81372], [26.70773, 39.0312], [26.43357, 39.43096], [25.94257, 39.39358], [25.61285, 40.17161], [26.04292, 40.3958], [25.94795, 40.72797], [26.03489, 40.73051]]]]
25035           }
25036         }, {
25037           type: "Feature",
25038           properties: {
25039             iso1A2: "GS",
25040             iso1A3: "SGS",
25041             iso1N3: "239",
25042             wikidata: "Q35086",
25043             nameEn: "South Georgia and South Sandwich Islands",
25044             country: "GB",
25045             groups: ["BOTS", "005", "419", "019", "UN"],
25046             driveSide: "left",
25047             roadSpeedUnit: "mph",
25048             roadHeightUnit: "ft",
25049             callingCodes: ["500"]
25050           },
25051           geometry: {
25052             type: "MultiPolygon",
25053             coordinates: [[[[-35.26394, -43.68272], [-53.39656, -59.87088], [-22.31757, -59.85974], [-35.26394, -43.68272]]]]
25054           }
25055         }, {
25056           type: "Feature",
25057           properties: {
25058             iso1A2: "GT",
25059             iso1A3: "GTM",
25060             iso1N3: "320",
25061             wikidata: "Q774",
25062             nameEn: "Guatemala",
25063             groups: ["013", "003", "419", "019", "UN"],
25064             callingCodes: ["502"]
25065           },
25066           geometry: {
25067             type: "MultiPolygon",
25068             coordinates: [[[[-89.14985, 17.81563], [-90.98678, 17.81655], [-90.99199, 17.25192], [-91.43809, 17.25373], [-91.04436, 16.92175], [-90.69064, 16.70697], [-90.61212, 16.49832], [-90.40499, 16.40524], [-90.44567, 16.07573], [-91.73182, 16.07371], [-92.20983, 15.26077], [-92.0621, 15.07406], [-92.1454, 14.98143], [-92.1423, 14.88647], [-92.18161, 14.84147], [-92.1454, 14.6804], [-92.2261, 14.53423], [-92.37213, 14.39277], [-90.55276, 12.8866], [-90.11344, 13.73679], [-90.10505, 13.85104], [-89.88937, 14.0396], [-89.81807, 14.07073], [-89.76103, 14.02923], [-89.73251, 14.04133], [-89.75569, 14.07073], [-89.70756, 14.1537], [-89.61844, 14.21937], [-89.52397, 14.22628], [-89.50614, 14.26084], [-89.58814, 14.33165], [-89.57441, 14.41637], [-89.39028, 14.44561], [-89.34776, 14.43013], [-89.35189, 14.47553], [-89.23719, 14.58046], [-89.15653, 14.57802], [-89.13132, 14.71582], [-89.23467, 14.85596], [-89.15149, 14.97775], [-89.18048, 14.99967], [-89.15149, 15.07392], [-88.97343, 15.14039], [-88.32467, 15.63665], [-88.31459, 15.66942], [-88.24022, 15.69247], [-88.22552, 15.72294], [-88.20359, 16.03858], [-88.40779, 16.09624], [-88.95358, 15.88698], [-89.02415, 15.9063], [-89.17418, 15.90898], [-89.22683, 15.88619], [-89.15025, 17.04813], [-89.14985, 17.81563]]]]
25069           }
25070         }, {
25071           type: "Feature",
25072           properties: {
25073             iso1A2: "GU",
25074             iso1A3: "GUM",
25075             iso1N3: "316",
25076             wikidata: "Q16635",
25077             nameEn: "Guam",
25078             aliases: ["US-GU"],
25079             country: "US",
25080             groups: ["Q1352230", "Q153732", "057", "009", "UN"],
25081             roadSpeedUnit: "mph",
25082             roadHeightUnit: "ft",
25083             callingCodes: ["1 671"]
25084           },
25085           geometry: {
25086             type: "MultiPolygon",
25087             coordinates: [[[[146.25931, 13.85876], [143.82485, 13.92273], [144.61642, 12.82462], [146.25931, 13.85876]]]]
25088           }
25089         }, {
25090           type: "Feature",
25091           properties: {
25092             iso1A2: "GW",
25093             iso1A3: "GNB",
25094             iso1N3: "624",
25095             wikidata: "Q1007",
25096             nameEn: "Guinea-Bissau",
25097             groups: ["011", "202", "002", "UN"],
25098             callingCodes: ["245"]
25099           },
25100           geometry: {
25101             type: "MultiPolygon",
25102             coordinates: [[[[-14.31513, 11.60713], [-14.26623, 11.67486], [-14.09799, 11.63649], [-13.7039, 11.70195], [-13.7039, 12.00869], [-13.94589, 12.16869], [-13.92745, 12.24077], [-13.70851, 12.24978], [-13.64168, 12.42764], [-13.65089, 12.49515], [-13.7039, 12.60313], [-13.70523, 12.68013], [-15.17582, 12.6847], [-15.67302, 12.42974], [-16.20591, 12.46157], [-16.38191, 12.36449], [-16.70562, 12.34803], [-17.4623, 11.92379], [-15.96748, 10.162], [-15.07174, 10.89557], [-14.95993, 10.99244], [-14.77786, 11.36323], [-14.66677, 11.51188], [-14.51173, 11.49708], [-14.31513, 11.60713]]]]
25103           }
25104         }, {
25105           type: "Feature",
25106           properties: {
25107             iso1A2: "GY",
25108             iso1A3: "GUY",
25109             iso1N3: "328",
25110             wikidata: "Q734",
25111             nameEn: "Guyana",
25112             groups: ["005", "419", "019", "UN"],
25113             driveSide: "left",
25114             callingCodes: ["592"]
25115           },
25116           geometry: {
25117             type: "MultiPolygon",
25118             coordinates: [[[[-56.84822, 6.73257], [-59.54058, 8.6862], [-59.98508, 8.53046], [-59.85562, 8.35213], [-59.80661, 8.28906], [-59.83156, 8.23261], [-59.97059, 8.20791], [-60.02407, 8.04557], [-60.38056, 7.8302], [-60.51959, 7.83373], [-60.64793, 7.56877], [-60.71923, 7.55817], [-60.59802, 7.33194], [-60.63367, 7.25061], [-60.54098, 7.14804], [-60.44116, 7.20817], [-60.28074, 7.1162], [-60.39419, 6.94847], [-60.54873, 6.8631], [-61.13632, 6.70922], [-61.20762, 6.58174], [-61.15058, 6.19558], [-61.4041, 5.95304], [-60.73204, 5.20931], [-60.32352, 5.21299], [-60.20944, 5.28754], [-59.98129, 5.07097], [-60.04189, 4.69801], [-60.15953, 4.53456], [-59.78878, 4.45637], [-59.69361, 4.34069], [-59.73353, 4.20399], [-59.51963, 3.91951], [-59.86899, 3.57089], [-59.79769, 3.37162], [-59.99733, 2.92312], [-59.91177, 2.36759], [-59.7264, 2.27497], [-59.74066, 1.87596], [-59.25583, 1.40559], [-58.92072, 1.31293], [-58.84229, 1.17749], [-58.53571, 1.29154], [-58.4858, 1.48399], [-58.33887, 1.58014], [-58.01873, 1.51966], [-57.97336, 1.64566], [-57.77281, 1.73344], [-57.55743, 1.69605], [-57.35073, 1.98327], [-57.23981, 1.95808], [-57.09109, 2.01854], [-57.07092, 1.95304], [-56.7659, 1.89509], [-56.47045, 1.95135], [-56.55439, 2.02003], [-56.70519, 2.02964], [-57.35891, 3.32121], [-58.0307, 3.95513], [-57.8699, 4.89394], [-57.37442, 5.0208], [-57.22536, 5.15605], [-57.31629, 5.33714], [-56.84822, 6.73257]]]]
25119           }
25120         }, {
25121           type: "Feature",
25122           properties: {
25123             iso1A2: "HK",
25124             iso1A3: "HKG",
25125             iso1N3: "344",
25126             wikidata: "Q8646",
25127             nameEn: "Hong Kong",
25128             country: "CN",
25129             groups: ["030", "142", "UN"],
25130             driveSide: "left",
25131             callingCodes: ["852"]
25132           },
25133           geometry: {
25134             type: "MultiPolygon",
25135             coordinates: [[[[113.92195, 22.13873], [114.50148, 22.15017], [114.44998, 22.55977], [114.25154, 22.55977], [114.22888, 22.5436], [114.22185, 22.55343], [114.20655, 22.55706], [114.18338, 22.55444], [114.17247, 22.55944], [114.1597, 22.56041], [114.15123, 22.55163], [114.1482, 22.54091], [114.13823, 22.54319], [114.12665, 22.54003], [114.11656, 22.53415], [114.11181, 22.52878], [114.1034, 22.5352], [114.09692, 22.53435], [114.09048, 22.53716], [114.08606, 22.53276], [114.07817, 22.52997], [114.07267, 22.51855], [114.06272, 22.51617], [114.05729, 22.51104], [114.05438, 22.5026], [114.03113, 22.5065], [113.86771, 22.42972], [113.81621, 22.2163], [113.83338, 22.1826], [113.92195, 22.13873]]]]
25136           }
25137         }, {
25138           type: "Feature",
25139           properties: {
25140             iso1A2: "HM",
25141             iso1A3: "HMD",
25142             iso1N3: "334",
25143             wikidata: "Q131198",
25144             nameEn: "Heard Island and McDonald Islands",
25145             country: "AU",
25146             groups: ["053", "009", "UN"],
25147             driveSide: "left"
25148           },
25149           geometry: {
25150             type: "MultiPolygon",
25151             coordinates: [[[[71.08716, -53.87687], [75.44182, -53.99822], [72.87012, -51.48322], [71.08716, -53.87687]]]]
25152           }
25153         }, {
25154           type: "Feature",
25155           properties: {
25156             iso1A2: "HN",
25157             iso1A3: "HND",
25158             iso1N3: "340",
25159             wikidata: "Q783",
25160             nameEn: "Honduras",
25161             groups: ["013", "003", "419", "019", "UN"],
25162             callingCodes: ["504"]
25163           },
25164           geometry: {
25165             type: "MultiPolygon",
25166             coordinates: [[[[-83.86109, 17.73736], [-88.20359, 16.03858], [-88.22552, 15.72294], [-88.24022, 15.69247], [-88.31459, 15.66942], [-88.32467, 15.63665], [-88.97343, 15.14039], [-89.15149, 15.07392], [-89.18048, 14.99967], [-89.15149, 14.97775], [-89.23467, 14.85596], [-89.13132, 14.71582], [-89.15653, 14.57802], [-89.23719, 14.58046], [-89.35189, 14.47553], [-89.34776, 14.43013], [-89.04187, 14.33644], [-88.94608, 14.20207], [-88.85785, 14.17763], [-88.815, 14.11652], [-88.73182, 14.10919], [-88.70661, 14.04317], [-88.49738, 13.97224], [-88.48982, 13.86458], [-88.25791, 13.91108], [-88.23018, 13.99915], [-88.07641, 13.98447], [-88.00331, 13.86948], [-87.7966, 13.91353], [-87.68821, 13.80829], [-87.73106, 13.75443], [-87.78148, 13.52906], [-87.71657, 13.50577], [-87.72115, 13.46083], [-87.73841, 13.44169], [-87.77354, 13.45767], [-87.83467, 13.44655], [-87.84675, 13.41078], [-87.80177, 13.35689], [-87.73714, 13.32715], [-87.69751, 13.25228], [-87.55124, 13.12523], [-87.37107, 12.98646], [-87.06306, 13.00892], [-87.03785, 12.98682], [-86.93197, 13.05313], [-86.93383, 13.18677], [-86.87066, 13.30641], [-86.71267, 13.30348], [-86.76812, 13.79605], [-86.35219, 13.77157], [-86.14801, 14.04317], [-86.00685, 14.08474], [-86.03458, 13.99181], [-85.75477, 13.8499], [-85.73964, 13.9698], [-85.45762, 14.11304], [-85.32149, 14.2562], [-85.18602, 14.24929], [-85.1575, 14.53934], [-84.90082, 14.80489], [-84.82596, 14.82212], [-84.70119, 14.68078], [-84.48373, 14.63249], [-84.10584, 14.76353], [-83.89551, 14.76697], [-83.62101, 14.89448], [-83.49268, 15.01158], [-83.13724, 15.00002], [-83.04763, 15.03256], [-82.06974, 14.49418], [-81.58685, 18.0025], [-83.86109, 17.73736]]]]
25167           }
25168         }, {
25169           type: "Feature",
25170           properties: {
25171             iso1A2: "HR",
25172             iso1A3: "HRV",
25173             iso1N3: "191",
25174             wikidata: "Q224",
25175             nameEn: "Croatia",
25176             groups: ["EU", "039", "150", "UN"],
25177             callingCodes: ["385"]
25178           },
25179           geometry: {
25180             type: "MultiPolygon",
25181             coordinates: [[[[17.6444, 42.88641], [17.5392, 42.92787], [17.70879, 42.97223], [17.64268, 43.08595], [17.46986, 43.16559], [17.286, 43.33065], [17.25579, 43.40353], [17.29699, 43.44542], [17.24411, 43.49376], [17.15828, 43.49376], [17.00585, 43.58037], [16.80736, 43.76011], [16.75316, 43.77157], [16.70922, 43.84887], [16.55472, 43.95326], [16.50528, 44.0244], [16.43629, 44.02826], [16.43662, 44.07523], [16.36864, 44.08263], [16.18688, 44.27012], [16.21346, 44.35231], [16.12969, 44.38275], [16.16814, 44.40679], [16.10566, 44.52586], [16.03012, 44.55572], [16.00884, 44.58605], [16.05828, 44.61538], [15.89348, 44.74964], [15.8255, 44.71501], [15.72584, 44.82334], [15.79472, 44.8455], [15.76096, 44.87045], [15.74723, 44.96818], [15.78568, 44.97401], [15.74585, 45.0638], [15.78842, 45.11519], [15.76371, 45.16508], [15.83512, 45.22459], [15.98412, 45.23088], [16.12153, 45.09616], [16.29036, 44.99732], [16.35404, 45.00241], [16.35863, 45.03529], [16.3749, 45.05206], [16.38219, 45.05139], [16.38309, 45.05955], [16.40023, 45.1147], [16.4634, 45.14522], [16.49155, 45.21153], [16.52982, 45.22713], [16.5501, 45.2212], [16.56559, 45.22307], [16.60194, 45.23042], [16.64962, 45.20714], [16.74845, 45.20393], [16.78219, 45.19002], [16.81137, 45.18434], [16.83804, 45.18951], [16.92405, 45.27607], [16.9385, 45.22742], [17.0415, 45.20759], [17.18438, 45.14764], [17.24325, 45.146], [17.25131, 45.14957], [17.26815, 45.18444], [17.32092, 45.16246], [17.33573, 45.14521], [17.41229, 45.13335], [17.4498, 45.16119], [17.45615, 45.12523], [17.47589, 45.12656], [17.51469, 45.10791], [17.59104, 45.10816], [17.66571, 45.13408], [17.84826, 45.04489], [17.87148, 45.04645], [17.93706, 45.08016], [17.97336, 45.12245], [17.97834, 45.13831], [17.99479, 45.14958], [18.01594, 45.15163], [18.03121, 45.12632], [18.1624, 45.07654], [18.24387, 45.13699], [18.32077, 45.1021], [18.41896, 45.11083], [18.47939, 45.05871], [18.65723, 45.07544], [18.78357, 44.97741], [18.80661, 44.93561], [18.76369, 44.93707], [18.76347, 44.90669], [18.8704, 44.85097], [19.01994, 44.85493], [18.98957, 44.90645], [19.02871, 44.92541], [19.06853, 44.89915], [19.15573, 44.95409], [19.05205, 44.97692], [19.1011, 45.01191], [19.07952, 45.14668], [19.14063, 45.12972], [19.19144, 45.17863], [19.43589, 45.17137], [19.41941, 45.23475], [19.28208, 45.23813], [19.10774, 45.29547], [18.97446, 45.37528], [18.99918, 45.49333], [19.08364, 45.48804], [19.07471, 45.53086], [18.94562, 45.53712], [18.88776, 45.57253], [18.96691, 45.66731], [18.90305, 45.71863], [18.85783, 45.85493], [18.81394, 45.91329], [18.80211, 45.87995], [18.6792, 45.92057], [18.57483, 45.80772], [18.44368, 45.73972], [18.12439, 45.78905], [18.08869, 45.76511], [17.99805, 45.79671], [17.87377, 45.78522], [17.66545, 45.84207], [17.56821, 45.93728], [17.35672, 45.95209], [17.14592, 46.16697], [16.8903, 46.28122], [16.8541, 46.36255], [16.7154, 46.39523], [16.6639, 46.45203], [16.59527, 46.47524], [16.52604, 46.47831], [16.5007, 46.49644], [16.44036, 46.5171], [16.38771, 46.53608], [16.37193, 46.55008], [16.29793, 46.5121], [16.26733, 46.51505], [16.26759, 46.50566], [16.23961, 46.49653], [16.25124, 46.48067], [16.27398, 46.42875], [16.27329, 46.41467], [16.30162, 46.40437], [16.30233, 46.37837], [16.18824, 46.38282], [16.14859, 46.40547], [16.05281, 46.39141], [16.05065, 46.3833], [16.07314, 46.36458], [16.07616, 46.3463], [15.97965, 46.30652], [15.79284, 46.25811], [15.78817, 46.21719], [15.75479, 46.20336], [15.75436, 46.21969], [15.67395, 46.22478], [15.6434, 46.21396], [15.64904, 46.19229], [15.59909, 46.14761], [15.6083, 46.11992], [15.62317, 46.09103], [15.72977, 46.04682], [15.71246, 46.01196], [15.70327, 46.00015], [15.70636, 45.92116], [15.67967, 45.90455], [15.68383, 45.88867], [15.68232, 45.86819], [15.70411, 45.8465], [15.66662, 45.84085], [15.64185, 45.82915], [15.57952, 45.84953], [15.52234, 45.82195], [15.47325, 45.8253], [15.47531, 45.79802], [15.40836, 45.79491], [15.25423, 45.72275], [15.30872, 45.69014], [15.34919, 45.71623], [15.4057, 45.64727], [15.38952, 45.63682], [15.34214, 45.64702], [15.34695, 45.63382], [15.31027, 45.6303], [15.27747, 45.60504], [15.29837, 45.5841], [15.30249, 45.53224], [15.38188, 45.48752], [15.33051, 45.45258], [15.27758, 45.46678], [15.16862, 45.42309], [15.05187, 45.49079], [15.02385, 45.48533], [14.92266, 45.52788], [14.90554, 45.47769], [14.81992, 45.45913], [14.80124, 45.49515], [14.71718, 45.53442], [14.68605, 45.53006], [14.69694, 45.57366], [14.59576, 45.62812], [14.60977, 45.66403], [14.57397, 45.67165], [14.53816, 45.6205], [14.5008, 45.60852], [14.49769, 45.54424], [14.36693, 45.48642], [14.32487, 45.47142], [14.27681, 45.4902], [14.26611, 45.48239], [14.24239, 45.50607], [14.22371, 45.50388], [14.20348, 45.46896], [14.07116, 45.48752], [14.00578, 45.52352], [13.96063, 45.50825], [13.99488, 45.47551], [13.97309, 45.45258], [13.90771, 45.45149], [13.88124, 45.42637], [13.81742, 45.43729], [13.7785, 45.46787], [13.67398, 45.4436], [13.62902, 45.45898], [13.56979, 45.4895], [13.45644, 45.59464], [13.05142, 45.33128], [13.12821, 44.48877], [16.15283, 42.18525], [18.45131, 42.21682], [18.54128, 42.39171], [18.52152, 42.42302], [18.43588, 42.48556], [18.44307, 42.51077], [18.43735, 42.55921], [18.36197, 42.61423], [18.24318, 42.6112], [17.88201, 42.83668], [17.80854, 42.9182], [17.7948, 42.89556], [17.68151, 42.92725], [17.6444, 42.88641]]]]
25182           }
25183         }, {
25184           type: "Feature",
25185           properties: {
25186             iso1A2: "HT",
25187             iso1A3: "HTI",
25188             iso1N3: "332",
25189             wikidata: "Q790",
25190             nameEn: "Haiti",
25191             aliases: ["RH"],
25192             groups: ["029", "003", "419", "019", "UN"],
25193             callingCodes: ["509"]
25194           },
25195           geometry: {
25196             type: "MultiPolygon",
25197             coordinates: [[[[-71.71885, 18.78423], [-71.72624, 18.87802], [-71.77766, 18.95007], [-71.88102, 18.95007], [-71.74088, 19.0437], [-71.71088, 19.08353], [-71.69938, 19.10916], [-71.65337, 19.11759], [-71.62642, 19.21212], [-71.73229, 19.26686], [-71.77766, 19.33823], [-71.69448, 19.37866], [-71.6802, 19.45008], [-71.71268, 19.53374], [-71.71449, 19.55364], [-71.7429, 19.58445], [-71.75865, 19.70231], [-71.77419, 19.73128], [-72.38946, 20.27111], [-73.37289, 20.43199], [-74.7289, 18.71009], [-74.76465, 18.06252], [-72.29523, 17.48026], [-71.75671, 18.03456], [-71.73783, 18.07177], [-71.74994, 18.11115], [-71.75465, 18.14405], [-71.78271, 18.18302], [-71.69952, 18.34101], [-71.90875, 18.45821], [-71.88102, 18.50125], [-72.00201, 18.62312], [-71.95412, 18.64939], [-71.82556, 18.62551], [-71.71885, 18.78423]]]]
25198           }
25199         }, {
25200           type: "Feature",
25201           properties: {
25202             iso1A2: "HU",
25203             iso1A3: "HUN",
25204             iso1N3: "348",
25205             wikidata: "Q28",
25206             nameEn: "Hungary",
25207             groups: ["EU", "151", "150", "UN"],
25208             callingCodes: ["36"]
25209           },
25210           geometry: {
25211             type: "MultiPolygon",
25212             coordinates: [[[[21.72525, 48.34628], [21.67134, 48.3989], [21.6068, 48.50365], [21.44063, 48.58456], [21.11516, 48.49546], [20.83248, 48.5824], [20.5215, 48.53336], [20.29943, 48.26104], [20.24312, 48.2784], [19.92452, 48.1283], [19.63338, 48.25006], [19.52489, 48.19791], [19.47957, 48.09437], [19.28182, 48.08336], [19.23924, 48.0595], [19.01952, 48.07052], [18.82176, 48.04206], [18.76134, 47.97499], [18.76821, 47.87469], [18.8506, 47.82308], [18.74074, 47.8157], [18.66521, 47.76772], [18.56496, 47.76588], [18.29305, 47.73541], [18.02938, 47.75665], [17.71215, 47.7548], [17.23699, 48.02094], [17.16001, 48.00636], [17.09786, 47.97336], [17.11022, 47.92461], [17.08275, 47.87719], [17.00997, 47.86245], [17.07039, 47.81129], [17.05048, 47.79377], [17.08893, 47.70928], [16.87538, 47.68895], [16.86509, 47.72268], [16.82938, 47.68432], [16.7511, 47.67878], [16.72089, 47.73469], [16.65679, 47.74197], [16.61183, 47.76171], [16.54779, 47.75074], [16.53514, 47.73837], [16.55129, 47.72268], [16.4222, 47.66537], [16.58699, 47.61772], [16.64193, 47.63114], [16.71059, 47.52692], [16.64821, 47.50155], [16.6718, 47.46139], [16.57152, 47.40868], [16.52414, 47.41007], [16.49908, 47.39416], [16.45104, 47.41181], [16.47782, 47.25918], [16.44142, 47.25079], [16.43663, 47.21127], [16.41739, 47.20649], [16.42801, 47.18422], [16.4523, 47.18812], [16.46442, 47.16845], [16.44932, 47.14418], [16.52863, 47.13974], [16.46134, 47.09395], [16.52176, 47.05747], [16.43936, 47.03548], [16.51369, 47.00084], [16.28202, 47.00159], [16.27594, 46.9643], [16.22403, 46.939], [16.19904, 46.94134], [16.10983, 46.867], [16.14365, 46.8547], [16.15711, 46.85434], [16.21892, 46.86961], [16.2365, 46.87775], [16.2941, 46.87137], [16.34547, 46.83836], [16.3408, 46.80641], [16.31303, 46.79838], [16.30966, 46.7787], [16.37816, 46.69975], [16.42641, 46.69228], [16.41863, 46.66238], [16.38594, 46.6549], [16.39217, 46.63673], [16.50139, 46.56684], [16.52885, 46.53303], [16.52604, 46.5051], [16.59527, 46.47524], [16.6639, 46.45203], [16.7154, 46.39523], [16.8541, 46.36255], [16.8903, 46.28122], [17.14592, 46.16697], [17.35672, 45.95209], [17.56821, 45.93728], [17.66545, 45.84207], [17.87377, 45.78522], [17.99805, 45.79671], [18.08869, 45.76511], [18.12439, 45.78905], [18.44368, 45.73972], [18.57483, 45.80772], [18.6792, 45.92057], [18.80211, 45.87995], [18.81394, 45.91329], [18.99712, 45.93537], [19.01284, 45.96529], [19.0791, 45.96458], [19.10388, 46.04015], [19.14543, 45.9998], [19.28826, 45.99694], [19.52473, 46.1171], [19.56113, 46.16824], [19.66007, 46.19005], [19.81491, 46.1313], [19.93508, 46.17553], [20.01816, 46.17696], [20.03533, 46.14509], [20.09713, 46.17315], [20.26068, 46.12332], [20.28324, 46.1438], [20.35573, 46.16629], [20.45377, 46.14405], [20.49718, 46.18721], [20.63863, 46.12728], [20.76085, 46.21002], [20.74574, 46.25467], [20.86797, 46.28884], [21.06572, 46.24897], [21.16872, 46.30118], [21.28061, 46.44941], [21.26929, 46.4993], [21.33214, 46.63035], [21.43926, 46.65109], [21.5151, 46.72147], [21.48935, 46.7577], [21.52028, 46.84118], [21.59307, 46.86935], [21.59581, 46.91628], [21.68645, 46.99595], [21.648, 47.03902], [21.78395, 47.11104], [21.94463, 47.38046], [22.01055, 47.37767], [22.03389, 47.42508], [22.00917, 47.50492], [22.31816, 47.76126], [22.41979, 47.7391], [22.46559, 47.76583], [22.67247, 47.7871], [22.76617, 47.8417], [22.77991, 47.87211], [22.89849, 47.95851], [22.84276, 47.98602], [22.87847, 48.04665], [22.81804, 48.11363], [22.73427, 48.12005], [22.66835, 48.09162], [22.58733, 48.10813], [22.59007, 48.15121], [22.49806, 48.25189], [22.38133, 48.23726], [22.2083, 48.42534], [22.14689, 48.4005], [21.83339, 48.36242], [21.8279, 48.33321], [21.72525, 48.34628]]]]
25213           }
25214         }, {
25215           type: "Feature",
25216           properties: {
25217             iso1A2: "IC",
25218             wikidata: "Q5813",
25219             nameEn: "Canary Islands",
25220             country: "ES",
25221             groups: ["Q3320166", "Q105472", "EU", "039", "150", "UN"],
25222             isoStatus: "excRes",
25223             callingCodes: ["34"]
25224           },
25225           geometry: {
25226             type: "MultiPolygon",
25227             coordinates: [[[[-12.00985, 30.24121], [-25.3475, 27.87574], [-14.43883, 27.02969], [-12.00985, 30.24121]]]]
25228           }
25229         }, {
25230           type: "Feature",
25231           properties: {
25232             iso1A2: "ID",
25233             iso1A3: "IDN",
25234             iso1N3: "360",
25235             wikidata: "Q252",
25236             nameEn: "Indonesia",
25237             aliases: ["RI"]
25238           },
25239           geometry: null
25240         }, {
25241           type: "Feature",
25242           properties: {
25243             iso1A2: "IE",
25244             iso1A3: "IRL",
25245             iso1N3: "372",
25246             wikidata: "Q27",
25247             nameEn: "Republic of Ireland",
25248             groups: ["EU", "Q22890", "154", "150", "UN"],
25249             driveSide: "left",
25250             callingCodes: ["353"]
25251           },
25252           geometry: {
25253             type: "MultiPolygon",
25254             coordinates: [[[[-6.26218, 54.09785], [-6.29003, 54.11278], [-6.32694, 54.09337], [-6.36279, 54.11248], [-6.36605, 54.07234], [-6.47849, 54.06947], [-6.62842, 54.03503], [-6.66264, 54.0666], [-6.6382, 54.17071], [-6.70175, 54.20218], [-6.74575, 54.18788], [-6.81583, 54.22791], [-6.85179, 54.29176], [-6.87775, 54.34682], [-7.02034, 54.4212], [-7.19145, 54.31296], [-7.14908, 54.22732], [-7.25012, 54.20063], [-7.26316, 54.13863], [-7.29493, 54.12013], [-7.29687, 54.1354], [-7.28017, 54.16714], [-7.29157, 54.17191], [-7.34005, 54.14698], [-7.30553, 54.11869], [-7.32834, 54.11475], [-7.44567, 54.1539], [-7.4799, 54.12239], [-7.55812, 54.12239], [-7.69501, 54.20731], [-7.81397, 54.20159], [-7.8596, 54.21779], [-7.87101, 54.29299], [-8.04555, 54.36292], [-8.179, 54.46763], [-8.04538, 54.48941], [-7.99812, 54.54427], [-7.8596, 54.53671], [-7.70315, 54.62077], [-7.93293, 54.66603], [-7.83352, 54.73854], [-7.75041, 54.7103], [-7.64449, 54.75265], [-7.54671, 54.74606], [-7.54508, 54.79401], [-7.47626, 54.83084], [-7.4473, 54.87003], [-7.44404, 54.9403], [-7.40004, 54.94498], [-7.4033, 55.00391], [-7.34464, 55.04688], [-7.2471, 55.06933], [-6.34755, 55.49206], [-7.75229, 55.93854], [-22.01468, 48.19557], [-6.03913, 51.13217], [-5.37267, 53.63269], [-6.26218, 54.09785]]]]
25255           }
25256         }, {
25257           type: "Feature",
25258           properties: {
25259             iso1A2: "IL",
25260             iso1A3: "ISR",
25261             iso1N3: "376",
25262             wikidata: "Q801",
25263             nameEn: "Israel",
25264             groups: ["145", "142", "UN"],
25265             callingCodes: ["972"]
25266           },
25267           geometry: {
25268             type: "MultiPolygon",
25269             coordinates: [[[[34.052, 31.46619], [34.29262, 31.70393], [34.48681, 31.59711], [34.56797, 31.54197], [34.48892, 31.48365], [34.40077, 31.40926], [34.36505, 31.36404], [34.37381, 31.30598], [34.36523, 31.28963], [34.29417, 31.24194], [34.26742, 31.21998], [34.92298, 29.45305], [34.97718, 29.54294], [34.98207, 29.58147], [35.02147, 29.66343], [35.14108, 30.07374], [35.19183, 30.34636], [35.16218, 30.43535], [35.19595, 30.50297], [35.21379, 30.60401], [35.29311, 30.71365], [35.33456, 30.81224], [35.33984, 30.8802], [35.41371, 30.95565], [35.43658, 31.12444], [35.40316, 31.25535], [35.47672, 31.49578], [35.39675, 31.49572], [35.22921, 31.37445], [35.13033, 31.3551], [35.02459, 31.35979], [34.92571, 31.34337], [34.88932, 31.37093], [34.87833, 31.39321], [34.89756, 31.43891], [34.93258, 31.47816], [34.94356, 31.50743], [34.9415, 31.55601], [34.95249, 31.59813], [35.00879, 31.65426], [35.08226, 31.69107], [35.10782, 31.71594], [35.11895, 31.71454], [35.12933, 31.7325], [35.13931, 31.73012], [35.15119, 31.73634], [35.15474, 31.73352], [35.16478, 31.73242], [35.18023, 31.72067], [35.20538, 31.72388], [35.21937, 31.71578], [35.22392, 31.71899], [35.23972, 31.70896], [35.24315, 31.71244], [35.2438, 31.7201], [35.24981, 31.72543], [35.25182, 31.73945], [35.26319, 31.74846], [35.25225, 31.7678], [35.26058, 31.79064], [35.25573, 31.81362], [35.26404, 31.82567], [35.251, 31.83085], [35.25753, 31.8387], [35.24816, 31.8458], [35.2304, 31.84222], [35.2249, 31.85433], [35.22817, 31.8638], [35.22567, 31.86745], [35.22294, 31.87889], [35.22014, 31.88264], [35.2136, 31.88241], [35.21276, 31.88153], [35.21016, 31.88237], [35.20945, 31.8815], [35.20791, 31.8821], [35.20673, 31.88151], [35.20381, 31.86716], [35.21128, 31.863], [35.216, 31.83894], [35.21469, 31.81835], [35.19461, 31.82687], [35.18169, 31.82542], [35.18603, 31.80901], [35.14174, 31.81325], [35.07677, 31.85627], [35.05617, 31.85685], [35.01978, 31.82944], [34.9724, 31.83352], [34.99712, 31.85569], [35.03489, 31.85919], [35.03978, 31.89276], [35.03489, 31.92448], [35.00124, 31.93264], [34.98682, 31.96935], [35.00261, 32.027], [34.9863, 32.09551], [34.99437, 32.10962], [34.98507, 32.12606], [34.99039, 32.14626], [34.96009, 32.17503], [34.95703, 32.19522], [34.98885, 32.20758], [35.01841, 32.23981], [35.02939, 32.2671], [35.01119, 32.28684], [35.01772, 32.33863], [35.04243, 32.35008], [35.05142, 32.3667], [35.0421, 32.38242], [35.05311, 32.4024], [35.05423, 32.41754], [35.07059, 32.4585], [35.08564, 32.46948], [35.09236, 32.47614], [35.10024, 32.47856], [35.10882, 32.4757], [35.15937, 32.50466], [35.2244, 32.55289], [35.25049, 32.52453], [35.29306, 32.50947], [35.30685, 32.51024], [35.35212, 32.52047], [35.40224, 32.50136], [35.42034, 32.46009], [35.41598, 32.45593], [35.41048, 32.43706], [35.42078, 32.41562], [35.55807, 32.38674], [35.55494, 32.42687], [35.57485, 32.48669], [35.56614, 32.64393], [35.59813, 32.65159], [35.61669, 32.67999], [35.66527, 32.681], [35.68467, 32.70715], [35.75983, 32.74803], [35.78745, 32.77938], [35.83758, 32.82817], [35.84021, 32.8725], [35.87012, 32.91976], [35.89298, 32.9456], [35.87188, 32.98028], [35.84802, 33.1031], [35.81911, 33.11077], [35.81911, 33.1336], [35.84285, 33.16673], [35.83846, 33.19397], [35.81647, 33.2028], [35.81295, 33.24841], [35.77513, 33.27342], [35.813, 33.3172], [35.77477, 33.33609], [35.62019, 33.27278], [35.62283, 33.24226], [35.58502, 33.26653], [35.58326, 33.28381], [35.56523, 33.28969], [35.55555, 33.25844], [35.54544, 33.25513], [35.54808, 33.236], [35.5362, 33.23196], [35.54228, 33.19865], [35.52573, 33.11921], [35.50335, 33.114], [35.50272, 33.09056], [35.448, 33.09264], [35.43059, 33.06659], [35.35223, 33.05617], [35.31429, 33.10515], [35.1924, 33.08743], [35.10645, 33.09318], [34.78515, 33.20368], [33.62659, 31.82938], [34.052, 31.46619]]]]
25270           }
25271         }, {
25272           type: "Feature",
25273           properties: {
25274             iso1A2: "IM",
25275             iso1A3: "IMN",
25276             iso1N3: "833",
25277             wikidata: "Q9676",
25278             nameEn: "Isle of Man",
25279             country: "GB",
25280             groups: ["Q185086", "154", "150", "UN"],
25281             driveSide: "left",
25282             roadSpeedUnit: "mph",
25283             roadHeightUnit: "ft",
25284             callingCodes: ["44 01624", "44 07624", "44 07524", "44 07924"]
25285           },
25286           geometry: {
25287             type: "MultiPolygon",
25288             coordinates: [[[[-3.98763, 54.07351], [-4.1819, 54.57861], [-5.6384, 53.81157], [-3.98763, 54.07351]]]]
25289           }
25290         }, {
25291           type: "Feature",
25292           properties: {
25293             iso1A2: "IN",
25294             iso1A3: "IND",
25295             iso1N3: "356",
25296             wikidata: "Q668",
25297             nameEn: "India"
25298           },
25299           geometry: null
25300         }, {
25301           type: "Feature",
25302           properties: {
25303             iso1A2: "IO",
25304             iso1A3: "IOT",
25305             iso1N3: "086",
25306             wikidata: "Q43448",
25307             nameEn: "British Indian Ocean Territory",
25308             country: "GB"
25309           },
25310           geometry: null
25311         }, {
25312           type: "Feature",
25313           properties: {
25314             iso1A2: "IQ",
25315             iso1A3: "IRQ",
25316             iso1N3: "368",
25317             wikidata: "Q796",
25318             nameEn: "Iraq",
25319             groups: ["145", "142", "UN"],
25320             callingCodes: ["964"]
25321           },
25322           geometry: {
25323             type: "MultiPolygon",
25324             coordinates: [[[[42.78887, 37.38615], [42.56725, 37.14878], [42.35724, 37.10998], [42.36697, 37.0627], [41.81736, 36.58782], [41.40058, 36.52502], [41.28864, 36.35368], [41.2564, 36.06012], [41.37027, 35.84095], [41.38184, 35.62502], [41.26569, 35.42708], [41.21654, 35.1508], [41.2345, 34.80049], [41.12388, 34.65742], [40.97676, 34.39788], [40.64314, 34.31604], [38.79171, 33.37328], [39.08202, 32.50304], [38.98762, 32.47694], [39.04251, 32.30203], [39.26157, 32.35555], [39.29903, 32.23259], [40.01521, 32.05667], [42.97601, 30.72204], [42.97796, 30.48295], [44.72255, 29.19736], [46.42415, 29.05947], [46.5527, 29.10283], [46.89695, 29.50584], [47.15166, 30.01044], [47.37192, 30.10421], [47.7095, 30.10453], [48.01114, 29.98906], [48.06782, 30.02906], [48.17332, 30.02448], [48.40479, 29.85763], [48.59531, 29.66815], [48.83867, 29.78572], [48.61441, 29.93675], [48.51011, 29.96238], [48.44785, 30.00148], [48.4494, 30.04456], [48.43384, 30.08233], [48.38869, 30.11062], [48.38714, 30.13485], [48.41671, 30.17254], [48.41117, 30.19846], [48.26393, 30.3408], [48.24385, 30.33846], [48.21279, 30.31644], [48.19425, 30.32796], [48.18321, 30.39703], [48.14585, 30.44133], [48.02443, 30.4789], [48.03221, 30.9967], [47.68219, 31.00004], [47.6804, 31.39086], [47.86337, 31.78422], [47.64771, 32.07666], [47.52474, 32.15972], [47.57144, 32.20583], [47.37529, 32.47808], [47.17218, 32.45393], [46.46788, 32.91992], [46.32298, 32.9731], [46.17198, 32.95612], [46.09103, 32.98354], [46.15175, 33.07229], [46.03966, 33.09577], [46.05367, 33.13097], [46.11905, 33.11924], [46.20623, 33.20395], [45.99919, 33.5082], [45.86687, 33.49263], [45.96183, 33.55751], [45.89801, 33.63661], [45.77814, 33.60938], [45.50261, 33.94968], [45.42789, 33.9458], [45.41077, 33.97421], [45.47264, 34.03099], [45.56176, 34.15088], [45.58667, 34.30147], [45.53552, 34.35148], [45.49171, 34.3439], [45.46697, 34.38221], [45.43879, 34.45949], [45.51883, 34.47692], [45.53219, 34.60441], [45.59074, 34.55558], [45.60224, 34.55057], [45.73923, 34.54416], [45.70031, 34.69277], [45.65672, 34.7222], [45.68284, 34.76624], [45.70031, 34.82322], [45.73641, 34.83975], [45.79682, 34.85133], [45.78904, 34.91135], [45.86532, 34.89858], [45.89477, 34.95805], [45.87864, 35.03441], [45.92173, 35.0465], [45.92203, 35.09538], [45.93108, 35.08148], [45.94756, 35.09188], [46.06508, 35.03699], [46.07747, 35.0838], [46.11763, 35.07551], [46.19116, 35.11097], [46.15642, 35.1268], [46.16229, 35.16984], [46.19738, 35.18536], [46.18457, 35.22561], [46.11367, 35.23729], [46.15474, 35.2883], [46.13152, 35.32548], [46.05358, 35.38568], [45.98453, 35.49848], [46.01518, 35.52012], [45.97584, 35.58132], [46.03028, 35.57416], [46.01307, 35.59756], [46.0165, 35.61501], [45.99452, 35.63574], [46.0117, 35.65059], [46.01631, 35.69139], [46.23736, 35.71414], [46.34166, 35.78363], [46.32921, 35.82655], [46.17198, 35.8013], [46.08325, 35.8581], [45.94711, 35.82218], [45.89784, 35.83708], [45.81442, 35.82107], [45.76145, 35.79898], [45.6645, 35.92872], [45.60018, 35.96069], [45.55245, 35.99943], [45.46594, 36.00042], [45.38275, 35.97156], [45.33916, 35.99424], [45.37652, 36.06222], [45.37312, 36.09917], [45.32235, 36.17383], [45.30038, 36.27769], [45.26261, 36.3001], [45.27394, 36.35846], [45.23953, 36.43257], [45.11811, 36.40751], [45.00759, 36.5402], [45.06985, 36.62645], [45.06985, 36.6814], [45.01537, 36.75128], [44.84725, 36.77622], [44.83479, 36.81362], [44.90173, 36.86096], [44.91199, 36.91468], [44.89862, 37.01897], [44.81611, 37.04383], [44.75229, 37.11958], [44.78319, 37.1431], [44.76698, 37.16162], [44.63179, 37.19229], [44.42631, 37.05825], [44.38117, 37.05825], [44.35315, 37.04955], [44.35937, 37.02843], [44.30645, 36.97373], [44.25975, 36.98119], [44.18503, 37.09551], [44.22239, 37.15756], [44.27998, 37.16501], [44.2613, 37.25055], [44.13521, 37.32486], [44.02002, 37.33229], [43.90949, 37.22453], [43.84878, 37.22205], [43.82699, 37.19477], [43.8052, 37.22825], [43.7009, 37.23692], [43.63085, 37.21957], [43.56702, 37.25675], [43.50787, 37.24436], [43.33508, 37.33105], [43.30083, 37.30629], [43.11403, 37.37436], [42.93705, 37.32015], [42.78887, 37.38615]]]]
25325           }
25326         }, {
25327           type: "Feature",
25328           properties: {
25329             iso1A2: "IR",
25330             iso1A3: "IRN",
25331             iso1N3: "364",
25332             wikidata: "Q794",
25333             nameEn: "Iran",
25334             groups: ["034", "142", "UN"],
25335             callingCodes: ["98"]
25336           },
25337           geometry: {
25338             type: "MultiPolygon",
25339             coordinates: [[[[44.96746, 39.42998], [44.88916, 39.59653], [44.81043, 39.62677], [44.71806, 39.71124], [44.65422, 39.72163], [44.6137, 39.78393], [44.47298, 39.68788], [44.48111, 39.61579], [44.41849, 39.56659], [44.42832, 39.4131], [44.37921, 39.4131], [44.29818, 39.378], [44.22452, 39.4169], [44.03667, 39.39223], [44.1043, 39.19842], [44.20946, 39.13975], [44.18863, 38.93881], [44.30322, 38.81581], [44.26155, 38.71427], [44.28065, 38.6465], [44.32058, 38.62752], [44.3207, 38.49799], [44.3119, 38.37887], [44.38309, 38.36117], [44.44386, 38.38295], [44.50115, 38.33939], [44.42476, 38.25763], [44.22509, 37.88859], [44.3883, 37.85433], [44.45948, 37.77065], [44.55498, 37.783], [44.62096, 37.71985], [44.56887, 37.6429], [44.61401, 37.60165], [44.58449, 37.45018], [44.81021, 37.2915], [44.75986, 37.21549], [44.7868, 37.16644], [44.78319, 37.1431], [44.75229, 37.11958], [44.81611, 37.04383], [44.89862, 37.01897], [44.91199, 36.91468], [44.90173, 36.86096], [44.83479, 36.81362], [44.84725, 36.77622], [45.01537, 36.75128], [45.06985, 36.6814], [45.06985, 36.62645], [45.00759, 36.5402], [45.11811, 36.40751], [45.23953, 36.43257], [45.27394, 36.35846], [45.26261, 36.3001], [45.30038, 36.27769], [45.32235, 36.17383], [45.37312, 36.09917], [45.37652, 36.06222], [45.33916, 35.99424], [45.38275, 35.97156], [45.46594, 36.00042], [45.55245, 35.99943], [45.60018, 35.96069], [45.6645, 35.92872], [45.76145, 35.79898], [45.81442, 35.82107], [45.89784, 35.83708], [45.94711, 35.82218], [46.08325, 35.8581], [46.17198, 35.8013], [46.32921, 35.82655], [46.34166, 35.78363], [46.23736, 35.71414], [46.01631, 35.69139], [46.0117, 35.65059], [45.99452, 35.63574], [46.0165, 35.61501], [46.01307, 35.59756], [46.03028, 35.57416], [45.97584, 35.58132], [46.01518, 35.52012], [45.98453, 35.49848], [46.05358, 35.38568], [46.13152, 35.32548], [46.15474, 35.2883], [46.11367, 35.23729], [46.18457, 35.22561], [46.19738, 35.18536], [46.16229, 35.16984], [46.15642, 35.1268], [46.19116, 35.11097], [46.11763, 35.07551], [46.07747, 35.0838], [46.06508, 35.03699], [45.94756, 35.09188], [45.93108, 35.08148], [45.92203, 35.09538], [45.92173, 35.0465], [45.87864, 35.03441], [45.89477, 34.95805], [45.86532, 34.89858], [45.78904, 34.91135], [45.79682, 34.85133], [45.73641, 34.83975], [45.70031, 34.82322], [45.68284, 34.76624], [45.65672, 34.7222], [45.70031, 34.69277], [45.73923, 34.54416], [45.60224, 34.55057], [45.59074, 34.55558], [45.53219, 34.60441], [45.51883, 34.47692], [45.43879, 34.45949], [45.46697, 34.38221], [45.49171, 34.3439], [45.53552, 34.35148], [45.58667, 34.30147], [45.56176, 34.15088], [45.47264, 34.03099], [45.41077, 33.97421], [45.42789, 33.9458], [45.50261, 33.94968], [45.77814, 33.60938], [45.89801, 33.63661], [45.96183, 33.55751], [45.86687, 33.49263], [45.99919, 33.5082], [46.20623, 33.20395], [46.11905, 33.11924], [46.05367, 33.13097], [46.03966, 33.09577], [46.15175, 33.07229], [46.09103, 32.98354], [46.17198, 32.95612], [46.32298, 32.9731], [46.46788, 32.91992], [47.17218, 32.45393], [47.37529, 32.47808], [47.57144, 32.20583], [47.52474, 32.15972], [47.64771, 32.07666], [47.86337, 31.78422], [47.6804, 31.39086], [47.68219, 31.00004], [48.03221, 30.9967], [48.02443, 30.4789], [48.14585, 30.44133], [48.18321, 30.39703], [48.19425, 30.32796], [48.21279, 30.31644], [48.24385, 30.33846], [48.26393, 30.3408], [48.41117, 30.19846], [48.41671, 30.17254], [48.38714, 30.13485], [48.38869, 30.11062], [48.43384, 30.08233], [48.4494, 30.04456], [48.44785, 30.00148], [48.51011, 29.96238], [48.61441, 29.93675], [48.83867, 29.78572], [49.98877, 27.87827], [50.37726, 27.89227], [54.39838, 25.68383], [55.14145, 25.62624], [55.81777, 26.18798], [56.2644, 26.58649], [56.68954, 26.76645], [56.79239, 26.41236], [56.82555, 25.7713], [56.86325, 25.03856], [61.46682, 24.57869], [61.6433, 25.27541], [61.683, 25.66638], [61.83968, 25.7538], [61.83831, 26.07249], [61.89391, 26.26251], [62.05117, 26.31647], [62.21304, 26.26601], [62.31484, 26.528], [62.77352, 26.64099], [63.1889, 26.65072], [63.18688, 26.83844], [63.25005, 26.84212], [63.25005, 27.08692], [63.32283, 27.14437], [63.19649, 27.25674], [62.80604, 27.22412], [62.79684, 27.34381], [62.84905, 27.47627], [62.7638, 28.02992], [62.79412, 28.28108], [62.59499, 28.24842], [62.40259, 28.42703], [61.93581, 28.55284], [61.65978, 28.77937], [61.53765, 29.00507], [61.31508, 29.38903], [60.87231, 29.86514], [61.80829, 30.84224], [61.78268, 30.92724], [61.8335, 30.97669], [61.83257, 31.0452], [61.80957, 31.12576], [61.80569, 31.16167], [61.70929, 31.37391], [60.84541, 31.49561], [60.86191, 32.22565], [60.56485, 33.12944], [60.88908, 33.50219], [60.91133, 33.55596], [60.69573, 33.56054], [60.57762, 33.59772], [60.5485, 33.73422], [60.5838, 33.80793], [60.50209, 34.13992], [60.66502, 34.31539], [60.91321, 34.30411], [60.72316, 34.52857], [60.99922, 34.63064], [61.00197, 34.70631], [61.06926, 34.82139], [61.12831, 35.09938], [61.0991, 35.27845], [61.18187, 35.30249], [61.27371, 35.61482], [61.22719, 35.67038], [61.26152, 35.80749], [61.22444, 35.92879], [61.12007, 35.95992], [61.22719, 36.12759], [61.1393, 36.38782], [61.18187, 36.55348], [61.14516, 36.64644], [60.34767, 36.63214], [60.00768, 37.04102], [59.74678, 37.12499], [59.55178, 37.13594], [59.39385, 37.34257], [59.39797, 37.47892], [59.33507, 37.53146], [59.22905, 37.51161], [58.9338, 37.67374], [58.6921, 37.64548], [58.5479, 37.70526], [58.47786, 37.6433], [58.39959, 37.63134], [58.22999, 37.6856], [58.21399, 37.77281], [57.79534, 37.89299], [57.35042, 37.98546], [57.37236, 38.09321], [57.21169, 38.28965], [57.03453, 38.18717], [56.73928, 38.27887], [56.62255, 38.24005], [56.43303, 38.26054], [56.32454, 38.18502], [56.33278, 38.08132], [55.97847, 38.08024], [55.76561, 38.12238], [55.44152, 38.08564], [55.13412, 37.94705], [54.851, 37.75739], [54.77684, 37.62264], [54.81804, 37.61285], [54.77822, 37.51597], [54.67247, 37.43532], [54.58664, 37.45809], [54.36211, 37.34912], [54.24565, 37.32047], [53.89734, 37.3464], [48.88288, 38.43975], [48.84969, 38.45015], [48.81072, 38.44853], [48.78979, 38.45026], [48.70001, 38.40564], [48.62217, 38.40198], [48.58793, 38.45076], [48.45084, 38.61013], [48.3146, 38.59958], [48.24773, 38.71883], [48.02581, 38.82705], [48.01409, 38.90333], [48.07734, 38.91616], [48.08627, 38.94434], [48.28437, 38.97186], [48.33884, 39.03022], [48.31239, 39.09278], [48.15361, 39.19419], [48.12404, 39.25208], [48.15984, 39.30028], [48.37385, 39.37584], [48.34264, 39.42935], [47.98977, 39.70999], [47.84774, 39.66285], [47.50099, 39.49615], [47.38978, 39.45999], [47.31301, 39.37492], [47.05927, 39.24846], [47.05771, 39.20143], [46.95341, 39.13505], [46.92539, 39.16644], [46.83822, 39.13143], [46.75752, 39.03231], [46.53497, 38.86548], [46.34059, 38.92076], [46.20601, 38.85262], [46.14785, 38.84206], [46.06766, 38.87861], [46.00228, 38.87376], [45.94624, 38.89072], [45.90266, 38.87739], [45.83883, 38.90768], [45.65172, 38.95199], [45.6155, 38.94304], [45.6131, 38.964], [45.44966, 38.99243], [45.44811, 39.04927], [45.40452, 39.07224], [45.40148, 39.09007], [45.30489, 39.18333], [45.16168, 39.21952], [45.08751, 39.35052], [45.05932, 39.36435], [44.96746, 39.42998]]]]
25340           }
25341         }, {
25342           type: "Feature",
25343           properties: {
25344             iso1A2: "IS",
25345             iso1A3: "ISL",
25346             iso1N3: "352",
25347             wikidata: "Q189",
25348             nameEn: "Iceland",
25349             groups: ["154", "150", "UN"],
25350             callingCodes: ["354"]
25351           },
25352           geometry: {
25353             type: "MultiPolygon",
25354             coordinates: [[[[-33.15676, 62.62995], [-8.25539, 63.0423], [-15.70914, 69.67442], [-33.15676, 62.62995]]]]
25355           }
25356         }, {
25357           type: "Feature",
25358           properties: {
25359             iso1A2: "IT",
25360             iso1A3: "ITA",
25361             iso1N3: "380",
25362             wikidata: "Q38",
25363             nameEn: "Italy",
25364             groups: ["EU", "039", "150", "UN"],
25365             callingCodes: ["39"]
25366           },
25367           geometry: {
25368             type: "MultiPolygon",
25369             coordinates: [[[[8.95861, 45.96485], [8.97604, 45.96151], [8.97741, 45.98317], [8.96668, 45.98436], [8.95861, 45.96485]]], [[[7.63035, 43.57419], [9.56115, 43.20816], [10.09675, 41.44089], [7.60802, 41.05927], [7.89009, 38.19924], [11.2718, 37.6713], [12.13667, 34.20326], [14.02721, 36.53141], [17.67657, 35.68918], [18.83516, 40.36999], [16.15283, 42.18525], [13.12821, 44.48877], [13.05142, 45.33128], [13.45644, 45.59464], [13.6076, 45.64761], [13.7198, 45.59352], [13.74587, 45.59811], [13.78445, 45.5825], [13.84106, 45.58185], [13.86771, 45.59898], [13.8695, 45.60835], [13.9191, 45.6322], [13.87933, 45.65207], [13.83422, 45.68703], [13.83332, 45.70855], [13.8235, 45.7176], [13.66986, 45.79955], [13.59784, 45.8072], [13.58858, 45.83503], [13.57563, 45.8425], [13.58644, 45.88173], [13.59565, 45.89446], [13.60857, 45.89907], [13.61931, 45.91782], [13.63815, 45.93607], [13.6329, 45.94894], [13.64307, 45.98326], [13.63458, 45.98947], [13.62074, 45.98388], [13.58903, 45.99009], [13.56759, 45.96991], [13.52963, 45.96588], [13.50104, 45.98078], [13.47474, 46.00546], [13.49702, 46.01832], [13.50998, 46.04498], [13.49568, 46.04839], [13.50104, 46.05986], [13.57072, 46.09022], [13.64053, 46.13587], [13.66472, 46.17392], [13.64451, 46.18966], [13.56682, 46.18703], [13.56114, 46.2054], [13.47587, 46.22725], [13.42218, 46.20758], [13.37671, 46.29668], [13.44808, 46.33507], [13.43418, 46.35992], [13.47019, 46.3621], [13.5763, 46.40915], [13.5763, 46.42613], [13.59777, 46.44137], [13.68684, 46.43881], [13.7148, 46.5222], [13.64088, 46.53438], [13.27627, 46.56059], [12.94445, 46.60401], [12.59992, 46.6595], [12.38708, 46.71529], [12.27591, 46.88651], [12.2006, 46.88854], [12.11675, 47.01241], [12.21781, 47.03996], [12.19254, 47.09331], [11.74789, 46.98484], [11.50739, 47.00644], [11.33355, 46.99862], [11.10618, 46.92966], [11.00764, 46.76896], [10.72974, 46.78972], [10.75753, 46.82258], [10.66405, 46.87614], [10.54783, 46.84505], [10.47197, 46.85698], [10.38659, 46.67847], [10.40475, 46.63671], [10.44686, 46.64162], [10.49375, 46.62049], [10.46136, 46.53164], [10.25309, 46.57432], [10.23674, 46.63484], [10.10307, 46.61003], [10.03715, 46.44479], [10.165, 46.41051], [10.10506, 46.3372], [10.17862, 46.25626], [10.14439, 46.22992], [10.07055, 46.21668], [9.95249, 46.38045], [9.73086, 46.35071], [9.71273, 46.29266], [9.57015, 46.2958], [9.46117, 46.37481], [9.45936, 46.50873], [9.40487, 46.46621], [9.36128, 46.5081], [9.28136, 46.49685], [9.25502, 46.43743], [9.29226, 46.32717], [9.24503, 46.23616], [9.01618, 46.04928], [8.99257, 45.9698], [9.09065, 45.89906], [9.06642, 45.8761], [9.04546, 45.84968], [9.04059, 45.8464], [9.03505, 45.83976], [9.03793, 45.83548], [9.03279, 45.82865], [9.0298, 45.82127], [9.00324, 45.82055], [8.99663, 45.83466], [8.9621, 45.83707], [8.94737, 45.84285], [8.91129, 45.8388], [8.93504, 45.86245], [8.94372, 45.86587], [8.93649, 45.86775], [8.88904, 45.95465], [8.86688, 45.96135], [8.85121, 45.97239], [8.8319, 45.9879], [8.79362, 45.99207], [8.78585, 45.98973], [8.79414, 46.00913], [8.85617, 46.0748], [8.80778, 46.10085], [8.75697, 46.10395], [8.62242, 46.12112], [8.45032, 46.26869], [8.46317, 46.43712], [8.42464, 46.46367], [8.30648, 46.41587], [8.31162, 46.38044], [8.08814, 46.26692], [8.16866, 46.17817], [8.11383, 46.11577], [8.02906, 46.10331], [7.98881, 45.99867], [7.9049, 45.99945], [7.85949, 45.91485], [7.56343, 45.97421], [7.10685, 45.85653], [7.04151, 45.92435], [6.95315, 45.85163], [6.80785, 45.83265], [6.80785, 45.71864], [6.98948, 45.63869], [7.00037, 45.509], [7.18019, 45.40071], [7.10572, 45.32924], [7.13115, 45.25386], [7.07074, 45.21228], [6.96706, 45.20841], [6.85144, 45.13226], [6.7697, 45.16044], [6.62803, 45.11175], [6.66981, 45.02324], [6.74791, 45.01939], [6.74519, 44.93661], [6.75518, 44.89915], [6.90774, 44.84322], [6.93499, 44.8664], [7.02217, 44.82519], [7.00401, 44.78782], [7.07484, 44.68073], [7.00582, 44.69364], [6.95133, 44.66264], [6.96042, 44.62129], [6.85507, 44.53072], [6.86233, 44.49834], [6.94504, 44.43112], [6.88784, 44.42043], [6.89171, 44.36637], [6.98221, 44.28289], [7.00764, 44.23736], [7.16929, 44.20352], [7.27827, 44.1462], [7.34547, 44.14359], [7.36364, 44.11882], [7.62155, 44.14881], [7.63245, 44.17877], [7.68694, 44.17487], [7.66878, 44.12795], [7.72508, 44.07578], [7.6597, 44.03009], [7.66848, 43.99943], [7.65266, 43.9763], [7.60771, 43.95772], [7.56858, 43.94506], [7.56075, 43.89932], [7.51162, 43.88301], [7.49355, 43.86551], [7.50423, 43.84345], [7.53006, 43.78405], [7.63035, 43.57419]], [[12.45181, 41.90056], [12.44834, 41.90095], [12.44582, 41.90194], [12.44815, 41.90326], [12.44984, 41.90545], [12.45091, 41.90625], [12.45543, 41.90738], [12.45561, 41.90629], [12.45762, 41.9058], [12.45755, 41.9033], [12.45826, 41.90281], [12.45834, 41.90174], [12.4577, 41.90115], [12.45691, 41.90125], [12.45626, 41.90172], [12.45435, 41.90143], [12.45446, 41.90028], [12.45181, 41.90056]], [[12.45648, 43.89369], [12.44184, 43.90498], [12.41641, 43.89991], [12.40935, 43.9024], [12.41233, 43.90956], [12.40733, 43.92379], [12.41551, 43.92984], [12.41165, 43.93769], [12.40506, 43.94325], [12.40415, 43.95485], [12.41414, 43.95273], [12.42005, 43.9578], [12.43662, 43.95698], [12.44684, 43.96597], [12.46205, 43.97463], [12.47853, 43.98052], [12.49406, 43.98492], [12.50678, 43.99113], [12.51463, 43.99122], [12.5154, 43.98508], [12.51064, 43.98165], [12.51109, 43.97201], [12.50622, 43.97131], [12.50875, 43.96198], [12.50655, 43.95796], [12.51427, 43.94897], [12.51553, 43.94096], [12.50496, 43.93017], [12.50269, 43.92363], [12.49724, 43.92248], [12.49247, 43.91774], [12.49429, 43.90973], [12.48771, 43.89706], [12.45648, 43.89369]]]]
25370           }
25371         }, {
25372           type: "Feature",
25373           properties: {
25374             iso1A2: "JE",
25375             iso1A3: "JEY",
25376             iso1N3: "832",
25377             wikidata: "Q785",
25378             nameEn: "Bailiwick of Jersey",
25379             country: "GB",
25380             groups: ["830", "Q185086", "154", "150", "UN"],
25381             driveSide: "left",
25382             roadSpeedUnit: "mph",
25383             roadHeightUnit: "ft",
25384             callingCodes: ["44 01534"]
25385           },
25386           geometry: {
25387             type: "MultiPolygon",
25388             coordinates: [[[[-2.00491, 48.86706], [-1.83944, 49.23037], [-2.09454, 49.46288], [-2.65349, 49.15373], [-2.00491, 48.86706]]]]
25389           }
25390         }, {
25391           type: "Feature",
25392           properties: {
25393             iso1A2: "JM",
25394             iso1A3: "JAM",
25395             iso1N3: "388",
25396             wikidata: "Q766",
25397             nameEn: "Jamaica",
25398             aliases: ["JA"],
25399             groups: ["029", "003", "419", "019", "UN"],
25400             driveSide: "left",
25401             callingCodes: ["1 876", "1 658"]
25402           },
25403           geometry: {
25404             type: "MultiPolygon",
25405             coordinates: [[[[-74.09729, 17.36817], [-78.9741, 19.59515], [-78.34606, 16.57862], [-74.09729, 17.36817]]]]
25406           }
25407         }, {
25408           type: "Feature",
25409           properties: {
25410             iso1A2: "JO",
25411             iso1A3: "JOR",
25412             iso1N3: "400",
25413             wikidata: "Q810",
25414             nameEn: "Jordan",
25415             groups: ["145", "142", "UN"],
25416             callingCodes: ["962"]
25417           },
25418           geometry: {
25419             type: "MultiPolygon",
25420             coordinates: [[[[39.04251, 32.30203], [38.98762, 32.47694], [39.08202, 32.50304], [38.79171, 33.37328], [36.83946, 32.31293], [36.40959, 32.37908], [36.23948, 32.50108], [36.20875, 32.49529], [36.20379, 32.52751], [36.08074, 32.51463], [36.02239, 32.65911], [35.96633, 32.66237], [35.93307, 32.71966], [35.88405, 32.71321], [35.75983, 32.74803], [35.68467, 32.70715], [35.66527, 32.681], [35.61669, 32.67999], [35.59813, 32.65159], [35.56614, 32.64393], [35.57485, 32.48669], [35.55494, 32.42687], [35.55807, 32.38674], [35.57111, 32.21877], [35.52012, 32.04076], [35.54375, 31.96587], [35.52758, 31.9131], [35.55941, 31.76535], [35.47672, 31.49578], [35.40316, 31.25535], [35.43658, 31.12444], [35.41371, 30.95565], [35.33984, 30.8802], [35.33456, 30.81224], [35.29311, 30.71365], [35.21379, 30.60401], [35.19595, 30.50297], [35.16218, 30.43535], [35.19183, 30.34636], [35.14108, 30.07374], [35.02147, 29.66343], [34.98207, 29.58147], [34.97718, 29.54294], [34.92298, 29.45305], [34.8812, 29.36878], [36.07081, 29.18469], [36.50005, 29.49696], [36.75083, 29.86903], [37.4971, 29.99949], [37.66395, 30.33245], [37.99354, 30.49998], [36.99791, 31.50081], [38.99233, 31.99721], [39.29903, 32.23259], [39.26157, 32.35555], [39.04251, 32.30203]]]]
25421           }
25422         }, {
25423           type: "Feature",
25424           properties: {
25425             iso1A2: "JP",
25426             iso1A3: "JPN",
25427             iso1N3: "392",
25428             wikidata: "Q17",
25429             nameEn: "Japan",
25430             groups: ["030", "142", "UN"],
25431             driveSide: "left",
25432             callingCodes: ["81"]
25433           },
25434           geometry: {
25435             type: "MultiPolygon",
25436             coordinates: [[[[145.82361, 43.38904], [145.23667, 43.76813], [145.82343, 44.571], [140.9182, 45.92937], [133.61399, 37.41], [129.2669, 34.87122], [122.26612, 25.98197], [123.92912, 17.8782], [155.16731, 23.60141], [145.82361, 43.38904]]]]
25437           }
25438         }, {
25439           type: "Feature",
25440           properties: {
25441             iso1A2: "KE",
25442             iso1A3: "KEN",
25443             iso1N3: "404",
25444             wikidata: "Q114",
25445             nameEn: "Kenya",
25446             groups: ["014", "202", "002", "UN"],
25447             driveSide: "left",
25448             callingCodes: ["254"]
25449           },
25450           geometry: {
25451             type: "MultiPolygon",
25452             coordinates: [[[[35.9419, 4.61933], [35.51424, 4.61643], [35.42366, 4.76969], [35.47843, 4.91872], [35.30992, 4.90402], [35.34151, 5.02364], [34.47601, 4.72162], [33.9873, 4.23316], [34.06046, 4.15235], [34.15429, 3.80464], [34.45815, 3.67385], [34.44922, 3.51627], [34.39112, 3.48802], [34.41794, 3.44342], [34.40006, 3.37949], [34.45815, 3.18319], [34.56242, 3.11478], [34.60114, 2.93034], [34.65774, 2.8753], [34.73967, 2.85447], [34.78137, 2.76223], [34.77244, 2.70272], [34.95267, 2.47209], [34.90947, 2.42447], [34.98692, 1.97348], [34.9899, 1.6668], [34.92734, 1.56109], [34.87819, 1.5596], [34.7918, 1.36752], [34.82606, 1.30944], [34.82606, 1.26626], [34.80223, 1.22754], [34.67562, 1.21265], [34.58029, 1.14712], [34.57427, 1.09868], [34.52369, 1.10692], [34.43349, 0.85254], [34.40041, 0.80266], [34.31516, 0.75693], [34.27345, 0.63182], [34.20196, 0.62289], [34.13493, 0.58118], [34.11408, 0.48884], [34.08727, 0.44713], [34.10067, 0.36372], [33.90936, 0.10581], [33.98449, -0.13079], [33.9264, -0.54188], [33.93107, -0.99298], [34.02286, -1.00779], [34.03084, -1.05101], [34.0824, -1.02264], [37.67199, -3.06222], [37.71745, -3.304], [37.5903, -3.42735], [37.63099, -3.50723], [37.75036, -3.54243], [37.81321, -3.69179], [39.21631, -4.67835], [39.44306, -4.93877], [39.62121, -4.68136], [41.75542, -1.85308], [41.56362, -1.66375], [41.56, -1.59812], [41.00099, -0.83068], [40.98767, 2.82959], [41.31368, 3.14314], [41.89488, 3.97375], [41.1754, 3.94079], [40.77498, 4.27683], [39.86043, 3.86974], [39.76808, 3.67058], [39.58339, 3.47434], [39.55132, 3.39634], [39.51551, 3.40895], [39.49444, 3.45521], [39.19954, 3.47834], [39.07736, 3.5267], [38.91938, 3.51198], [38.52336, 3.62551], [38.45812, 3.60445], [38.14168, 3.62487], [37.07724, 4.33503], [36.84474, 4.44518], [36.03924, 4.44406], [35.95449, 4.53244], [35.9419, 4.61933]]]]
25453           }
25454         }, {
25455           type: "Feature",
25456           properties: {
25457             iso1A2: "KG",
25458             iso1A3: "KGZ",
25459             iso1N3: "417",
25460             wikidata: "Q813",
25461             nameEn: "Kyrgyzstan",
25462             groups: ["143", "142", "UN"],
25463             callingCodes: ["996"]
25464           },
25465           geometry: {
25466             type: "MultiPolygon",
25467             coordinates: [[[[74.88756, 42.98612], [74.75, 42.99029], [74.70331, 43.02519], [74.64615, 43.05881], [74.57491, 43.13702], [74.22489, 43.24657], [73.55634, 43.03071], [73.50992, 42.82356], [73.44393, 42.43098], [71.88792, 42.83578], [71.62405, 42.76613], [71.53272, 42.8014], [71.2724, 42.77853], [71.22785, 42.69248], [71.17807, 42.67381], [71.15232, 42.60486], [70.97717, 42.50147], [70.85973, 42.30188], [70.94483, 42.26238], [71.13263, 42.28356], [71.28719, 42.18033], [70.69777, 41.92554], [70.17682, 41.5455], [70.48909, 41.40335], [70.67586, 41.47953], [70.78572, 41.36419], [70.77885, 41.24813], [70.86263, 41.23833], [70.9615, 41.16393], [71.02193, 41.19494], [71.11806, 41.15359], [71.25813, 41.18796], [71.27187, 41.11015], [71.34877, 41.16807], [71.40198, 41.09436], [71.46148, 41.13958], [71.43814, 41.19644], [71.46688, 41.31883], [71.57227, 41.29175], [71.6787, 41.42111], [71.65914, 41.49599], [71.73054, 41.54713], [71.71132, 41.43012], [71.76625, 41.4466], [71.83914, 41.3546], [71.91457, 41.2982], [71.85964, 41.19081], [72.07249, 41.11739], [72.10745, 41.15483], [72.16433, 41.16483], [72.17594, 41.15522], [72.14864, 41.13363], [72.1792, 41.10621], [72.21061, 41.05607], [72.17594, 41.02377], [72.18339, 40.99571], [72.324, 41.03381], [72.34026, 41.04539], [72.34757, 41.06104], [72.36138, 41.04384], [72.38511, 41.02785], [72.45206, 41.03018], [72.48742, 40.97136], [72.55109, 40.96046], [72.59136, 40.86947], [72.68157, 40.84942], [72.84291, 40.85512], [72.94454, 40.8094], [73.01869, 40.84681], [73.13267, 40.83512], [73.13412, 40.79122], [73.0612, 40.76678], [72.99133, 40.76457], [72.93296, 40.73089], [72.8722, 40.71111], [72.85372, 40.7116], [72.84754, 40.67229], [72.80137, 40.67856], [72.74866, 40.60873], [72.74894, 40.59592], [72.75982, 40.57273], [72.74862, 40.57131], [72.74768, 40.58051], [72.73995, 40.58409], [72.69579, 40.59778], [72.66713, 40.59076], [72.66713, 40.5219], [72.47795, 40.5532], [72.40517, 40.61917], [72.34406, 40.60144], [72.41714, 40.55736], [72.38384, 40.51535], [72.41513, 40.50856], [72.44191, 40.48222], [72.40346, 40.4007], [72.24368, 40.46091], [72.18648, 40.49893], [71.96401, 40.31907], [72.05464, 40.27586], [71.85002, 40.25647], [71.82646, 40.21872], [71.73054, 40.14818], [71.71719, 40.17886], [71.69621, 40.18492], [71.70569, 40.20391], [71.68386, 40.26984], [71.61931, 40.26775], [71.61725, 40.20615], [71.51549, 40.22986], [71.51215, 40.26943], [71.4246, 40.28619], [71.36663, 40.31593], [71.13042, 40.34106], [71.05901, 40.28765], [70.95789, 40.28761], [70.9818, 40.22392], [70.80495, 40.16813], [70.7928, 40.12797], [70.65827, 40.0981], [70.65946, 39.9878], [70.58912, 39.95211], [70.55033, 39.96619], [70.47557, 39.93216], [70.57384, 39.99394], [70.58297, 40.00891], [70.01283, 40.23288], [69.67001, 40.10639], [69.64704, 40.12165], [69.57615, 40.10524], [69.55555, 40.12296], [69.53794, 40.11833], [69.53855, 40.0887], [69.5057, 40.03277], [69.53615, 39.93991], [69.43557, 39.92877], [69.43134, 39.98431], [69.35649, 40.01994], [69.26938, 39.8127], [69.3594, 39.52516], [69.68677, 39.59281], [69.87491, 39.53882], [70.11111, 39.58223], [70.2869, 39.53141], [70.44757, 39.60128], [70.64087, 39.58792], [70.7854, 39.38933], [71.06418, 39.41586], [71.08752, 39.50704], [71.49814, 39.61397], [71.55856, 39.57588], [71.5517, 39.45722], [71.62688, 39.44056], [71.76816, 39.45456], [71.80164, 39.40631], [71.7522, 39.32031], [71.79202, 39.27355], [71.90601, 39.27674], [72.04059, 39.36704], [72.09689, 39.26823], [72.17242, 39.2661], [72.23834, 39.17248], [72.33173, 39.33093], [72.62027, 39.39696], [72.85934, 39.35116], [73.18454, 39.35536], [73.31912, 39.38615], [73.45096, 39.46677], [73.59831, 39.46425], [73.87018, 39.47879], [73.94683, 39.60733], [73.92354, 39.69565], [73.9051, 39.75073], [73.83006, 39.76136], [73.97049, 40.04378], [74.25533, 40.13191], [74.35063, 40.09742], [74.69875, 40.34668], [74.85996, 40.32857], [74.78168, 40.44886], [74.82013, 40.52197], [75.08243, 40.43945], [75.22834, 40.45382], [75.5854, 40.66874], [75.69663, 40.28642], [75.91361, 40.2948], [75.96168, 40.38064], [76.33659, 40.3482], [76.5261, 40.46114], [76.75681, 40.95354], [76.99302, 41.0696], [77.28004, 41.0033], [77.3693, 41.0375], [77.52723, 41.00227], [77.76206, 41.01574], [77.81287, 41.14307], [78.12873, 41.23091], [78.15757, 41.38565], [78.3732, 41.39603], [79.92977, 42.04113], [80.17842, 42.03211], [80.17807, 42.21166], [79.97364, 42.42816], [79.52921, 42.44778], [79.19763, 42.804], [78.91502, 42.76839], [78.48469, 42.89649], [75.82823, 42.94848], [75.72174, 42.79672], [75.29966, 42.86183], [75.22619, 42.85528], [74.88756, 42.98612]], [[70.74189, 39.86319], [70.63105, 39.77923], [70.59667, 39.83542], [70.54998, 39.85137], [70.52631, 39.86989], [70.53651, 39.89155], [70.74189, 39.86319]], [[71.86463, 39.98598], [71.84316, 39.95582], [71.7504, 39.93701], [71.71511, 39.96348], [71.78838, 40.01404], [71.86463, 39.98598]], [[71.21139, 40.03369], [71.1427, 39.95026], [71.23067, 39.93581], [71.16101, 39.88423], [71.10531, 39.91354], [71.04979, 39.89808], [71.10501, 39.95568], [71.09063, 39.99], [71.11668, 39.99291], [71.11037, 40.01984], [71.01035, 40.05481], [71.00236, 40.18154], [71.06305, 40.1771], [71.12218, 40.03052], [71.21139, 40.03369]]]]
25468           }
25469         }, {
25470           type: "Feature",
25471           properties: {
25472             iso1A2: "KH",
25473             iso1A3: "KHM",
25474             iso1N3: "116",
25475             wikidata: "Q424",
25476             nameEn: "Cambodia",
25477             groups: ["035", "142", "UN"],
25478             callingCodes: ["855"]
25479           },
25480           geometry: {
25481             type: "MultiPolygon",
25482             coordinates: [[[[105.87328, 11.55953], [105.81645, 11.56876], [105.80867, 11.60536], [105.8507, 11.66635], [105.88962, 11.67854], [105.95188, 11.63738], [106.00792, 11.7197], [106.02038, 11.77457], [106.06708, 11.77761], [106.13158, 11.73283], [106.18539, 11.75171], [106.26478, 11.72122], [106.30525, 11.67549], [106.37219, 11.69836], [106.44691, 11.66787], [106.45158, 11.68616], [106.41577, 11.76999], [106.44535, 11.8279], [106.44068, 11.86294], [106.4687, 11.86751], [106.4111, 11.97413], [106.70687, 11.96956], [106.79405, 12.0807], [106.92325, 12.06548], [106.99953, 12.08983], [107.15831, 12.27547], [107.34511, 12.33327], [107.42917, 12.24657], [107.4463, 12.29373], [107.55059, 12.36824], [107.5755, 12.52177], [107.55993, 12.7982], [107.49611, 12.88926], [107.49144, 13.01215], [107.62843, 13.3668], [107.61909, 13.52577], [107.53503, 13.73908], [107.45252, 13.78897], [107.46498, 13.91593], [107.44318, 13.99751], [107.38247, 13.99147], [107.35757, 14.02319], [107.37158, 14.07906], [107.33577, 14.11832], [107.40427, 14.24509], [107.39493, 14.32655], [107.44941, 14.41552], [107.48521, 14.40346], [107.52569, 14.54665], [107.52102, 14.59034], [107.55371, 14.628], [107.54361, 14.69092], [107.47238, 14.61523], [107.44435, 14.52785], [107.37897, 14.54443], [107.3276, 14.58812], [107.29803, 14.58963], [107.26534, 14.54292], [107.256, 14.48716], [107.21241, 14.48716], [107.17038, 14.41782], [107.09722, 14.3937], [107.03962, 14.45099], [107.04585, 14.41782], [106.98825, 14.36806], [106.9649, 14.3198], [106.90574, 14.33639], [106.8497, 14.29416], [106.80767, 14.31226], [106.73762, 14.42687], [106.63333, 14.44194], [106.59908, 14.50977], [106.57106, 14.50525], [106.54148, 14.59565], [106.50723, 14.58963], [106.45898, 14.55045], [106.47766, 14.50977], [106.43874, 14.52032], [106.40916, 14.45249], [106.32355, 14.44043], [106.25194, 14.48415], [106.21302, 14.36203], [106.00131, 14.36957], [105.99509, 14.32734], [106.02311, 14.30623], [106.04801, 14.20363], [106.10872, 14.18401], [106.11962, 14.11307], [106.18656, 14.06324], [106.16632, 14.01794], [106.10094, 13.98471], [106.10405, 13.9137], [105.90791, 13.92881], [105.78182, 14.02247], [105.78338, 14.08438], [105.5561, 14.15684], [105.44869, 14.10703], [105.36775, 14.09948], [105.2759, 14.17496], [105.20894, 14.34967], [105.17748, 14.34432], [105.14012, 14.23873], [105.08408, 14.20402], [105.02804, 14.23722], [104.97667, 14.38806], [104.69335, 14.42726], [104.55014, 14.36091], [104.27616, 14.39861], [103.93836, 14.3398], [103.70175, 14.38052], [103.71109, 14.4348], [103.53518, 14.42575], [103.39353, 14.35639], [103.16469, 14.33075], [102.93275, 14.19044], [102.91251, 14.01531], [102.77864, 13.93374], [102.72727, 13.77806], [102.56848, 13.69366], [102.5481, 13.6589], [102.58635, 13.6286], [102.62483, 13.60883], [102.57573, 13.60461], [102.5358, 13.56933], [102.44601, 13.5637], [102.36859, 13.57488], [102.33828, 13.55613], [102.361, 13.50551], [102.35563, 13.47307], [102.35692, 13.38274], [102.34611, 13.35618], [102.36001, 13.31142], [102.36146, 13.26006], [102.43422, 13.09061], [102.46011, 13.08057], [102.52275, 12.99813], [102.48694, 12.97537], [102.49335, 12.92711], [102.53053, 12.77506], [102.4994, 12.71736], [102.51963, 12.66117], [102.57567, 12.65358], [102.7796, 12.43781], [102.78116, 12.40284], [102.73134, 12.37091], [102.70176, 12.1686], [102.77026, 12.06815], [102.78427, 11.98746], [102.83957, 11.8519], [102.90973, 11.75613], [102.91449, 11.65512], [102.52395, 11.25257], [102.47649, 9.66162], [103.99198, 10.48391], [104.43778, 10.42386], [104.47963, 10.43046], [104.49869, 10.4057], [104.59018, 10.53073], [104.87933, 10.52833], [104.95094, 10.64003], [105.09571, 10.72722], [105.02722, 10.89236], [105.08326, 10.95656], [105.11449, 10.96332], [105.34011, 10.86179], [105.42884, 10.96878], [105.50045, 10.94586], [105.77751, 11.03671], [105.86376, 10.89839], [105.84603, 10.85873], [105.93403, 10.83853], [105.94535, 10.9168], [106.06708, 10.8098], [106.18539, 10.79451], [106.14301, 10.98176], [106.20095, 10.97795], [106.1757, 11.07301], [106.1527, 11.10476], [106.10444, 11.07879], [105.86782, 11.28343], [105.88962, 11.43605], [105.87328, 11.55953]]]]
25483           }
25484         }, {
25485           type: "Feature",
25486           properties: {
25487             iso1A2: "KI",
25488             iso1A3: "KIR",
25489             iso1N3: "296",
25490             wikidata: "Q710",
25491             nameEn: "Kiribati",
25492             groups: ["057", "009", "UN"],
25493             driveSide: "left",
25494             callingCodes: ["686"]
25495           },
25496           geometry: {
25497             type: "MultiPolygon",
25498             coordinates: [[[[169, 3.9], [169, -3.5], [178, -3.5], [178, 3.9], [169, 3.9]]], [[[-161.06795, 5.2462], [-158.12991, -1.86122], [-175.33482, -1.40631], [-175.31804, -7.54825], [-156.50903, -7.4975], [-156.48634, -15.52824], [-135.59706, -4.70473], [-161.06795, 5.2462]]]]
25499           }
25500         }, {
25501           type: "Feature",
25502           properties: {
25503             iso1A2: "KM",
25504             iso1A3: "COM",
25505             iso1N3: "174",
25506             wikidata: "Q970",
25507             nameEn: "Comoros",
25508             groups: ["014", "202", "002", "UN"],
25509             callingCodes: ["269"]
25510           },
25511           geometry: {
25512             type: "MultiPolygon",
25513             coordinates: [[[[42.63904, -10.02522], [43.28731, -13.97126], [45.4971, -11.75965], [42.63904, -10.02522]]]]
25514           }
25515         }, {
25516           type: "Feature",
25517           properties: {
25518             iso1A2: "KN",
25519             iso1A3: "KNA",
25520             iso1N3: "659",
25521             wikidata: "Q763",
25522             nameEn: "St. Kitts and Nevis",
25523             groups: ["029", "003", "419", "019", "UN"],
25524             driveSide: "left",
25525             roadSpeedUnit: "mph",
25526             callingCodes: ["1 869"]
25527           },
25528           geometry: {
25529             type: "MultiPolygon",
25530             coordinates: [[[[-62.29333, 17.43155], [-62.76692, 17.64353], [-63.09677, 17.21372], [-62.63813, 16.65446], [-62.29333, 17.43155]]]]
25531           }
25532         }, {
25533           type: "Feature",
25534           properties: {
25535             iso1A2: "KP",
25536             iso1A3: "PRK",
25537             iso1N3: "408",
25538             wikidata: "Q423",
25539             nameEn: "North Korea",
25540             groups: ["030", "142", "UN"],
25541             callingCodes: ["850"]
25542           },
25543           geometry: {
25544             type: "MultiPolygon",
25545             coordinates: [[[[130.26095, 42.9027], [130.09764, 42.91425], [130.12957, 42.98361], [129.96409, 42.97306], [129.95082, 43.01051], [129.8865, 43.00395], [129.85261, 42.96494], [129.83277, 42.86746], [129.80719, 42.79218], [129.7835, 42.76521], [129.77183, 42.69435], [129.75294, 42.59409], [129.72541, 42.43739], [129.60482, 42.44461], [129.54701, 42.37254], [129.42882, 42.44702], [129.28541, 42.41574], [129.22423, 42.3553], [129.22285, 42.26491], [129.15178, 42.17224], [128.96068, 42.06657], [128.94007, 42.03537], [128.04487, 42.01769], [128.15119, 41.74568], [128.30716, 41.60322], [128.20061, 41.40895], [128.18546, 41.41279], [128.12967, 41.37931], [128.03311, 41.39232], [128.02633, 41.42103], [127.92943, 41.44291], [127.29712, 41.49473], [127.17841, 41.59714], [126.90729, 41.79955], [126.60631, 41.65565], [126.53189, 41.35206], [126.242, 41.15454], [126.00335, 40.92835], [125.76869, 40.87908], [125.71172, 40.85223], [124.86913, 40.45387], [124.40719, 40.13655], [124.38556, 40.11047], [124.3322, 40.05573], [124.37089, 40.03004], [124.35029, 39.95639], [124.23201, 39.9248], [124.17532, 39.8232], [123.90497, 38.79949], [123.85601, 37.49093], [124.67666, 38.05679], [124.84224, 37.977], [124.87921, 37.80827], [125.06408, 37.66334], [125.37112, 37.62643], [125.81159, 37.72949], [126.13074, 37.70512], [126.18776, 37.74728], [126.19097, 37.81462], [126.24402, 37.83113], [126.43239, 37.84095], [126.46818, 37.80873], [126.56709, 37.76857], [126.59918, 37.76364], [126.66067, 37.7897], [126.68793, 37.83728], [126.68793, 37.9175], [126.67023, 37.95852], [126.84961, 38.0344], [126.88106, 38.10246], [126.95887, 38.1347], [126.95338, 38.17735], [127.04479, 38.25518], [127.15749, 38.30722], [127.38727, 38.33227], [127.49672, 38.30647], [127.55013, 38.32257], [128.02917, 38.31861], [128.27652, 38.41657], [128.31105, 38.58462], [128.37487, 38.62345], [128.65655, 38.61914], [131.95041, 41.5445], [130.65022, 42.32281], [130.66367, 42.38024], [130.64181, 42.41422], [130.60805, 42.4317], [130.56835, 42.43281], [130.55143, 42.52158], [130.50123, 42.61636], [130.44361, 42.54849], [130.41826, 42.6011], [130.2385, 42.71127], [130.23068, 42.80125], [130.26095, 42.9027]]]]
25546           }
25547         }, {
25548           type: "Feature",
25549           properties: {
25550             iso1A2: "KR",
25551             iso1A3: "KOR",
25552             iso1N3: "410",
25553             wikidata: "Q884",
25554             nameEn: "South Korea",
25555             groups: ["030", "142", "UN"],
25556             callingCodes: ["82"]
25557           },
25558           geometry: {
25559             type: "MultiPolygon",
25560             coordinates: [[[[133.11729, 37.53115], [128.65655, 38.61914], [128.37487, 38.62345], [128.31105, 38.58462], [128.27652, 38.41657], [128.02917, 38.31861], [127.55013, 38.32257], [127.49672, 38.30647], [127.38727, 38.33227], [127.15749, 38.30722], [127.04479, 38.25518], [126.95338, 38.17735], [126.95887, 38.1347], [126.88106, 38.10246], [126.84961, 38.0344], [126.67023, 37.95852], [126.68793, 37.9175], [126.68793, 37.83728], [126.66067, 37.7897], [126.59918, 37.76364], [126.56709, 37.76857], [126.46818, 37.80873], [126.43239, 37.84095], [126.24402, 37.83113], [126.19097, 37.81462], [126.18776, 37.74728], [126.13074, 37.70512], [125.81159, 37.72949], [125.37112, 37.62643], [125.06408, 37.66334], [124.87921, 37.80827], [124.84224, 37.977], [124.67666, 38.05679], [123.85601, 37.49093], [122.80525, 33.30571], [125.99728, 32.63328], [129.2669, 34.87122], [133.11729, 37.53115]]]]
25561           }
25562         }, {
25563           type: "Feature",
25564           properties: {
25565             iso1A2: "KW",
25566             iso1A3: "KWT",
25567             iso1N3: "414",
25568             wikidata: "Q817",
25569             nameEn: "Kuwait",
25570             groups: ["145", "142", "UN"],
25571             callingCodes: ["965"]
25572           },
25573           geometry: {
25574             type: "MultiPolygon",
25575             coordinates: [[[[49.00421, 28.81495], [48.59531, 29.66815], [48.40479, 29.85763], [48.17332, 30.02448], [48.06782, 30.02906], [48.01114, 29.98906], [47.7095, 30.10453], [47.37192, 30.10421], [47.15166, 30.01044], [46.89695, 29.50584], [46.5527, 29.10283], [47.46202, 29.0014], [47.58376, 28.83382], [47.59863, 28.66798], [47.70561, 28.5221], [48.42991, 28.53628], [49.00421, 28.81495]]]]
25576           }
25577         }, {
25578           type: "Feature",
25579           properties: {
25580             iso1A2: "KY",
25581             iso1A3: "CYM",
25582             iso1N3: "136",
25583             wikidata: "Q5785",
25584             nameEn: "Cayman Islands",
25585             country: "GB",
25586             groups: ["BOTS", "029", "003", "419", "019", "UN"],
25587             driveSide: "left",
25588             roadSpeedUnit: "mph",
25589             roadHeightUnit: "ft",
25590             callingCodes: ["1 345"]
25591           },
25592           geometry: {
25593             type: "MultiPolygon",
25594             coordinates: [[[[-82.11509, 19.60401], [-80.36068, 18.11751], [-79.32727, 20.06742], [-82.11509, 19.60401]]]]
25595           }
25596         }, {
25597           type: "Feature",
25598           properties: {
25599             iso1A2: "KZ",
25600             iso1A3: "KAZ",
25601             iso1N3: "398",
25602             wikidata: "Q232",
25603             nameEn: "Kazakhstan",
25604             groups: ["143", "142", "UN"],
25605             callingCodes: ["7"]
25606           },
25607           geometry: {
25608             type: "MultiPolygon",
25609             coordinates: [[[[68.90865, 55.38148], [68.19206, 55.18823], [68.26661, 55.09226], [68.21308, 54.98645], [65.20174, 54.55216], [65.24663, 54.35721], [65.11033, 54.33028], [64.97216, 54.4212], [63.97686, 54.29763], [64.02715, 54.22679], [63.91224, 54.20013], [63.80604, 54.27079], [62.58651, 54.05871], [62.56876, 53.94047], [62.45931, 53.90737], [62.38535, 54.03961], [62.00966, 54.04134], [62.03913, 53.94768], [61.65318, 54.02445], [61.56941, 53.95703], [61.47603, 54.08048], [61.3706, 54.08464], [61.26863, 53.92797], [60.99796, 53.93699], [61.14283, 53.90063], [61.22574, 53.80268], [60.90626, 53.62937], [61.55706, 53.57144], [61.57185, 53.50112], [61.37957, 53.45887], [61.29082, 53.50992], [61.14291, 53.41481], [61.19024, 53.30536], [62.14574, 53.09626], [62.12799, 52.99133], [62.0422, 52.96105], [61.23462, 53.03227], [61.05842, 52.92217], [60.71989, 52.75923], [60.71693, 52.66245], [60.84118, 52.63912], [60.84709, 52.52228], [60.98021, 52.50068], [61.05417, 52.35096], [60.78201, 52.22067], [60.72581, 52.15538], [60.48915, 52.15175], [60.19925, 51.99173], [59.99809, 51.98263], [60.09867, 51.87135], [60.50986, 51.7964], [60.36787, 51.66815], [60.5424, 51.61675], [60.92401, 51.61124], [60.95655, 51.48615], [61.50677, 51.40687], [61.55114, 51.32746], [61.6813, 51.25716], [61.56889, 51.23679], [61.4431, 50.80679], [60.81833, 50.6629], [60.31914, 50.67705], [60.17262, 50.83312], [60.01288, 50.8163], [59.81172, 50.54451], [59.51886, 50.49937], [59.48928, 50.64216], [58.87974, 50.70852], [58.3208, 51.15151], [57.75578, 51.13852], [57.74986, 50.93017], [57.44221, 50.88354], [57.17302, 51.11253], [56.17906, 50.93204], [56.11398, 50.7471], [55.67774, 50.54508], [54.72067, 51.03261], [54.56685, 51.01958], [54.71476, 50.61214], [54.55797, 50.52006], [54.41894, 50.61214], [54.46331, 50.85554], [54.12248, 51.11542], [53.69299, 51.23466], [53.46165, 51.49445], [52.54329, 51.48444], [52.36119, 51.74161], [51.8246, 51.67916], [51.77431, 51.49536], [51.301, 51.48799], [51.26254, 51.68466], [50.59695, 51.61859], [50.26859, 51.28677], [49.97277, 51.2405], [49.76866, 51.11067], [49.39001, 51.09396], [49.41959, 50.85927], [49.12673, 50.78639], [48.86936, 50.61589], [48.57946, 50.63278], [48.90782, 50.02281], [48.68352, 49.89546], [48.42564, 49.82283], [48.24519, 49.86099], [48.10044, 50.09242], [47.58551, 50.47867], [47.30448, 50.30894], [47.34589, 50.09308], [47.18319, 49.93721], [46.9078, 49.86707], [46.78398, 49.34026], [47.04658, 49.19834], [47.00857, 49.04921], [46.78392, 48.95352], [46.49011, 48.43019], [47.11516, 48.27188], [47.12107, 47.83687], [47.38731, 47.68176], [47.41689, 47.83687], [47.64973, 47.76559], [48.15348, 47.74545], [48.45173, 47.40818], [48.52326, 47.4102], [49.01136, 46.72716], [48.51142, 46.69268], [48.54988, 46.56267], [49.16518, 46.38542], [49.32259, 46.26944], [49.88945, 46.04554], [49.2134, 44.84989], [52.26048, 41.69249], [52.47884, 41.78034], [52.97575, 42.1308], [54.20635, 42.38477], [54.95182, 41.92424], [55.45471, 41.25609], [56.00314, 41.32584], [55.97584, 44.99322], [55.97584, 44.99328], [55.97584, 44.99338], [55.97584, 44.99343], [55.97584, 44.99348], [55.97584, 44.99353], [55.97584, 44.99359], [55.97584, 44.99369], [55.97584, 44.99374], [55.97584, 44.99384], [55.97584, 44.9939], [55.97584, 44.994], [55.97584, 44.99405], [55.97584, 44.99415], [55.97584, 44.99421], [55.97584, 44.99426], [55.97584, 44.99431], [55.97584, 44.99436], [55.97584, 44.99441], [55.97594, 44.99446], [55.97605, 44.99452], [55.97605, 44.99457], [55.97605, 44.99462], [55.97605, 44.99467], [55.97605, 44.99477], [55.97615, 44.99477], [55.97615, 44.99483], [55.97615, 44.99493], [55.97615, 44.99498], [55.97615, 44.99503], [55.97615, 44.99508], [55.97625, 44.99514], [55.97636, 44.99519], [55.97636, 44.99524], [55.97646, 44.99529], [55.97646, 44.99534], [55.97656, 44.99539], [55.97667, 44.99545], [55.97677, 44.9955], [55.97677, 44.99555], [55.97677, 44.9956], [55.97687, 44.9956], [55.97698, 44.99565], [55.97698, 44.9957], [55.97708, 44.99576], [55.97718, 44.99581], [55.97729, 44.99586], [55.97739, 44.99586], [55.97739, 44.99591], [55.97749, 44.99591], [55.9776, 44.99591], [55.9777, 44.99596], [55.9777, 44.99601], [55.9778, 44.99607], [55.97791, 44.99607], [55.97801, 44.99607], [55.97801, 44.99612], [55.97811, 44.99617], [55.97822, 44.99617], [55.97832, 44.99622], [55.97842, 44.99622], [58.59711, 45.58671], [61.01475, 44.41383], [62.01711, 43.51008], [63.34656, 43.64003], [64.53885, 43.56941], [64.96464, 43.74748], [65.18666, 43.48835], [65.53277, 43.31856], [65.85194, 42.85481], [66.09482, 42.93426], [66.00546, 41.94455], [66.53302, 41.87388], [66.69129, 41.1311], [67.9644, 41.14611], [67.98511, 41.02794], [68.08273, 41.08148], [68.1271, 41.0324], [67.96736, 40.83798], [68.49983, 40.56437], [68.63, 40.59358], [68.58444, 40.91447], [68.49983, 40.99669], [68.62221, 41.03019], [68.65662, 40.93861], [68.73945, 40.96989], [68.7217, 41.05025], [69.01308, 41.22804], [69.05006, 41.36183], [69.15137, 41.43078], [69.17701, 41.43769], [69.18528, 41.45175], [69.20439, 41.45391], [69.22671, 41.46298], [69.23332, 41.45847], [69.25059, 41.46693], [69.29778, 41.43673], [69.35554, 41.47211], [69.37468, 41.46555], [69.45081, 41.46246], [69.39485, 41.51518], [69.45751, 41.56863], [69.49545, 41.545], [70.94483, 42.26238], [70.85973, 42.30188], [70.97717, 42.50147], [71.15232, 42.60486], [71.17807, 42.67381], [71.22785, 42.69248], [71.2724, 42.77853], [71.53272, 42.8014], [71.62405, 42.76613], [71.88792, 42.83578], [73.44393, 42.43098], [73.50992, 42.82356], [73.55634, 43.03071], [74.22489, 43.24657], [74.57491, 43.13702], [74.64615, 43.05881], [74.70331, 43.02519], [74.75, 42.99029], [74.88756, 42.98612], [75.22619, 42.85528], [75.29966, 42.86183], [75.72174, 42.79672], [75.82823, 42.94848], [78.48469, 42.89649], [78.91502, 42.76839], [79.19763, 42.804], [79.52921, 42.44778], [79.97364, 42.42816], [80.17807, 42.21166], [80.26841, 42.23797], [80.16892, 42.61137], [80.26886, 42.8366], [80.38169, 42.83142], [80.58999, 42.9011], [80.3735, 43.01557], [80.62913, 43.141], [80.78817, 43.14235], [80.77771, 43.30065], [80.69718, 43.32589], [80.75156, 43.44948], [80.40031, 44.10986], [80.40229, 44.23319], [80.38384, 44.63073], [79.8987, 44.89957], [80.11169, 45.03352], [81.73278, 45.3504], [82.51374, 45.1755], [82.58474, 45.40027], [82.21792, 45.56619], [83.04622, 47.19053], [83.92184, 46.98912], [84.73077, 47.01394], [84.93995, 46.87399], [85.22443, 47.04816], [85.54294, 47.06171], [85.69696, 47.2898], [85.61067, 47.49753], [85.5169, 48.05493], [85.73581, 48.3939], [86.38069, 48.46064], [86.75343, 48.70331], [86.73568, 48.99918], [86.87238, 49.12432], [87.28386, 49.11626], [87.31465, 49.23603], [87.03071, 49.25142], [86.82606, 49.51796], [86.61307, 49.60239], [86.79056, 49.74787], [86.63674, 49.80136], [86.18709, 49.50259], [85.24047, 49.60239], [84.99198, 50.06793], [84.29385, 50.27257], [83.8442, 50.87375], [83.14607, 51.00796], [82.55443, 50.75412], [81.94999, 50.79307], [81.46581, 50.77658], [81.41248, 50.97524], [81.06091, 50.94833], [81.16999, 51.15662], [80.80318, 51.28262], [80.44819, 51.20855], [80.4127, 50.95581], [80.08138, 50.77658], [79.11255, 52.01171], [77.90383, 53.29807], [76.54243, 53.99329], [76.44076, 54.16017], [76.82266, 54.1798], [76.91052, 54.4677], [75.3668, 54.07439], [75.43398, 53.98652], [75.07405, 53.80831], [73.39218, 53.44623], [73.25412, 53.61532], [73.68921, 53.86522], [73.74778, 54.07194], [73.37963, 53.96132], [72.71026, 54.1161], [72.43415, 53.92685], [72.17477, 54.36303], [71.96141, 54.17736], [71.10379, 54.13326], [71.08706, 54.33376], [71.24185, 54.64965], [71.08288, 54.71253], [70.96009, 55.10558], [70.76493, 55.3027], [70.19179, 55.1476], [69.74917, 55.35545], [69.34224, 55.36344], [68.90865, 55.38148]]]]
25610           }
25611         }, {
25612           type: "Feature",
25613           properties: {
25614             iso1A2: "LA",
25615             iso1A3: "LAO",
25616             iso1N3: "418",
25617             wikidata: "Q819",
25618             nameEn: "Laos",
25619             groups: ["035", "142", "UN"],
25620             callingCodes: ["856"]
25621           },
25622           geometry: {
25623             type: "MultiPolygon",
25624             coordinates: [[[[102.1245, 22.43372], [102.03633, 22.46164], [101.98487, 22.42766], [101.91344, 22.44417], [101.90714, 22.38688], [101.86828, 22.38397], [101.7685, 22.50337], [101.68973, 22.46843], [101.61306, 22.27515], [101.56789, 22.28876], [101.53638, 22.24794], [101.60675, 22.13513], [101.57525, 22.13026], [101.62566, 21.96574], [101.7791, 21.83019], [101.74555, 21.72852], [101.83257, 21.61562], [101.80001, 21.57461], [101.7475, 21.5873], [101.7727, 21.51794], [101.74224, 21.48276], [101.74014, 21.30967], [101.84412, 21.25291], [101.83887, 21.20983], [101.76745, 21.21571], [101.79266, 21.19025], [101.7622, 21.14813], [101.70548, 21.14911], [101.66977, 21.20004], [101.60886, 21.17947], [101.59491, 21.18621], [101.6068, 21.23329], [101.54563, 21.25668], [101.29326, 21.17254], [101.2229, 21.23271], [101.26912, 21.36482], [101.19349, 21.41959], [101.2124, 21.56422], [101.15156, 21.56129], [101.16198, 21.52808], [101.00234, 21.39612], [100.80173, 21.2934], [100.72716, 21.31786], [100.63578, 21.05639], [100.55281, 21.02796], [100.50974, 20.88574], [100.64628, 20.88279], [100.60112, 20.8347], [100.51079, 20.82194], [100.36375, 20.82783], [100.1957, 20.68247], [100.08404, 20.36626], [100.09999, 20.31614], [100.09337, 20.26293], [100.11785, 20.24787], [100.1712, 20.24324], [100.16668, 20.2986], [100.22076, 20.31598], [100.25769, 20.3992], [100.33383, 20.4028], [100.37439, 20.35156], [100.41473, 20.25625], [100.44992, 20.23644], [100.4537, 20.19971], [100.47567, 20.19133], [100.51052, 20.14928], [100.55218, 20.17741], [100.58808, 20.15791], [100.5094, 19.87904], [100.398, 19.75047], [100.49604, 19.53504], [100.58219, 19.49164], [100.64606, 19.55884], [100.77231, 19.48324], [100.90302, 19.61901], [101.08928, 19.59748], [101.26545, 19.59242], [101.26991, 19.48324], [101.21347, 19.46223], [101.20604, 19.35296], [101.24911, 19.33334], [101.261, 19.12717], [101.35606, 19.04716], [101.25803, 18.89545], [101.22832, 18.73377], [101.27585, 18.68875], [101.06047, 18.43247], [101.18227, 18.34367], [101.15108, 18.25624], [101.19118, 18.2125], [101.1793, 18.0544], [101.02185, 17.87637], [100.96541, 17.57926], [101.15108, 17.47586], [101.44667, 17.7392], [101.72294, 17.92867], [101.78087, 18.07559], [101.88485, 18.02474], [102.11359, 18.21532], [102.45523, 17.97106], [102.59234, 17.96127], [102.60971, 17.95411], [102.61432, 17.92273], [102.5896, 17.84889], [102.59485, 17.83537], [102.68194, 17.80151], [102.69946, 17.81686], [102.67543, 17.84529], [102.68538, 17.86653], [102.75954, 17.89561], [102.79044, 17.93612], [102.81988, 17.94233], [102.86323, 17.97531], [102.95812, 18.0054], [102.9912, 17.9949], [103.01998, 17.97095], [103.0566, 18.00144], [103.07823, 18.03833], [103.07343, 18.12351], [103.1493, 18.17799], [103.14994, 18.23172], [103.17093, 18.2618], [103.29757, 18.30475], [103.23818, 18.34875], [103.24779, 18.37807], [103.30977, 18.4341], [103.41044, 18.4486], [103.47773, 18.42841], [103.60957, 18.40528], [103.699, 18.34125], [103.82449, 18.33979], [103.85642, 18.28666], [103.93916, 18.33914], [103.97725, 18.33631], [104.06533, 18.21656], [104.10927, 18.10826], [104.21776, 17.99335], [104.2757, 17.86139], [104.35432, 17.82871], [104.45404, 17.66788], [104.69867, 17.53038], [104.80061, 17.39367], [104.80716, 17.19025], [104.73712, 17.01404], [104.7373, 16.91125], [104.76442, 16.84752], [104.7397, 16.81005], [104.76099, 16.69302], [104.73349, 16.565], [104.88057, 16.37311], [105.00262, 16.25627], [105.06204, 16.09792], [105.42001, 16.00657], [105.38508, 15.987], [105.34115, 15.92737], [105.37959, 15.84074], [105.42285, 15.76971], [105.46573, 15.74742], [105.61756, 15.68792], [105.60446, 15.53301], [105.58191, 15.41031], [105.47635, 15.3796], [105.4692, 15.33709], [105.50662, 15.32054], [105.58043, 15.32724], [105.46661, 15.13132], [105.61162, 15.00037], [105.5121, 14.80802], [105.53864, 14.55731], [105.43783, 14.43865], [105.20894, 14.34967], [105.2759, 14.17496], [105.36775, 14.09948], [105.44869, 14.10703], [105.5561, 14.15684], [105.78338, 14.08438], [105.78182, 14.02247], [105.90791, 13.92881], [106.10405, 13.9137], [106.10094, 13.98471], [106.16632, 14.01794], [106.18656, 14.06324], [106.11962, 14.11307], [106.10872, 14.18401], [106.04801, 14.20363], [106.02311, 14.30623], [105.99509, 14.32734], [106.00131, 14.36957], [106.21302, 14.36203], [106.25194, 14.48415], [106.32355, 14.44043], [106.40916, 14.45249], [106.43874, 14.52032], [106.47766, 14.50977], [106.45898, 14.55045], [106.50723, 14.58963], [106.54148, 14.59565], [106.57106, 14.50525], [106.59908, 14.50977], [106.63333, 14.44194], [106.73762, 14.42687], [106.80767, 14.31226], [106.8497, 14.29416], [106.90574, 14.33639], [106.9649, 14.3198], [106.98825, 14.36806], [107.04585, 14.41782], [107.03962, 14.45099], [107.09722, 14.3937], [107.17038, 14.41782], [107.21241, 14.48716], [107.256, 14.48716], [107.26534, 14.54292], [107.29803, 14.58963], [107.3276, 14.58812], [107.37897, 14.54443], [107.44435, 14.52785], [107.47238, 14.61523], [107.54361, 14.69092], [107.51579, 14.79282], [107.59285, 14.87795], [107.48277, 14.93751], [107.46516, 15.00982], [107.61486, 15.0566], [107.61926, 15.13949], [107.58844, 15.20111], [107.62587, 15.2266], [107.60605, 15.37524], [107.62367, 15.42193], [107.53341, 15.40496], [107.50699, 15.48771], [107.3815, 15.49832], [107.34408, 15.62345], [107.27583, 15.62769], [107.27143, 15.71459], [107.21859, 15.74638], [107.21419, 15.83747], [107.34188, 15.89464], [107.39471, 15.88829], [107.46296, 16.01106], [107.44975, 16.08511], [107.33968, 16.05549], [107.25822, 16.13587], [107.14595, 16.17816], [107.15035, 16.26271], [107.09091, 16.3092], [107.02597, 16.31132], [106.97385, 16.30204], [106.96638, 16.34938], [106.88067, 16.43594], [106.88727, 16.52671], [106.84104, 16.55415], [106.74418, 16.41904], [106.65832, 16.47816], [106.66052, 16.56892], [106.61477, 16.60713], [106.58267, 16.6012], [106.59013, 16.62259], [106.55485, 16.68704], [106.55265, 16.86831], [106.52183, 16.87884], [106.51963, 16.92097], [106.54824, 16.92729], [106.55045, 17.0031], [106.50862, 16.9673], [106.43597, 17.01362], [106.31929, 17.20509], [106.29287, 17.3018], [106.24444, 17.24714], [106.18991, 17.28227], [106.09019, 17.36399], [105.85744, 17.63221], [105.76612, 17.67147], [105.60381, 17.89356], [105.64784, 17.96687], [105.46292, 18.22008], [105.38366, 18.15315], [105.15942, 18.38691], [105.10408, 18.43533], [105.1327, 18.58355], [105.19654, 18.64196], [105.12829, 18.70453], [104.64617, 18.85668], [104.5361, 18.97747], [103.87125, 19.31854], [104.06058, 19.43484], [104.10832, 19.51575], [104.05617, 19.61743], [104.06498, 19.66926], [104.23229, 19.70242], [104.41281, 19.70035], [104.53169, 19.61743], [104.64837, 19.62365], [104.68359, 19.72729], [104.8355, 19.80395], [104.8465, 19.91783], [104.9874, 20.09573], [104.91695, 20.15567], [104.86852, 20.14121], [104.61315, 20.24452], [104.62195, 20.36633], [104.72102, 20.40554], [104.66158, 20.47774], [104.47886, 20.37459], [104.40621, 20.3849], [104.38199, 20.47155], [104.63957, 20.6653], [104.27412, 20.91433], [104.11121, 20.96779], [103.98024, 20.91531], [103.82282, 20.8732], [103.73478, 20.6669], [103.68633, 20.66324], [103.45737, 20.82382], [103.38032, 20.79501], [103.21497, 20.89832], [103.12055, 20.89994], [103.03469, 21.05821], [102.97745, 21.05821], [102.89825, 21.24707], [102.80794, 21.25736], [102.88939, 21.3107], [102.94223, 21.46034], [102.86297, 21.4255], [102.98846, 21.58936], [102.97965, 21.74076], [102.86077, 21.71213], [102.85637, 21.84501], [102.81894, 21.83888], [102.82115, 21.73667], [102.74189, 21.66713], [102.67145, 21.65894], [102.62301, 21.91447], [102.49092, 21.99002], [102.51734, 22.02676], [102.18712, 22.30403], [102.14099, 22.40092], [102.1245, 22.43372]]]]
25625           }
25626         }, {
25627           type: "Feature",
25628           properties: {
25629             iso1A2: "LB",
25630             iso1A3: "LBN",
25631             iso1N3: "422",
25632             wikidata: "Q822",
25633             nameEn: "Lebanon",
25634             aliases: ["RL"],
25635             groups: ["145", "142", "UN"],
25636             callingCodes: ["961"]
25637           },
25638           geometry: {
25639             type: "MultiPolygon",
25640             coordinates: [[[[35.94816, 33.47886], [35.94465, 33.52774], [36.05723, 33.57904], [35.9341, 33.6596], [36.06778, 33.82927], [36.14517, 33.85118], [36.3967, 33.83365], [36.38263, 33.86579], [36.28589, 33.91981], [36.41078, 34.05253], [36.50576, 34.05982], [36.5128, 34.09916], [36.62537, 34.20251], [36.59195, 34.2316], [36.58667, 34.27667], [36.60778, 34.31009], [36.56556, 34.31881], [36.53039, 34.3798], [36.55853, 34.41609], [36.46179, 34.46541], [36.4442, 34.50165], [36.34745, 34.5002], [36.3369, 34.52629], [36.39846, 34.55672], [36.41429, 34.61175], [36.45299, 34.59438], [36.46003, 34.6378], [36.42941, 34.62505], [36.35384, 34.65447], [36.35135, 34.68516], [36.32399, 34.69334], [36.29165, 34.62991], [35.98718, 34.64977], [35.97386, 34.63322], [35.48515, 34.70851], [34.78515, 33.20368], [35.10645, 33.09318], [35.1924, 33.08743], [35.31429, 33.10515], [35.35223, 33.05617], [35.43059, 33.06659], [35.448, 33.09264], [35.50272, 33.09056], [35.50335, 33.114], [35.52573, 33.11921], [35.54228, 33.19865], [35.5362, 33.23196], [35.54808, 33.236], [35.54544, 33.25513], [35.55555, 33.25844], [35.56523, 33.28969], [35.58326, 33.28381], [35.58502, 33.26653], [35.62283, 33.24226], [35.62019, 33.27278], [35.77477, 33.33609], [35.81324, 33.36354], [35.82577, 33.40479], [35.88668, 33.43183], [35.94816, 33.47886]]]]
25641           }
25642         }, {
25643           type: "Feature",
25644           properties: {
25645             iso1A2: "LC",
25646             iso1A3: "LCA",
25647             iso1N3: "662",
25648             wikidata: "Q760",
25649             nameEn: "St. Lucia",
25650             aliases: ["WL"],
25651             groups: ["029", "003", "419", "019", "UN"],
25652             driveSide: "left",
25653             roadSpeedUnit: "mph",
25654             callingCodes: ["1 758"]
25655           },
25656           geometry: {
25657             type: "MultiPolygon",
25658             coordinates: [[[[-59.95997, 14.20285], [-61.69315, 14.26451], [-59.94058, 12.34011], [-59.95997, 14.20285]]]]
25659           }
25660         }, {
25661           type: "Feature",
25662           properties: {
25663             iso1A2: "LI",
25664             iso1A3: "LIE",
25665             iso1N3: "438",
25666             wikidata: "Q347",
25667             nameEn: "Liechtenstein",
25668             aliases: ["FL"],
25669             groups: ["155", "150", "UN"],
25670             callingCodes: ["423"]
25671           },
25672           geometry: {
25673             type: "MultiPolygon",
25674             coordinates: [[[[9.60717, 47.06091], [9.61216, 47.07732], [9.63395, 47.08443], [9.62623, 47.14685], [9.56539, 47.17124], [9.58264, 47.20673], [9.56981, 47.21926], [9.55176, 47.22585], [9.56766, 47.24281], [9.53116, 47.27029], [9.52406, 47.24959], [9.50318, 47.22153], [9.4891, 47.19346], [9.48774, 47.17402], [9.51044, 47.13727], [9.52089, 47.10019], [9.51362, 47.08505], [9.47139, 47.06402], [9.47548, 47.05257], [9.54041, 47.06495], [9.55721, 47.04762], [9.60717, 47.06091]]]]
25675           }
25676         }, {
25677           type: "Feature",
25678           properties: {
25679             iso1A2: "LK",
25680             iso1A3: "LKA",
25681             iso1N3: "144",
25682             wikidata: "Q854",
25683             nameEn: "Sri Lanka",
25684             groups: ["034", "142", "UN"],
25685             driveSide: "left",
25686             callingCodes: ["94"]
25687           },
25688           geometry: {
25689             type: "MultiPolygon",
25690             coordinates: [[[[76.59015, 5.591], [85.15017, 5.21497], [80.48418, 10.20786], [79.42124, 9.80115], [79.50447, 8.91876], [76.59015, 5.591]]]]
25691           }
25692         }, {
25693           type: "Feature",
25694           properties: {
25695             iso1A2: "LR",
25696             iso1A3: "LBR",
25697             iso1N3: "430",
25698             wikidata: "Q1014",
25699             nameEn: "Liberia",
25700             groups: ["011", "202", "002", "UN"],
25701             callingCodes: ["231"]
25702           },
25703           geometry: {
25704             type: "MultiPolygon",
25705             coordinates: [[[[-8.47114, 7.55676], [-8.55874, 7.62525], [-8.55874, 7.70167], [-8.67814, 7.69428], [-8.72789, 7.51429], [-8.8448, 7.35149], [-8.85724, 7.26019], [-8.93435, 7.2824], [-9.09107, 7.1985], [-9.18311, 7.30461], [-9.20798, 7.38109], [-9.305, 7.42056], [-9.41943, 7.41809], [-9.48161, 7.37122], [-9.37465, 7.62032], [-9.35724, 7.74111], [-9.44928, 7.9284], [-9.41445, 8.02448], [-9.50898, 8.18455], [-9.47415, 8.35195], [-9.77763, 8.54633], [-10.05873, 8.42578], [-10.05375, 8.50697], [-10.14579, 8.52665], [-10.203, 8.47991], [-10.27575, 8.48711], [-10.30084, 8.30008], [-10.31635, 8.28554], [-10.29839, 8.21283], [-10.35227, 8.15223], [-10.45023, 8.15627], [-10.51554, 8.1393], [-10.57523, 8.04829], [-10.60492, 8.04072], [-10.60422, 7.7739], [-11.29417, 7.21576], [-11.4027, 6.97746], [-11.50429, 6.92704], [-12.15048, 6.15992], [-7.52774, 3.7105], [-7.53259, 4.35145], [-7.59349, 4.8909], [-7.53876, 4.94294], [-7.55369, 5.08667], [-7.48901, 5.14118], [-7.46165, 5.26256], [-7.36463, 5.32944], [-7.43428, 5.42355], [-7.37209, 5.61173], [-7.43926, 5.74787], [-7.43677, 5.84687], [-7.46165, 5.84934], [-7.48155, 5.80974], [-7.67309, 5.94337], [-7.70294, 5.90625], [-7.78254, 5.99037], [-7.79747, 6.07696], [-7.8497, 6.08932], [-7.83478, 6.20309], [-7.90692, 6.27728], [-8.00642, 6.31684], [-8.17557, 6.28222], [-8.3298, 6.36381], [-8.38453, 6.35887], [-8.45666, 6.49977], [-8.48652, 6.43797], [-8.59456, 6.50612], [-8.31736, 6.82837], [-8.29249, 7.1691], [-8.37458, 7.25794], [-8.41935, 7.51203], [-8.47114, 7.55676]]]]
25706           }
25707         }, {
25708           type: "Feature",
25709           properties: {
25710             iso1A2: "LS",
25711             iso1A3: "LSO",
25712             iso1N3: "426",
25713             wikidata: "Q1013",
25714             nameEn: "Lesotho",
25715             groups: ["018", "202", "002", "UN"],
25716             driveSide: "left",
25717             callingCodes: ["266"]
25718           },
25719           geometry: {
25720             type: "MultiPolygon",
25721             coordinates: [[[[29.33204, -29.45598], [29.44883, -29.3772], [29.40524, -29.21246], [28.68043, -28.58744], [28.65091, -28.57025], [28.40612, -28.6215], [28.30518, -28.69531], [28.2348, -28.69471], [28.1317, -28.7293], [28.02503, -28.85991], [27.98675, -28.8787], [27.9392, -28.84864], [27.88933, -28.88156], [27.8907, -28.91612], [27.75458, -28.89839], [27.55974, -29.18954], [27.5158, -29.2261], [27.54258, -29.25575], [27.48679, -29.29349], [27.45125, -29.29708], [27.47254, -29.31968], [27.4358, -29.33465], [27.33464, -29.48161], [27.01016, -29.65439], [27.09489, -29.72796], [27.22719, -30.00718], [27.29603, -30.05473], [27.32555, -30.14785], [27.40778, -30.14577], [27.37293, -30.19401], [27.36649, -30.27246], [27.38108, -30.33456], [27.45452, -30.32239], [27.56901, -30.42504], [27.56781, -30.44562], [27.62137, -30.50509], [27.6521, -30.51707], [27.67819, -30.53437], [27.69467, -30.55862], [27.74814, -30.60635], [28.12073, -30.68072], [28.2319, -30.28476], [28.399, -30.1592], [28.68627, -30.12885], [28.80222, -30.10579], [28.9338, -30.05072], [29.16548, -29.91706], [29.12553, -29.76266], [29.28545, -29.58456], [29.33204, -29.45598]]]]
25722           }
25723         }, {
25724           type: "Feature",
25725           properties: {
25726             iso1A2: "LT",
25727             iso1A3: "LTU",
25728             iso1N3: "440",
25729             wikidata: "Q37",
25730             nameEn: "Lithuania",
25731             groups: ["EU", "154", "150", "UN"],
25732             callingCodes: ["370"]
25733           },
25734           geometry: {
25735             type: "MultiPolygon",
25736             coordinates: [[[[24.89005, 56.46666], [24.83686, 56.41565], [24.70022, 56.40483], [24.57353, 56.31525], [24.58143, 56.29125], [24.42746, 56.26522], [24.32334, 56.30226], [24.13139, 56.24881], [24.02657, 56.3231], [23.75726, 56.37282], [23.49803, 56.34307], [23.40486, 56.37689], [23.31606, 56.3827], [23.17312, 56.36795], [23.09531, 56.30511], [22.96988, 56.41213], [22.83048, 56.367], [22.69354, 56.36284], [22.56441, 56.39305], [22.3361, 56.4016], [22.09728, 56.42851], [22.00548, 56.41508], [21.74558, 56.33181], [21.57888, 56.31406], [21.49736, 56.29106], [21.24644, 56.16917], [21.15016, 56.07818], [20.68447, 56.04073], [20.60454, 55.40986], [20.95181, 55.27994], [21.26425, 55.24456], [21.35465, 55.28427], [21.38446, 55.29348], [21.46766, 55.21115], [21.51095, 55.18507], [21.55605, 55.20311], [21.64954, 55.1791], [21.85521, 55.09493], [21.96505, 55.07353], [21.99543, 55.08691], [22.03984, 55.07888], [22.02582, 55.05078], [22.06087, 55.02935], [22.11697, 55.02131], [22.14267, 55.05345], [22.31562, 55.0655], [22.47688, 55.04408], [22.58907, 55.07085], [22.60075, 55.01863], [22.65451, 54.97037], [22.68723, 54.9811], [22.76422, 54.92521], [22.85083, 54.88711], [22.87317, 54.79492], [22.73631, 54.72952], [22.73397, 54.66604], [22.75467, 54.6483], [22.74225, 54.64339], [22.7522, 54.63525], [22.68021, 54.58486], [22.71293, 54.56454], [22.67788, 54.532], [22.70208, 54.45312], [22.7253, 54.41732], [22.79705, 54.36264], [22.83756, 54.40827], [23.00584, 54.38514], [22.99649, 54.35927], [23.05726, 54.34565], [23.04323, 54.31567], [23.104, 54.29794], [23.13905, 54.31567], [23.15526, 54.31076], [23.15938, 54.29894], [23.24656, 54.25701], [23.3494, 54.25155], [23.39525, 54.21672], [23.42418, 54.17911], [23.45223, 54.17775], [23.49196, 54.14764], [23.52702, 54.04622], [23.48261, 53.98855], [23.51284, 53.95052], [23.61677, 53.92691], [23.71726, 53.93379], [23.80543, 53.89558], [23.81309, 53.94205], [23.95098, 53.9613], [23.98837, 53.92554], [24.19638, 53.96405], [24.34128, 53.90076], [24.44411, 53.90076], [24.62275, 54.00217], [24.69652, 54.01901], [24.69185, 53.96543], [24.74279, 53.96663], [24.85311, 54.02862], [24.77131, 54.11091], [24.96894, 54.17589], [24.991, 54.14241], [25.0728, 54.13419], [25.19199, 54.219], [25.22705, 54.26271], [25.35559, 54.26544], [25.509, 54.30267], [25.56823, 54.25212], [25.51452, 54.17799], [25.54724, 54.14925], [25.64875, 54.1259], [25.71084, 54.16704], [25.78563, 54.15747], [25.78553, 54.23327], [25.68513, 54.31727], [25.55425, 54.31591], [25.5376, 54.33158], [25.63371, 54.42075], [25.62203, 54.4656], [25.64813, 54.48704], [25.68045, 54.5321], [25.75977, 54.57252], [25.74122, 54.80108], [25.89462, 54.93438], [25.99129, 54.95705], [26.05907, 54.94631], [26.13386, 54.98924], [26.20397, 54.99729], [26.26941, 55.08032], [26.23202, 55.10439], [26.30628, 55.12536], [26.35121, 55.1525], [26.46249, 55.12814], [26.51481, 55.16051], [26.54753, 55.14181], [26.69243, 55.16718], [26.68075, 55.19787], [26.72983, 55.21788], [26.73017, 55.24226], [26.835, 55.28182], [26.83266, 55.30444], [26.80929, 55.31642], [26.6714, 55.33902], [26.5709, 55.32572], [26.44937, 55.34832], [26.5522, 55.40277], [26.55094, 55.5093], [26.63167, 55.57887], [26.63231, 55.67968], [26.58248, 55.6754], [26.46661, 55.70375], [26.39561, 55.71156], [26.18509, 55.86813], [26.03815, 55.95884], [25.90047, 56.0013], [25.85893, 56.00188], [25.81773, 56.05444], [25.69246, 56.08892], [25.68588, 56.14725], [25.53621, 56.16663], [25.39751, 56.15707], [25.23099, 56.19147], [25.09325, 56.1878], [25.05762, 56.26742], [24.89005, 56.46666]]]]
25737           }
25738         }, {
25739           type: "Feature",
25740           properties: {
25741             iso1A2: "LU",
25742             iso1A3: "LUX",
25743             iso1N3: "442",
25744             wikidata: "Q32",
25745             nameEn: "Luxembourg",
25746             groups: ["EU", "155", "150", "UN"],
25747             callingCodes: ["352"]
25748           },
25749           geometry: {
25750             type: "MultiPolygon",
25751             coordinates: [[[[6.1379, 50.12964], [6.1137, 50.13668], [6.12028, 50.16374], [6.08577, 50.17246], [6.06406, 50.15344], [6.03093, 50.16362], [6.02488, 50.18283], [5.96453, 50.17259], [5.95929, 50.13295], [5.89488, 50.11476], [5.8857, 50.07824], [5.85474, 50.06342], [5.86904, 50.04614], [5.8551, 50.02683], [5.81866, 50.01286], [5.82331, 49.99662], [5.83968, 49.9892], [5.83467, 49.97823], [5.81163, 49.97142], [5.80833, 49.96451], [5.77291, 49.96056], [5.77314, 49.93646], [5.73621, 49.89796], [5.78415, 49.87922], [5.75269, 49.8711], [5.75861, 49.85631], [5.74567, 49.85368], [5.75884, 49.84811], [5.74953, 49.84709], [5.74975, 49.83933], [5.74076, 49.83823], [5.7404, 49.83452], [5.74844, 49.82435], [5.74364, 49.82058], [5.74953, 49.81428], [5.75409, 49.79239], [5.78871, 49.7962], [5.82245, 49.75048], [5.83149, 49.74729], [5.82562, 49.72395], [5.84193, 49.72161], [5.86503, 49.72739], [5.88677, 49.70951], [5.86527, 49.69291], [5.86175, 49.67862], [5.9069, 49.66377], [5.90164, 49.6511], [5.90599, 49.63853], [5.88552, 49.63507], [5.88393, 49.62802], [5.87609, 49.62047], [5.8762, 49.60898], [5.84826, 49.5969], [5.84971, 49.58674], [5.86986, 49.58756], [5.87256, 49.57539], [5.8424, 49.56082], [5.84692, 49.55663], [5.84143, 49.5533], [5.81838, 49.54777], [5.80871, 49.5425], [5.81664, 49.53775], [5.83648, 49.5425], [5.84466, 49.53027], [5.83467, 49.52717], [5.83389, 49.52152], [5.86571, 49.50015], [5.94128, 49.50034], [5.94224, 49.49608], [5.96876, 49.49053], [5.97693, 49.45513], [6.02648, 49.45451], [6.02743, 49.44845], [6.04176, 49.44801], [6.05553, 49.46663], [6.07887, 49.46399], [6.08373, 49.45594], [6.10072, 49.45268], [6.09845, 49.46351], [6.10325, 49.4707], [6.12346, 49.4735], [6.12814, 49.49365], [6.14321, 49.48796], [6.16115, 49.49297], [6.15366, 49.50226], [6.17386, 49.50934], [6.19543, 49.50536], [6.2409, 49.51408], [6.25029, 49.50609], [6.27875, 49.503], [6.28818, 49.48465], [6.3687, 49.4593], [6.36778, 49.46937], [6.36907, 49.48931], [6.36788, 49.50377], [6.35666, 49.52931], [6.38072, 49.55171], [6.38228, 49.55855], [6.35825, 49.57053], [6.36676, 49.57813], [6.38024, 49.57593], [6.38342, 49.5799], [6.37464, 49.58886], [6.385, 49.59946], [6.39822, 49.60081], [6.41861, 49.61723], [6.4413, 49.65722], [6.43768, 49.66021], [6.42726, 49.66078], [6.42937, 49.66857], [6.44654, 49.67799], [6.46048, 49.69092], [6.48014, 49.69767], [6.49785, 49.71118], [6.50647, 49.71353], [6.5042, 49.71808], [6.49694, 49.72205], [6.49535, 49.72645], [6.50261, 49.72718], [6.51397, 49.72058], [6.51805, 49.72425], [6.50193, 49.73291], [6.50174, 49.75292], [6.51646, 49.75961], [6.51828, 49.76855], [6.51056, 49.77515], [6.51669, 49.78336], [6.50534, 49.78952], [6.52169, 49.79787], [6.53122, 49.80666], [6.52121, 49.81338], [6.51215, 49.80124], [6.50647, 49.80916], [6.48718, 49.81267], [6.47111, 49.82263], [6.45425, 49.81164], [6.44131, 49.81443], [6.42905, 49.81091], [6.42521, 49.81591], [6.40022, 49.82029], [6.36576, 49.85032], [6.34267, 49.84974], [6.33585, 49.83785], [6.32098, 49.83728], [6.32303, 49.85133], [6.30963, 49.87021], [6.29692, 49.86685], [6.28874, 49.87592], [6.26146, 49.88203], [6.23496, 49.89972], [6.22926, 49.92096], [6.21882, 49.92403], [6.22608, 49.929], [6.22094, 49.94955], [6.19856, 49.95053], [6.19089, 49.96991], [6.18045, 49.96611], [6.18554, 49.95622], [6.17872, 49.9537], [6.16466, 49.97086], [6.1701, 49.98518], [6.14147, 49.99563], [6.14948, 50.00908], [6.13806, 50.01056], [6.1295, 50.01849], [6.13273, 50.02019], [6.13794, 50.01466], [6.14666, 50.02207], [6.13044, 50.02929], [6.13458, 50.04141], [6.11274, 50.05916], [6.12055, 50.09171], [6.1379, 50.12964]]]]
25752           }
25753         }, {
25754           type: "Feature",
25755           properties: {
25756             iso1A2: "LV",
25757             iso1A3: "LVA",
25758             iso1N3: "428",
25759             wikidata: "Q211",
25760             nameEn: "Latvia",
25761             groups: ["EU", "154", "150", "UN"],
25762             callingCodes: ["371"]
25763           },
25764           geometry: {
25765             type: "MultiPolygon",
25766             coordinates: [[[[27.34698, 57.52242], [26.90364, 57.62823], [26.54675, 57.51813], [26.46527, 57.56885], [26.29253, 57.59244], [26.1866, 57.6849], [26.2029, 57.7206], [26.08098, 57.76619], [26.0543, 57.76105], [26.03332, 57.7718], [26.02415, 57.76865], [26.02069, 57.77169], [26.0266, 57.77441], [26.027, 57.78158], [26.02456, 57.78342], [26.0324, 57.79037], [26.05949, 57.84744], [25.73499, 57.90193], [25.29581, 58.08288], [25.28237, 57.98539], [25.19484, 58.0831], [24.3579, 57.87471], [24.26221, 57.91787], [23.20055, 57.56697], [22.80496, 57.87798], [19.84909, 57.57876], [19.64795, 57.06466], [20.68447, 56.04073], [21.15016, 56.07818], [21.24644, 56.16917], [21.49736, 56.29106], [21.57888, 56.31406], [21.74558, 56.33181], [22.00548, 56.41508], [22.09728, 56.42851], [22.3361, 56.4016], [22.56441, 56.39305], [22.69354, 56.36284], [22.83048, 56.367], [22.96988, 56.41213], [23.09531, 56.30511], [23.17312, 56.36795], [23.31606, 56.3827], [23.40486, 56.37689], [23.49803, 56.34307], [23.75726, 56.37282], [24.02657, 56.3231], [24.13139, 56.24881], [24.32334, 56.30226], [24.42746, 56.26522], [24.58143, 56.29125], [24.57353, 56.31525], [24.70022, 56.40483], [24.83686, 56.41565], [24.89005, 56.46666], [25.05762, 56.26742], [25.09325, 56.1878], [25.23099, 56.19147], [25.39751, 56.15707], [25.53621, 56.16663], [25.68588, 56.14725], [25.69246, 56.08892], [25.81773, 56.05444], [25.85893, 56.00188], [25.90047, 56.0013], [26.03815, 55.95884], [26.18509, 55.86813], [26.39561, 55.71156], [26.46661, 55.70375], [26.58248, 55.6754], [26.63231, 55.67968], [26.64888, 55.70515], [26.71802, 55.70645], [26.76872, 55.67658], [26.87448, 55.7172], [26.97153, 55.8102], [27.1559, 55.85032], [27.27804, 55.78299], [27.3541, 55.8089], [27.61683, 55.78558], [27.63065, 55.89687], [27.97865, 56.11849], [28.15217, 56.16964], [28.23716, 56.27588], [28.16599, 56.37806], [28.19057, 56.44637], [28.10069, 56.524], [28.13526, 56.57989], [28.04768, 56.59004], [27.86101, 56.88204], [27.66511, 56.83921], [27.86101, 57.29402], [27.52453, 57.42826], [27.56832, 57.53728], [27.34698, 57.52242]]]]
25767           }
25768         }, {
25769           type: "Feature",
25770           properties: {
25771             iso1A2: "LY",
25772             iso1A3: "LBY",
25773             iso1N3: "434",
25774             wikidata: "Q1016",
25775             nameEn: "Libya",
25776             groups: ["015", "002", "UN"],
25777             callingCodes: ["218"]
25778           },
25779           geometry: {
25780             type: "MultiPolygon",
25781             coordinates: [[[[26.92891, 33.39516], [11.58941, 33.36891], [11.55852, 33.1409], [11.51549, 33.09826], [11.46037, 32.6307], [11.57828, 32.48013], [11.53898, 32.4138], [11.04234, 32.2145], [10.7315, 31.97235], [10.62788, 31.96629], [10.48497, 31.72956], [10.31364, 31.72648], [10.12239, 31.42098], [10.29516, 30.90337], [9.88152, 30.34074], [9.76848, 30.34366], [9.55544, 30.23971], [9.3876, 30.16738], [9.78136, 29.40961], [9.89569, 26.57696], [9.51696, 26.39148], [9.38834, 26.19288], [10.03146, 25.35635], [10.02432, 24.98124], [10.33159, 24.5465], [10.85323, 24.5595], [11.41061, 24.21456], [11.62498, 24.26669], [11.96886, 23.51735], [13.5631, 23.16574], [14.22918, 22.61719], [14.99751, 23.00539], [15.99566, 23.49639], [23.99539, 19.49944], [23.99715, 20.00038], [24.99794, 19.99661], [24.99885, 21.99535], [24.99968, 29.24574], [24.71117, 30.17441], [25.01077, 30.73861], [24.8458, 31.39877], [26.92891, 33.39516]]]]
25782           }
25783         }, {
25784           type: "Feature",
25785           properties: {
25786             iso1A2: "MA",
25787             iso1A3: "MAR",
25788             iso1N3: "504",
25789             wikidata: "Q1028",
25790             nameEn: "Morocco",
25791             groups: ["015", "002", "UN"],
25792             callingCodes: ["212"]
25793           },
25794           geometry: {
25795             type: "MultiPolygon",
25796             coordinates: [[[[-2.27707, 35.35051], [-5.10878, 36.05227], [-7.2725, 35.73269], [-14.43883, 27.02969], [-17.27295, 21.93519], [-17.21511, 21.34226], [-17.02707, 21.34022], [-16.9978, 21.36239], [-16.44269, 21.39745], [-14.78487, 21.36587], [-14.47329, 21.63839], [-14.48112, 22.00886], [-14.1291, 22.41636], [-14.10361, 22.75501], [-13.75627, 23.77231], [-13.00628, 24.01923], [-12.92147, 24.39502], [-12.12281, 25.13682], [-12.06001, 26.04442], [-11.62052, 26.05229], [-11.38635, 26.611], [-11.23622, 26.72023], [-11.35695, 26.8505], [-10.68417, 26.90984], [-9.81998, 26.71379], [-9.56957, 26.90042], [-9.08698, 26.98639], [-8.71787, 26.9898], [-8.77527, 27.66663], [-8.66879, 27.6666], [-8.6715, 28.71194], [-7.61585, 29.36252], [-6.95824, 29.50924], [-6.78351, 29.44634], [-6.69965, 29.51623], [-5.75616, 29.61407], [-5.72121, 29.52322], [-5.58831, 29.48103], [-5.21671, 29.95253], [-4.6058, 30.28343], [-4.31774, 30.53229], [-3.64735, 30.67539], [-3.65418, 30.85566], [-3.54944, 31.0503], [-3.77103, 31.14984], [-3.77647, 31.31912], [-3.66386, 31.39202], [-3.66314, 31.6339], [-2.82784, 31.79459], [-2.93873, 32.06557], [-2.46166, 32.16603], [-1.22829, 32.07832], [-1.15735, 32.12096], [-1.24453, 32.1917], [-1.24998, 32.32993], [-0.9912, 32.52467], [-1.37794, 32.73628], [-1.54244, 32.95499], [-1.46249, 33.0499], [-1.67067, 33.27084], [-1.59508, 33.59929], [-1.73494, 33.71721], [-1.64666, 34.10405], [-1.78042, 34.39018], [-1.69788, 34.48056], [-1.84569, 34.61907], [-1.73707, 34.74226], [-1.97469, 34.886], [-1.97833, 34.93218], [-2.04734, 34.93218], [-2.21445, 35.04378], [-2.21248, 35.08532], [-2.27707, 35.35051]], [[-2.91909, 35.33927], [-2.92272, 35.27509], [-2.93893, 35.26737], [-2.95065, 35.26576], [-2.95431, 35.2728], [-2.96516, 35.27967], [-2.96826, 35.28296], [-2.96507, 35.28801], [-2.97035, 35.28852], [-2.96978, 35.29459], [-2.96648, 35.30475], [-2.96038, 35.31609], [-2.91909, 35.33927]], [[-3.90602, 35.21494], [-3.89343, 35.22728], [-3.88372, 35.20767], [-3.90602, 35.21494]], [[-4.30191, 35.17419], [-4.29436, 35.17149], [-4.30112, 35.17058], [-4.30191, 35.17419]], [[-2.40316, 35.16893], [-2.45965, 35.16527], [-2.43262, 35.20652], [-2.40316, 35.16893]], [[-5.38491, 35.92591], [-5.21179, 35.90091], [-5.34379, 35.8711], [-5.35844, 35.87375], [-5.37338, 35.88417], [-5.38491, 35.92591]]]]
25797           }
25798         }, {
25799           type: "Feature",
25800           properties: {
25801             iso1A2: "MC",
25802             iso1A3: "MCO",
25803             iso1N3: "492",
25804             wikidata: "Q235",
25805             nameEn: "Monaco",
25806             groups: ["155", "150", "UN"],
25807             callingCodes: ["377"]
25808           },
25809           geometry: {
25810             type: "MultiPolygon",
25811             coordinates: [[[[7.47823, 43.73341], [7.4379, 43.74963], [7.4389, 43.75151], [7.43708, 43.75197], [7.43624, 43.75014], [7.43013, 43.74895], [7.42809, 43.74396], [7.42443, 43.74087], [7.42299, 43.74176], [7.42062, 43.73977], [7.41233, 43.73439], [7.41298, 43.73311], [7.41291, 43.73168], [7.41113, 43.73156], [7.40903, 43.7296], [7.42422, 43.72209], [7.47823, 43.73341]]]]
25812           }
25813         }, {
25814           type: "Feature",
25815           properties: {
25816             iso1A2: "MD",
25817             iso1A3: "MDA",
25818             iso1N3: "498",
25819             wikidata: "Q217",
25820             nameEn: "Moldova",
25821             groups: ["151", "150", "UN"],
25822             callingCodes: ["373"]
25823           },
25824           geometry: {
25825             type: "MultiPolygon",
25826             coordinates: [[[[27.74422, 48.45926], [27.6658, 48.44034], [27.59027, 48.46311], [27.5889, 48.49224], [27.46942, 48.454], [27.44333, 48.41209], [27.37741, 48.41026], [27.37604, 48.44398], [27.32159, 48.4434], [27.27855, 48.37534], [27.13434, 48.37288], [27.08078, 48.43214], [27.0231, 48.42485], [27.03821, 48.37653], [26.93384, 48.36558], [26.85556, 48.41095], [26.71274, 48.40388], [26.82809, 48.31629], [26.79239, 48.29071], [26.6839, 48.35828], [26.62823, 48.25804], [26.81161, 48.25049], [26.87708, 48.19919], [26.94265, 48.1969], [26.98042, 48.15752], [26.96119, 48.13003], [27.04118, 48.12522], [27.02985, 48.09083], [27.15622, 47.98538], [27.1618, 47.92391], [27.29069, 47.73722], [27.25519, 47.71366], [27.32202, 47.64009], [27.3979, 47.59473], [27.47942, 47.48113], [27.55731, 47.46637], [27.60263, 47.32507], [27.68706, 47.28962], [27.73172, 47.29248], [27.81892, 47.1381], [28.09095, 46.97621], [28.12173, 46.82283], [28.24808, 46.64305], [28.22281, 46.50481], [28.25769, 46.43334], [28.18902, 46.35283], [28.19864, 46.31869], [28.10937, 46.22852], [28.13684, 46.18099], [28.08612, 46.01105], [28.13111, 45.92819], [28.16568, 45.6421], [28.08927, 45.6051], [28.18741, 45.47358], [28.21139, 45.46895], [28.30201, 45.54744], [28.41836, 45.51715], [28.43072, 45.48538], [28.51449, 45.49982], [28.49252, 45.56716], [28.54196, 45.58062], [28.51587, 45.6613], [28.47879, 45.66994], [28.52823, 45.73803], [28.70401, 45.78019], [28.69852, 45.81753], [28.78503, 45.83475], [28.74383, 45.96664], [28.98004, 46.00385], [29.00613, 46.04962], [28.94643, 46.09176], [29.06656, 46.19716], [28.94953, 46.25852], [28.98478, 46.31803], [29.004, 46.31495], [28.9306, 46.45699], [29.01241, 46.46177], [29.02409, 46.49582], [29.23547, 46.55435], [29.24886, 46.37912], [29.35357, 46.49505], [29.49914, 46.45889], [29.5939, 46.35472], [29.6763, 46.36041], [29.66359, 46.4215], [29.74496, 46.45605], [29.88329, 46.35851], [29.94114, 46.40114], [30.09103, 46.38694], [30.16794, 46.40967], [30.02511, 46.45132], [29.88916, 46.54302], [29.94409, 46.56002], [29.9743, 46.75325], [29.94522, 46.80055], [29.98814, 46.82358], [29.87405, 46.88199], [29.75458, 46.8604], [29.72986, 46.92234], [29.57056, 46.94766], [29.62137, 47.05069], [29.61038, 47.09932], [29.53044, 47.07851], [29.49732, 47.12878], [29.57696, 47.13581], [29.54996, 47.24962], [29.59665, 47.25521], [29.5733, 47.36508], [29.48678, 47.36043], [29.47854, 47.30366], [29.39889, 47.30179], [29.3261, 47.44664], [29.18603, 47.43387], [29.11743, 47.55001], [29.22414, 47.60012], [29.22242, 47.73607], [29.27255, 47.79953], [29.20663, 47.80367], [29.27804, 47.88893], [29.19839, 47.89261], [29.1723, 47.99013], [28.9306, 47.96255], [28.8414, 48.03392], [28.85232, 48.12506], [28.69896, 48.13106], [28.53921, 48.17453], [28.48428, 48.0737], [28.42454, 48.12047], [28.43701, 48.15832], [28.38712, 48.17567], [28.34009, 48.13147], [28.30609, 48.14018], [28.30586, 48.1597], [28.34912, 48.1787], [28.36996, 48.20543], [28.35519, 48.24957], [28.32508, 48.23384], [28.2856, 48.23202], [28.19314, 48.20749], [28.17666, 48.25963], [28.07504, 48.23494], [28.09873, 48.3124], [28.04527, 48.32661], [27.95883, 48.32368], [27.88391, 48.36699], [27.87533, 48.4037], [27.81902, 48.41874], [27.79225, 48.44244], [27.74422, 48.45926]]]]
25827           }
25828         }, {
25829           type: "Feature",
25830           properties: {
25831             iso1A2: "ME",
25832             iso1A3: "MNE",
25833             iso1N3: "499",
25834             wikidata: "Q236",
25835             nameEn: "Montenegro",
25836             groups: ["039", "150", "UN"],
25837             callingCodes: ["382"]
25838           },
25839           geometry: {
25840             type: "MultiPolygon",
25841             coordinates: [[[[19.22807, 43.5264], [19.15685, 43.53943], [19.13933, 43.5282], [19.04934, 43.50384], [19.01078, 43.55806], [18.91379, 43.50299], [18.95469, 43.49367], [18.96053, 43.45042], [19.01078, 43.43854], [19.04071, 43.397], [19.08673, 43.31453], [19.08206, 43.29668], [19.04233, 43.30008], [19.00844, 43.24988], [18.95001, 43.29327], [18.95819, 43.32899], [18.90911, 43.36383], [18.83912, 43.34795], [18.84794, 43.33735], [18.85342, 43.32426], [18.76538, 43.29838], [18.6976, 43.25243], [18.71747, 43.2286], [18.66605, 43.2056], [18.64735, 43.14766], [18.66254, 43.03928], [18.52232, 43.01451], [18.49076, 42.95553], [18.49661, 42.89306], [18.4935, 42.86433], [18.47633, 42.85829], [18.45921, 42.81682], [18.47324, 42.74992], [18.56789, 42.72074], [18.55221, 42.69045], [18.54603, 42.69171], [18.54841, 42.68328], [18.57373, 42.64429], [18.52232, 42.62279], [18.55504, 42.58409], [18.53751, 42.57376], [18.49778, 42.58409], [18.43735, 42.55921], [18.44307, 42.51077], [18.43588, 42.48556], [18.52152, 42.42302], [18.54128, 42.39171], [18.45131, 42.21682], [19.26406, 41.74971], [19.37597, 41.84849], [19.37451, 41.8842], [19.33812, 41.90669], [19.34601, 41.95675], [19.37691, 41.96977], [19.36867, 42.02564], [19.37548, 42.06835], [19.40687, 42.10024], [19.28623, 42.17745], [19.42, 42.33019], [19.42352, 42.36546], [19.4836, 42.40831], [19.65972, 42.62774], [19.73244, 42.66299], [19.77375, 42.58517], [19.74731, 42.57422], [19.76549, 42.50237], [19.82333, 42.46581], [19.9324, 42.51699], [20.00842, 42.5109], [20.01834, 42.54622], [20.07761, 42.55582], [20.0969, 42.65559], [20.02915, 42.71147], [20.02088, 42.74789], [20.04898, 42.77701], [20.2539, 42.76245], [20.27869, 42.81945], [20.35692, 42.8335], [20.34528, 42.90676], [20.16415, 42.97177], [20.14896, 42.99058], [20.12325, 42.96237], [20.05431, 42.99571], [20.04729, 43.02732], [19.98887, 43.0538], [19.96549, 43.11098], [19.92576, 43.08539], [19.79255, 43.11951], [19.76918, 43.16044], [19.64063, 43.19027], [19.62661, 43.2286], [19.54598, 43.25158], [19.52962, 43.31623], [19.48171, 43.32644], [19.44315, 43.38846], [19.22229, 43.47926], [19.22807, 43.5264]]]]
25842           }
25843         }, {
25844           type: "Feature",
25845           properties: {
25846             iso1A2: "MF",
25847             iso1A3: "MAF",
25848             iso1N3: "663",
25849             wikidata: "Q126125",
25850             nameEn: "Saint-Martin",
25851             country: "FR",
25852             groups: ["Q3320166", "EU", "029", "003", "419", "019", "UN"],
25853             callingCodes: ["590"]
25854           },
25855           geometry: {
25856             type: "MultiPolygon",
25857             coordinates: [[[[-62.93924, 18.02904], [-62.62718, 18.26185], [-63.35989, 18.06012], [-63.33064, 17.9615], [-63.13502, 18.05445], [-63.11042, 18.05339], [-63.09686, 18.04608], [-63.07759, 18.04943], [-63.0579, 18.06614], [-63.04039, 18.05619], [-63.02323, 18.05757], [-62.93924, 18.02904]]]]
25858           }
25859         }, {
25860           type: "Feature",
25861           properties: {
25862             iso1A2: "MG",
25863             iso1A3: "MDG",
25864             iso1N3: "450",
25865             wikidata: "Q1019",
25866             nameEn: "Madagascar",
25867             aliases: ["RM"],
25868             groups: ["014", "202", "002", "UN"],
25869             callingCodes: ["261"]
25870           },
25871           geometry: {
25872             type: "MultiPolygon",
25873             coordinates: [[[[51.93891, -10.85085], [45.84651, -12.77177], [42.14681, -19.63341], [45.80092, -33.00974], [51.93891, -10.85085]]]]
25874           }
25875         }, {
25876           type: "Feature",
25877           properties: {
25878             iso1A2: "MH",
25879             iso1A3: "MHL",
25880             iso1N3: "584",
25881             wikidata: "Q709",
25882             nameEn: "Marshall Islands",
25883             groups: ["057", "009", "UN"],
25884             roadSpeedUnit: "mph",
25885             callingCodes: ["692"]
25886           },
25887           geometry: {
25888             type: "MultiPolygon",
25889             coordinates: [[[[169, 3.9], [173.53711, 5.70687], [169.29099, 15.77133], [159.04653, 10.59067], [169, 3.9]]]]
25890           }
25891         }, {
25892           type: "Feature",
25893           properties: {
25894             iso1A2: "MK",
25895             iso1A3: "MKD",
25896             iso1N3: "807",
25897             wikidata: "Q221",
25898             nameEn: "North Macedonia",
25899             groups: ["039", "150", "UN"],
25900             callingCodes: ["389"]
25901           },
25902           geometry: {
25903             type: "MultiPolygon",
25904             coordinates: [[[[22.34773, 42.31725], [22.29275, 42.34913], [22.29605, 42.37477], [22.16384, 42.32103], [22.02908, 42.29848], [21.94405, 42.34669], [21.91595, 42.30392], [21.84654, 42.3247], [21.77176, 42.2648], [21.70111, 42.23789], [21.58992, 42.25915], [21.52145, 42.24465], [21.50823, 42.27156], [21.43882, 42.2789], [21.43882, 42.23609], [21.38428, 42.24465], [21.30496, 42.1418], [21.29913, 42.13954], [21.31983, 42.10993], [21.22728, 42.08909], [21.16614, 42.19815], [21.11491, 42.20794], [20.75464, 42.05229], [20.76786, 41.91839], [20.68523, 41.85318], [20.59524, 41.8818], [20.55976, 41.87068], [20.57144, 41.7897], [20.53405, 41.78099], [20.51301, 41.72433], [20.52937, 41.69292], [20.51769, 41.65975], [20.55508, 41.58113], [20.52103, 41.56473], [20.45809, 41.5549], [20.45331, 41.51436], [20.49039, 41.49277], [20.51301, 41.442], [20.55976, 41.4087], [20.52119, 41.34381], [20.49432, 41.33679], [20.51068, 41.2323], [20.59715, 41.13644], [20.58546, 41.11179], [20.59832, 41.09066], [20.63454, 41.0889], [20.65558, 41.08009], [20.71634, 40.91781], [20.73504, 40.9081], [20.81567, 40.89662], [20.83671, 40.92752], [20.94305, 40.92399], [20.97693, 40.90103], [20.97887, 40.85475], [21.15262, 40.85546], [21.21105, 40.8855], [21.25779, 40.86165], [21.35595, 40.87578], [21.41555, 40.9173], [21.53007, 40.90759], [21.57448, 40.86076], [21.69601, 40.9429], [21.7556, 40.92525], [21.91102, 41.04786], [21.90869, 41.09191], [22.06527, 41.15617], [22.1424, 41.12449], [22.17629, 41.15969], [22.26744, 41.16409], [22.42285, 41.11921], [22.5549, 41.13065], [22.58295, 41.11568], [22.62852, 41.14385], [22.65306, 41.18168], [22.71266, 41.13945], [22.74538, 41.16321], [22.76408, 41.32225], [22.81199, 41.3398], [22.93334, 41.34104], [22.96331, 41.35782], [22.95513, 41.63265], [23.03342, 41.71034], [23.01239, 41.76527], [22.96682, 41.77137], [22.90254, 41.87587], [22.86749, 42.02275], [22.67701, 42.06614], [22.51224, 42.15457], [22.50289, 42.19527], [22.47251, 42.20393], [22.38136, 42.30339], [22.34773, 42.31725]]]]
25905           }
25906         }, {
25907           type: "Feature",
25908           properties: {
25909             iso1A2: "ML",
25910             iso1A3: "MLI",
25911             iso1N3: "466",
25912             wikidata: "Q912",
25913             nameEn: "Mali",
25914             groups: ["011", "202", "002", "UN"],
25915             callingCodes: ["223"]
25916           },
25917           geometry: {
25918             type: "MultiPolygon",
25919             coordinates: [[[[-4.83423, 24.99935], [-6.57191, 25.0002], [-5.60725, 16.49919], [-5.33435, 16.33354], [-5.50165, 15.50061], [-9.32979, 15.50032], [-9.31106, 15.69412], [-9.33314, 15.7044], [-9.44673, 15.60553], [-9.40447, 15.4396], [-10.71721, 15.4223], [-10.90932, 15.11001], [-11.43483, 15.62339], [-11.70705, 15.51558], [-11.94903, 14.76143], [-12.23936, 14.76324], [-11.93043, 13.84505], [-12.06897, 13.71049], [-11.83345, 13.33333], [-11.63025, 13.39174], [-11.39935, 12.97808], [-11.37536, 12.40788], [-11.50006, 12.17826], [-11.24136, 12.01286], [-10.99758, 12.24634], [-10.80355, 12.1053], [-10.71897, 11.91552], [-10.30604, 12.24634], [-9.714, 12.0226], [-9.63938, 12.18312], [-9.32097, 12.29009], [-9.38067, 12.48446], [-9.13689, 12.50875], [-8.94784, 12.34842], [-8.80854, 11.66715], [-8.40058, 11.37466], [-8.66923, 10.99397], [-8.35083, 11.06234], [-8.2667, 10.91762], [-8.32614, 10.69273], [-8.22711, 10.41722], [-8.10207, 10.44649], [-7.9578, 10.2703], [-7.97971, 10.17117], [-7.92107, 10.15577], [-7.63048, 10.46334], [-7.54462, 10.40921], [-7.52261, 10.4655], [-7.44555, 10.44602], [-7.3707, 10.24677], [-7.13331, 10.24877], [-7.0603, 10.14711], [-7.00966, 10.15794], [-6.97444, 10.21644], [-7.01186, 10.25111], [-6.93921, 10.35291], [-6.68164, 10.35074], [-6.63541, 10.66893], [-6.52974, 10.59104], [-6.42847, 10.5694], [-6.40646, 10.69922], [-6.325, 10.68624], [-6.24795, 10.74248], [-6.1731, 10.46983], [-6.18851, 10.24244], [-5.99478, 10.19694], [-5.78124, 10.43952], [-5.65135, 10.46767], [-5.51058, 10.43177], [-5.46643, 10.56074], [-5.47083, 10.75329], [-5.41579, 10.84628], [-5.49284, 11.07538], [-5.32994, 11.13371], [-5.32553, 11.21578], [-5.25949, 11.24816], [-5.25509, 11.36905], [-5.20665, 11.43811], [-5.22867, 11.60421], [-5.29251, 11.61715], [-5.26389, 11.75728], [-5.40258, 11.8327], [-5.26389, 11.84778], [-5.07897, 11.97918], [-4.72893, 12.01579], [-4.70692, 12.06746], [-4.62987, 12.06531], [-4.62546, 12.13204], [-4.54841, 12.1385], [-4.57703, 12.19875], [-4.41412, 12.31922], [-4.47356, 12.71252], [-4.238, 12.71467], [-4.21819, 12.95722], [-4.34477, 13.12927], [-3.96501, 13.49778], [-3.90558, 13.44375], [-3.96282, 13.38164], [-3.7911, 13.36665], [-3.54454, 13.1781], [-3.4313, 13.1588], [-3.43507, 13.27272], [-3.23599, 13.29035], [-3.28396, 13.5422], [-3.26407, 13.70699], [-2.88189, 13.64921], [-2.90831, 13.81174], [-2.84667, 14.05532], [-2.66175, 14.14713], [-2.47587, 14.29671], [-2.10223, 14.14878], [-1.9992, 14.19011], [-1.97945, 14.47709], [-1.68083, 14.50023], [-1.32166, 14.72774], [-1.05875, 14.7921], [-0.72004, 15.08655], [-0.24673, 15.07805], [0.06588, 14.96961], [0.23859, 15.00135], [0.72632, 14.95898], [0.96711, 14.98275], [1.31275, 15.27978], [3.01806, 15.34571], [3.03134, 15.42221], [3.50368, 15.35934], [4.19893, 16.39923], [4.21787, 17.00118], [4.26762, 17.00432], [4.26651, 19.14224], [3.36082, 18.9745], [3.12501, 19.1366], [3.24648, 19.81703], [1.20992, 20.73533], [1.15698, 21.12843], [-4.83423, 24.99935]]]]
25920           }
25921         }, {
25922           type: "Feature",
25923           properties: {
25924             iso1A2: "MM",
25925             iso1A3: "MMR",
25926             iso1N3: "104",
25927             wikidata: "Q836",
25928             nameEn: "Myanmar",
25929             aliases: ["Burma", "BU"],
25930             groups: ["035", "142", "UN"],
25931             callingCodes: ["95"]
25932           },
25933           geometry: {
25934             type: "MultiPolygon",
25935             coordinates: [[[[92.62187, 21.87037], [92.59775, 21.6092], [92.68152, 21.28454], [92.60187, 21.24615], [92.55105, 21.3856], [92.43158, 21.37025], [92.37939, 21.47764], [92.20087, 21.337], [92.17752, 21.17445], [92.26071, 21.05697], [92.47409, 20.38654], [92.61042, 13.76986], [94.6371, 13.81803], [97.63455, 9.60854], [98.12555, 9.44056], [98.33094, 9.91973], [98.47298, 9.95782], [98.52291, 9.92389], [98.55174, 9.92804], [98.7391, 10.31488], [98.81944, 10.52761], [98.77275, 10.62548], [98.78511, 10.68351], [98.86819, 10.78336], [99.0069, 10.85485], [98.99701, 10.92962], [99.02337, 10.97217], [99.06938, 10.94857], [99.32756, 11.28545], [99.31573, 11.32081], [99.39485, 11.3925], [99.47598, 11.62434], [99.5672, 11.62732], [99.64108, 11.78948], [99.64891, 11.82699], [99.53424, 12.02317], [99.56445, 12.14805], [99.47519, 12.1353], [99.409, 12.60603], [99.29254, 12.68921], [99.18905, 12.84799], [99.18748, 12.9898], [99.10646, 13.05804], [99.12225, 13.19847], [99.20617, 13.20575], [99.16695, 13.72621], [98.97356, 14.04868], [98.56762, 14.37701], [98.24874, 14.83013], [98.18821, 15.13125], [98.22, 15.21327], [98.30446, 15.30667], [98.40522, 15.25268], [98.41906, 15.27103], [98.39351, 15.34177], [98.4866, 15.39154], [98.56027, 15.33471], [98.58598, 15.46821], [98.541, 15.65406], [98.59853, 15.87197], [98.57019, 16.04578], [98.69585, 16.13353], [98.8376, 16.11706], [98.92656, 16.36425], [98.84485, 16.42354], [98.68074, 16.27068], [98.63817, 16.47424], [98.57912, 16.55983], [98.5695, 16.62826], [98.51113, 16.64503], [98.51833, 16.676], [98.51472, 16.68521], [98.51579, 16.69433], [98.51043, 16.70107], [98.49713, 16.69022], [98.50253, 16.7139], [98.46994, 16.73613], [98.53833, 16.81934], [98.49603, 16.8446], [98.52624, 16.89979], [98.39441, 17.06266], [98.34566, 17.04822], [98.10439, 17.33847], [98.11185, 17.36829], [97.91829, 17.54504], [97.76407, 17.71595], [97.66794, 17.88005], [97.73723, 17.97912], [97.60841, 18.23846], [97.64116, 18.29778], [97.56219, 18.33885], [97.50383, 18.26844], [97.34522, 18.54596], [97.36444, 18.57138], [97.5258, 18.4939], [97.76752, 18.58097], [97.73836, 18.88478], [97.66487, 18.9371], [97.73654, 18.9812], [97.73797, 19.04261], [97.83479, 19.09972], [97.84024, 19.22217], [97.78606, 19.26769], [97.84186, 19.29526], [97.78769, 19.39429], [97.88423, 19.5041], [97.84715, 19.55782], [98.04364, 19.65755], [98.03314, 19.80941], [98.13829, 19.78541], [98.24884, 19.67876], [98.51182, 19.71303], [98.56065, 19.67807], [98.83661, 19.80931], [98.98679, 19.7419], [99.0735, 20.10298], [99.20328, 20.12877], [99.416, 20.08614], [99.52943, 20.14811], [99.5569, 20.20676], [99.46077, 20.36198], [99.46008, 20.39673], [99.68255, 20.32077], [99.81096, 20.33687], [99.86383, 20.44371], [99.88211, 20.44488], [99.88451, 20.44596], [99.89168, 20.44548], [99.89301, 20.44311], [99.89692, 20.44789], [99.90499, 20.4487], [99.91616, 20.44986], [99.95721, 20.46301], [100.08404, 20.36626], [100.1957, 20.68247], [100.36375, 20.82783], [100.51079, 20.82194], [100.60112, 20.8347], [100.64628, 20.88279], [100.50974, 20.88574], [100.55281, 21.02796], [100.63578, 21.05639], [100.72716, 21.31786], [100.80173, 21.2934], [101.00234, 21.39612], [101.16198, 21.52808], [101.15156, 21.56129], [101.11744, 21.77659], [100.87265, 21.67396], [100.72143, 21.51898], [100.57861, 21.45637], [100.4811, 21.46148], [100.42892, 21.54325], [100.35201, 21.53176], [100.25863, 21.47043], [100.18447, 21.51898], [100.1625, 21.48704], [100.12542, 21.50365], [100.10757, 21.59945], [100.17486, 21.65306], [100.12679, 21.70539], [100.04956, 21.66843], [99.98654, 21.71064], [99.94003, 21.82782], [99.99084, 21.97053], [99.96612, 22.05965], [99.85351, 22.04183], [99.47585, 22.13345], [99.33166, 22.09656], [99.1552, 22.15874], [99.19176, 22.16983], [99.17318, 22.18025], [99.28771, 22.4105], [99.37972, 22.50188], [99.38247, 22.57544], [99.31243, 22.73893], [99.45654, 22.85726], [99.43537, 22.94086], [99.54218, 22.90014], [99.52214, 23.08218], [99.34127, 23.13099], [99.25741, 23.09025], [99.04601, 23.12215], [99.05975, 23.16382], [98.88597, 23.18656], [98.92515, 23.29535], [98.93958, 23.31414], [98.87573, 23.33038], [98.92104, 23.36946], [98.87683, 23.48995], [98.82877, 23.47908], [98.80294, 23.5345], [98.88396, 23.59555], [98.81775, 23.694], [98.82933, 23.72921], [98.79607, 23.77947], [98.68209, 23.80492], [98.67797, 23.9644], [98.89632, 24.10612], [98.87998, 24.15624], [98.85319, 24.13042], [98.59256, 24.08371], [98.54476, 24.13119], [98.20666, 24.11406], [98.07806, 24.07988], [98.06703, 24.08028], [98.0607, 24.07812], [98.05671, 24.07961], [98.05302, 24.07408], [98.04709, 24.07616], [97.99583, 24.04932], [97.98691, 24.03897], [97.93951, 24.01953], [97.90998, 24.02094], [97.88616, 24.00463], [97.88414, 23.99405], [97.88814, 23.98605], [97.89683, 23.98389], [97.89676, 23.97931], [97.8955, 23.97758], [97.88811, 23.97446], [97.86545, 23.97723], [97.84328, 23.97603], [97.79416, 23.95663], [97.79456, 23.94836], [97.72302, 23.89288], [97.64667, 23.84574], [97.5247, 23.94032], [97.62363, 24.00506], [97.72903, 24.12606], [97.75305, 24.16902], [97.72799, 24.18883], [97.72998, 24.2302], [97.76799, 24.26365], [97.71941, 24.29652], [97.66723, 24.30027], [97.65624, 24.33781], [97.7098, 24.35658], [97.66998, 24.45288], [97.60029, 24.4401], [97.52757, 24.43748], [97.56286, 24.54535], [97.56525, 24.72838], [97.54675, 24.74202], [97.5542, 24.74943], [97.56383, 24.75535], [97.56648, 24.76475], [97.64354, 24.79171], [97.70181, 24.84557], [97.73127, 24.83015], [97.76481, 24.8289], [97.79949, 24.85655], [97.72903, 24.91332], [97.72216, 25.08508], [97.77023, 25.11492], [97.83614, 25.2715], [97.92541, 25.20815], [98.14925, 25.41547], [98.12591, 25.50722], [98.18084, 25.56298], [98.16848, 25.62739], [98.25774, 25.6051], [98.31268, 25.55307], [98.40606, 25.61129], [98.54064, 25.85129], [98.63128, 25.79937], [98.70818, 25.86241], [98.60763, 26.01512], [98.57085, 26.11547], [98.63128, 26.15492], [98.66884, 26.09165], [98.7329, 26.17218], [98.67797, 26.24487], [98.72741, 26.36183], [98.77547, 26.61994], [98.7333, 26.85615], [98.69582, 27.56499], [98.43353, 27.67086], [98.42529, 27.55404], [98.32641, 27.51385], [98.13964, 27.9478], [98.15337, 28.12114], [97.90069, 28.3776], [97.79632, 28.33168], [97.70705, 28.5056], [97.56835, 28.55628], [97.50518, 28.49716], [97.47085, 28.2688], [97.41729, 28.29783], [97.34547, 28.21385], [97.31292, 28.06784], [97.35412, 28.06663], [97.38845, 28.01329], [97.35824, 27.87256], [97.29919, 27.92233], [96.90112, 27.62149], [96.91431, 27.45752], [97.17422, 27.14052], [97.14675, 27.09041], [96.89132, 27.17474], [96.85287, 27.2065], [96.88445, 27.25046], [96.73888, 27.36638], [96.55761, 27.29928], [96.40779, 27.29818], [96.15591, 27.24572], [96.04949, 27.19428], [95.93002, 27.04149], [95.81603, 27.01335], [95.437, 26.7083], [95.30339, 26.65372], [95.23513, 26.68499], [95.05798, 26.45408], [95.12801, 26.38397], [95.11428, 26.1019], [95.18556, 26.07338], [94.80117, 25.49359], [94.68032, 25.47003], [94.57458, 25.20318], [94.74212, 25.13606], [94.73937, 25.00545], [94.60204, 24.70889], [94.5526, 24.70764], [94.50729, 24.59281], [94.45279, 24.56656], [94.32362, 24.27692], [94.30215, 24.23752], [94.14081, 23.83333], [93.92089, 23.95812], [93.80279, 23.92549], [93.75952, 24.0003], [93.62871, 24.00922], [93.50616, 23.94432], [93.46633, 23.97067], [93.41415, 24.07854], [93.34735, 24.10151], [93.32351, 24.04468], [93.36059, 23.93176], [93.3908, 23.92925], [93.3908, 23.7622], [93.43475, 23.68299], [93.38805, 23.4728], [93.39981, 23.38828], [93.38781, 23.36139], [93.36862, 23.35426], [93.38478, 23.13698], [93.2878, 23.00464], [93.12988, 23.05772], [93.134, 22.92498], [93.09417, 22.69459], [93.134, 22.59573], [93.11477, 22.54374], [93.13537, 22.45873], [93.18206, 22.43716], [93.19991, 22.25425], [93.14224, 22.24535], [93.15734, 22.18687], [93.04885, 22.20595], [92.99255, 22.05965], [92.99804, 21.98964], [92.93899, 22.02656], [92.89504, 21.95143], [92.86208, 22.05456], [92.70416, 22.16017], [92.67532, 22.03547], [92.60949, 21.97638], [92.62187, 21.87037]]]]
25936           }
25937         }, {
25938           type: "Feature",
25939           properties: {
25940             iso1A2: "MN",
25941             iso1A3: "MNG",
25942             iso1N3: "496",
25943             wikidata: "Q711",
25944             nameEn: "Mongolia",
25945             groups: ["030", "142", "UN"],
25946             callingCodes: ["976"]
25947           },
25948           geometry: {
25949             type: "MultiPolygon",
25950             coordinates: [[[[102.14032, 51.35566], [101.5044, 51.50467], [101.39085, 51.45753], [100.61116, 51.73028], [99.89203, 51.74903], [99.75578, 51.90108], [99.27888, 51.96876], [98.87768, 52.14563], [98.74142, 51.8637], [98.33222, 51.71832], [98.22053, 51.46579], [98.05257, 51.46696], [97.83305, 51.00248], [98.01472, 50.86652], [97.9693, 50.78044], [98.06393, 50.61262], [98.31373, 50.4996], [98.29481, 50.33561], [97.85197, 49.91339], [97.76871, 49.99861], [97.56432, 49.92801], [97.56811, 49.84265], [97.24639, 49.74737], [96.97388, 49.88413], [95.80056, 50.04239], [95.74757, 49.97915], [95.02465, 49.96941], [94.97166, 50.04725], [94.6121, 50.04239], [94.49477, 50.17832], [94.39258, 50.22193], [94.30823, 50.57498], [92.99595, 50.63183], [93.01109, 50.79001], [92.44714, 50.78762], [92.07173, 50.69585], [91.86048, 50.73734], [89.59711, 49.90851], [89.70687, 49.72535], [88.82499, 49.44808], [88.42449, 49.48821], [88.17223, 49.46934], [88.15543, 49.30314], [87.98977, 49.18147], [87.81333, 49.17354], [87.88171, 48.95853], [87.73822, 48.89582], [88.0788, 48.71436], [87.96361, 48.58478], [88.58939, 48.34531], [88.58316, 48.21893], [88.8011, 48.11302], [88.93186, 48.10263], [89.0711, 47.98528], [89.55453, 48.0423], [89.76624, 47.82745], [90.06512, 47.88177], [90.10871, 47.7375], [90.33598, 47.68303], [90.48854, 47.41826], [90.48542, 47.30438], [90.76108, 46.99399], [90.84035, 46.99525], [91.03649, 46.72916], [91.0147, 46.58171], [91.07696, 46.57315], [90.89639, 46.30711], [90.99672, 46.14207], [91.03026, 46.04194], [90.70907, 45.73437], [90.65114, 45.49314], [90.89169, 45.19667], [91.64048, 45.07408], [93.51161, 44.95964], [94.10003, 44.71016], [94.71959, 44.35284], [95.01191, 44.25274], [95.39772, 44.2805], [95.32891, 44.02407], [95.52594, 43.99353], [95.89543, 43.2528], [96.35658, 42.90363], [96.37926, 42.72055], [97.1777, 42.7964], [99.50671, 42.56535], [100.33297, 42.68231], [100.84979, 42.67087], [101.80515, 42.50074], [102.07645, 42.22519], [102.72403, 42.14675], [103.92804, 41.78246], [104.52258, 41.8706], [104.51667, 41.66113], [105.0123, 41.63188], [106.76517, 42.28741], [107.24774, 42.36107], [107.29755, 42.41395], [107.49681, 42.46221], [107.57258, 42.40898], [108.84489, 42.40246], [109.00679, 42.45302], [109.452, 42.44842], [109.89402, 42.63111], [110.08401, 42.6411], [110.4327, 42.78293], [111.0149, 43.3289], [111.59087, 43.51207], [111.79758, 43.6637], [111.93776, 43.68709], [111.96289, 43.81596], [111.40498, 44.3461], [111.76275, 44.98032], [111.98695, 45.09074], [112.4164, 45.06858], [112.74662, 44.86297], [113.70918, 44.72891], [114.5166, 45.27189], [114.54801, 45.38337], [114.74612, 45.43585], [114.94546, 45.37377], [115.60329, 45.44717], [116.16989, 45.68603], [116.27366, 45.78637], [116.24012, 45.8778], [116.26678, 45.96479], [116.58612, 46.30211], [116.75551, 46.33083], [116.83166, 46.38637], [117.36609, 46.36335], [117.41782, 46.57862], [117.60748, 46.59771], [117.69554, 46.50991], [118.30534, 46.73519], [118.78747, 46.68689], [118.8337, 46.77742], [118.89974, 46.77139], [118.92616, 46.72765], [119.00541, 46.74273], [119.10448, 46.65516], [119.24978, 46.64761], [119.32827, 46.61433], [119.42827, 46.63783], [119.65265, 46.62342], [119.68127, 46.59015], [119.77373, 46.62947], [119.80455, 46.67631], [119.89261, 46.66423], [119.91242, 46.90091], [119.85518, 46.92196], [119.71209, 47.19192], [119.62403, 47.24575], [119.56019, 47.24874], [119.54918, 47.29505], [119.31964, 47.42617], [119.35892, 47.48104], [119.13995, 47.53997], [119.12343, 47.66458], [118.7564, 47.76947], [118.55766, 47.99277], [118.29654, 48.00246], [118.22677, 48.03853], [118.11009, 48.04], [118.03676, 48.00982], [117.80196, 48.01661], [117.50181, 47.77216], [117.37875, 47.63627], [116.9723, 47.87285], [116.67405, 47.89039], [116.4465, 47.83662], [116.21879, 47.88505], [115.94296, 47.67741], [115.57128, 47.91988], [115.52082, 48.15367], [115.811, 48.25699], [115.78876, 48.51781], [116.06565, 48.81716], [116.03781, 48.87014], [116.71193, 49.83813], [116.62502, 49.92919], [116.22402, 50.04477], [115.73602, 49.87688], [115.26068, 49.97367], [114.9703, 50.19254], [114.325, 50.28098], [113.20216, 49.83356], [113.02647, 49.60772], [110.64493, 49.1816], [110.39891, 49.25083], [110.24373, 49.16676], [109.51325, 49.22859], [109.18017, 49.34709], [108.53969, 49.32325], [108.27937, 49.53167], [107.95387, 49.66659], [107.96116, 49.93191], [107.36407, 49.97612], [107.1174, 50.04239], [107.00007, 50.1977], [106.80326, 50.30177], [106.58373, 50.34044], [106.51122, 50.34408], [106.49628, 50.32436], [106.47156, 50.31909], [106.07865, 50.33474], [106.05562, 50.40582], [105.32528, 50.4648], [103.70343, 50.13952], [102.71178, 50.38873], [102.32194, 50.67982], [102.14032, 51.35566]]]]
25951           }
25952         }, {
25953           type: "Feature",
25954           properties: {
25955             iso1A2: "MO",
25956             iso1A3: "MAC",
25957             iso1N3: "446",
25958             wikidata: "Q14773",
25959             nameEn: "Macau",
25960             aliases: ["Macao"],
25961             country: "CN",
25962             groups: ["030", "142", "UN"],
25963             driveSide: "left",
25964             callingCodes: ["853"]
25965           },
25966           geometry: {
25967             type: "MultiPolygon",
25968             coordinates: [[[[113.54942, 22.14519], [113.54839, 22.10909], [113.57191, 22.07696], [113.63011, 22.10782], [113.60504, 22.20464], [113.57123, 22.20416], [113.56865, 22.20973], [113.5508, 22.21672], [113.54333, 22.21688], [113.54093, 22.21314], [113.53593, 22.2137], [113.53301, 22.21235], [113.53552, 22.20607], [113.52659, 22.18271], [113.54093, 22.15497], [113.54942, 22.14519]]]]
25969           }
25970         }, {
25971           type: "Feature",
25972           properties: {
25973             iso1A2: "MP",
25974             iso1A3: "MNP",
25975             iso1N3: "580",
25976             wikidata: "Q16644",
25977             nameEn: "Northern Mariana Islands",
25978             aliases: ["US-MP"],
25979             country: "US",
25980             groups: ["Q1352230", "Q153732", "057", "009", "UN"],
25981             roadSpeedUnit: "mph",
25982             callingCodes: ["1 670"]
25983           },
25984           geometry: {
25985             type: "MultiPolygon",
25986             coordinates: [[[[135.52896, 14.32623], [152.19114, 13.63487], [145.05972, 21.28731], [135.52896, 14.32623]]]]
25987           }
25988         }, {
25989           type: "Feature",
25990           properties: {
25991             iso1A2: "MQ",
25992             iso1A3: "MTQ",
25993             iso1N3: "474",
25994             wikidata: "Q17054",
25995             nameEn: "Martinique",
25996             country: "FR",
25997             groups: ["Q3320166", "EU", "029", "003", "419", "019", "UN"],
25998             callingCodes: ["596"]
25999           },
26000           geometry: {
26001             type: "MultiPolygon",
26002             coordinates: [[[[-59.95997, 14.20285], [-61.07821, 15.25109], [-61.69315, 14.26451], [-59.95997, 14.20285]]]]
26003           }
26004         }, {
26005           type: "Feature",
26006           properties: {
26007             iso1A2: "MR",
26008             iso1A3: "MRT",
26009             iso1N3: "478",
26010             wikidata: "Q1025",
26011             nameEn: "Mauritania",
26012             groups: ["011", "202", "002", "UN"],
26013             callingCodes: ["222"]
26014           },
26015           geometry: {
26016             type: "MultiPolygon",
26017             coordinates: [[[[-5.60725, 16.49919], [-6.57191, 25.0002], [-4.83423, 24.99935], [-8.66674, 27.31569], [-8.66721, 25.99918], [-12.0002, 25.9986], [-12.00251, 23.4538], [-12.14969, 23.41935], [-12.36213, 23.3187], [-12.5741, 23.28975], [-13.00412, 23.02297], [-13.10753, 22.89493], [-13.15313, 22.75649], [-13.08438, 22.53866], [-13.01525, 21.33343], [-16.95474, 21.33997], [-16.99806, 21.12142], [-17.0357, 21.05368], [-17.0396, 20.9961], [-17.06781, 20.92697], [-17.0695, 20.85742], [-17.0471, 20.76408], [-17.15288, 16.07139], [-16.50854, 16.09032], [-16.48967, 16.0496], [-16.44814, 16.09753], [-16.4429, 16.20605], [-16.27016, 16.51565], [-15.6509, 16.50315], [-15.00557, 16.64997], [-14.32144, 16.61495], [-13.80075, 16.13961], [-13.43135, 16.09022], [-13.11029, 15.52116], [-12.23936, 14.76324], [-11.94903, 14.76143], [-11.70705, 15.51558], [-11.43483, 15.62339], [-10.90932, 15.11001], [-10.71721, 15.4223], [-9.40447, 15.4396], [-9.44673, 15.60553], [-9.33314, 15.7044], [-9.31106, 15.69412], [-9.32979, 15.50032], [-5.50165, 15.50061], [-5.33435, 16.33354], [-5.60725, 16.49919]]]]
26018           }
26019         }, {
26020           type: "Feature",
26021           properties: {
26022             iso1A2: "MS",
26023             iso1A3: "MSR",
26024             iso1N3: "500",
26025             wikidata: "Q13353",
26026             nameEn: "Montserrat",
26027             country: "GB",
26028             groups: ["BOTS", "029", "003", "419", "019", "UN"],
26029             driveSide: "left",
26030             roadSpeedUnit: "mph",
26031             roadHeightUnit: "ft",
26032             callingCodes: ["1 664"]
26033           },
26034           geometry: {
26035             type: "MultiPolygon",
26036             coordinates: [[[[-61.91508, 16.51165], [-62.1023, 16.97277], [-62.58307, 16.68909], [-61.91508, 16.51165]]]]
26037           }
26038         }, {
26039           type: "Feature",
26040           properties: {
26041             iso1A2: "MT",
26042             iso1A3: "MLT",
26043             iso1N3: "470",
26044             wikidata: "Q233",
26045             nameEn: "Malta",
26046             groups: ["EU", "039", "150", "UN"],
26047             driveSide: "left",
26048             callingCodes: ["356"]
26049           },
26050           geometry: {
26051             type: "MultiPolygon",
26052             coordinates: [[[[15.70991, 35.79901], [14.07544, 36.41525], [13.27636, 35.20764], [15.70991, 35.79901]]]]
26053           }
26054         }, {
26055           type: "Feature",
26056           properties: {
26057             iso1A2: "MU",
26058             iso1A3: "MUS",
26059             iso1N3: "480",
26060             wikidata: "Q1027",
26061             nameEn: "Mauritius",
26062             groups: ["014", "202", "002", "UN"],
26063             driveSide: "left",
26064             callingCodes: ["230"]
26065           },
26066           geometry: {
26067             type: "MultiPolygon",
26068             coordinates: [[[[56.09755, -9.55401], [57.50644, -31.92637], [68.4673, -19.15185], [56.09755, -9.55401]]]]
26069           }
26070         }, {
26071           type: "Feature",
26072           properties: {
26073             iso1A2: "MV",
26074             iso1A3: "MDV",
26075             iso1N3: "462",
26076             wikidata: "Q826",
26077             nameEn: "Maldives",
26078             groups: ["034", "142", "UN"],
26079             driveSide: "left",
26080             callingCodes: ["960"]
26081           },
26082           geometry: {
26083             type: "MultiPolygon",
26084             coordinates: [[[[71.9161, 8.55531], [72.57428, -3.7623], [76.59015, 5.591], [71.9161, 8.55531]]]]
26085           }
26086         }, {
26087           type: "Feature",
26088           properties: {
26089             iso1A2: "MW",
26090             iso1A3: "MWI",
26091             iso1N3: "454",
26092             wikidata: "Q1020",
26093             nameEn: "Malawi",
26094             groups: ["014", "202", "002", "UN"],
26095             driveSide: "left",
26096             callingCodes: ["265"]
26097           },
26098           geometry: {
26099             type: "MultiPolygon",
26100             coordinates: [[[[33.48052, -9.62442], [33.31581, -9.48554], [33.14925, -9.49322], [32.99397, -9.36712], [32.95389, -9.40138], [33.00476, -9.5133], [33.00256, -9.63053], [33.05485, -9.61316], [33.10163, -9.66525], [33.12144, -9.58929], [33.2095, -9.61099], [33.31517, -9.82364], [33.36581, -9.81063], [33.37902, -9.9104], [33.31297, -10.05133], [33.53863, -10.20148], [33.54797, -10.36077], [33.70675, -10.56896], [33.47636, -10.78465], [33.28022, -10.84428], [33.25998, -10.88862], [33.39697, -11.15296], [33.29267, -11.3789], [33.29267, -11.43536], [33.23663, -11.40637], [33.24252, -11.59302], [33.32692, -11.59248], [33.33937, -11.91252], [33.25998, -12.14242], [33.3705, -12.34931], [33.47636, -12.32498], [33.54485, -12.35996], [33.37517, -12.54085], [33.28177, -12.54692], [33.18837, -12.61377], [33.05917, -12.59554], [32.94397, -12.76868], [32.96733, -12.88251], [33.02181, -12.88707], [32.98289, -13.12671], [33.0078, -13.19492], [32.86113, -13.47292], [32.84176, -13.52794], [32.73683, -13.57682], [32.68436, -13.55769], [32.66468, -13.60019], [32.68654, -13.64268], [32.7828, -13.64805], [32.84528, -13.71576], [32.76962, -13.77224], [32.79015, -13.80755], [32.88985, -13.82956], [32.99042, -13.95689], [33.02977, -14.05022], [33.07568, -13.98447], [33.16749, -13.93992], [33.24249, -14.00019], [33.66677, -14.61306], [33.7247, -14.4989], [33.88503, -14.51652], [33.92898, -14.47929], [34.08588, -14.48893], [34.18733, -14.43823], [34.22355, -14.43607], [34.34453, -14.3985], [34.35843, -14.38652], [34.39277, -14.39467], [34.4192, -14.43191], [34.44641, -14.47746], [34.45053, -14.49873], [34.47628, -14.53363], [34.48932, -14.53646], [34.49636, -14.55091], [34.52366, -14.5667], [34.53962, -14.59776], [34.55112, -14.64494], [34.53516, -14.67782], [34.52057, -14.68263], [34.54503, -14.74672], [34.567, -14.77345], [34.61522, -14.99583], [34.57503, -15.30619], [34.43126, -15.44778], [34.44981, -15.60864], [34.25195, -15.90321], [34.43126, -16.04737], [34.40344, -16.20923], [35.04805, -16.83167], [35.13771, -16.81687], [35.17017, -16.93521], [35.04805, -17.00027], [35.0923, -17.13235], [35.3062, -17.1244], [35.27065, -16.93817], [35.30929, -16.82871], [35.27219, -16.69402], [35.14235, -16.56812], [35.25828, -16.4792], [35.30157, -16.2211], [35.43355, -16.11371], [35.52365, -16.15414], [35.70107, -16.10147], [35.80487, -16.03907], [35.85303, -15.41913], [35.78799, -15.17428], [35.91812, -14.89514], [35.87212, -14.89478], [35.86945, -14.67481], [35.5299, -14.27714], [35.47989, -14.15594], [34.86229, -13.48958], [34.60253, -13.48487], [34.37831, -12.17408], [34.46088, -12.0174], [34.70739, -12.15652], [34.82903, -12.04837], [34.57917, -11.87849], [34.64241, -11.57499], [34.96296, -11.57354], [34.91153, -11.39799], [34.79375, -11.32245], [34.63305, -11.11731], [34.61161, -11.01611], [34.67047, -10.93796], [34.65946, -10.6828], [34.57581, -10.56271], [34.51911, -10.12279], [34.54499, -10.0678], [34.03865, -9.49398], [33.95829, -9.54066], [33.9638, -9.62206], [33.93298, -9.71647], [33.76677, -9.58516], [33.48052, -9.62442]]]]
26101           }
26102         }, {
26103           type: "Feature",
26104           properties: {
26105             iso1A2: "MX",
26106             iso1A3: "MEX",
26107             iso1N3: "484",
26108             wikidata: "Q96",
26109             nameEn: "Mexico",
26110             groups: ["013", "003", "419", "019", "UN"],
26111             callingCodes: ["52"]
26112           },
26113           geometry: {
26114             type: "MultiPolygon",
26115             coordinates: [[[[-117.1243, 32.53427], [-118.48109, 32.5991], [-120.12904, 18.41089], [-92.37213, 14.39277], [-92.2261, 14.53423], [-92.1454, 14.6804], [-92.18161, 14.84147], [-92.1423, 14.88647], [-92.1454, 14.98143], [-92.0621, 15.07406], [-92.20983, 15.26077], [-91.73182, 16.07371], [-90.44567, 16.07573], [-90.40499, 16.40524], [-90.61212, 16.49832], [-90.69064, 16.70697], [-91.04436, 16.92175], [-91.43809, 17.25373], [-90.99199, 17.25192], [-90.98678, 17.81655], [-89.14985, 17.81563], [-89.15105, 17.95104], [-89.03839, 18.0067], [-88.8716, 17.89535], [-88.71505, 18.0707], [-88.48242, 18.49164], [-88.3268, 18.49048], [-88.29909, 18.47591], [-88.26593, 18.47617], [-88.03238, 18.41778], [-88.03165, 18.16657], [-87.90671, 18.15213], [-87.87604, 18.18313], [-87.86657, 18.19971], [-87.85693, 18.18266], [-87.84815, 18.18511], [-86.92368, 17.61462], [-85.9092, 21.8218], [-96.92418, 25.97377], [-97.13927, 25.96583], [-97.35946, 25.92189], [-97.37332, 25.83854], [-97.42511, 25.83969], [-97.45669, 25.86874], [-97.49828, 25.89877], [-97.52025, 25.88518], [-97.66511, 26.01708], [-97.95155, 26.0625], [-97.97017, 26.05232], [-98.24603, 26.07191], [-98.27075, 26.09457], [-98.30491, 26.10475], [-98.35126, 26.15129], [-99.00546, 26.3925], [-99.03053, 26.41249], [-99.08477, 26.39849], [-99.53573, 27.30926], [-99.49744, 27.43746], [-99.482, 27.47128], [-99.48045, 27.49016], [-99.50208, 27.50021], [-99.52955, 27.49747], [-99.51478, 27.55836], [-99.55409, 27.61314], [-100.50029, 28.66117], [-100.51222, 28.70679], [-100.5075, 28.74066], [-100.52313, 28.75598], [-100.59809, 28.88197], [-100.63689, 28.90812], [-100.67294, 29.09744], [-100.79696, 29.24688], [-100.87982, 29.296], [-100.94056, 29.33371], [-100.94579, 29.34523], [-100.96725, 29.3477], [-101.01128, 29.36947], [-101.05686, 29.44738], [-101.47277, 29.7744], [-102.60596, 29.8192], [-103.15787, 28.93865], [-104.37752, 29.54255], [-104.39363, 29.55396], [-104.3969, 29.57105], [-104.5171, 29.64671], [-104.77674, 30.4236], [-106.00363, 31.39181], [-106.09025, 31.40569], [-106.20346, 31.46305], [-106.23711, 31.51262], [-106.24612, 31.54193], [-106.28084, 31.56173], [-106.30305, 31.62154], [-106.33419, 31.66303], [-106.34864, 31.69663], [-106.3718, 31.71165], [-106.38003, 31.73151], [-106.41773, 31.75196], [-106.43419, 31.75478], [-106.45244, 31.76523], [-106.46726, 31.75998], [-106.47298, 31.75054], [-106.48815, 31.74769], [-106.50111, 31.75714], [-106.50962, 31.76155], [-106.51251, 31.76922], [-106.52266, 31.77509], [-106.529, 31.784], [-108.20899, 31.78534], [-108.20979, 31.33316], [-111.07523, 31.33232], [-114.82011, 32.49609], [-114.79524, 32.55731], [-114.81141, 32.55543], [-114.80584, 32.62028], [-114.76736, 32.64094], [-114.71871, 32.71894], [-115.88053, 32.63624], [-117.1243, 32.53427]]]]
26116           }
26117         }, {
26118           type: "Feature",
26119           properties: {
26120             iso1A2: "MY",
26121             iso1A3: "MYS",
26122             iso1N3: "458",
26123             wikidata: "Q833",
26124             nameEn: "Malaysia"
26125           },
26126           geometry: null
26127         }, {
26128           type: "Feature",
26129           properties: {
26130             iso1A2: "MZ",
26131             iso1A3: "MOZ",
26132             iso1N3: "508",
26133             wikidata: "Q1029",
26134             nameEn: "Mozambique",
26135             groups: ["014", "202", "002", "UN"],
26136             driveSide: "left",
26137             callingCodes: ["258"]
26138           },
26139           geometry: {
26140             type: "MultiPolygon",
26141             coordinates: [[[[40.74206, -10.25691], [40.44265, -10.4618], [40.00295, -10.80255], [39.58249, -10.96043], [39.24395, -11.17433], [38.88996, -11.16978], [38.47258, -11.4199], [38.21598, -11.27289], [37.93618, -11.26228], [37.8388, -11.3123], [37.76614, -11.53352], [37.3936, -11.68949], [36.80309, -11.56836], [36.62068, -11.72884], [36.19094, -11.70008], [36.19094, -11.57593], [35.82767, -11.41081], [35.63599, -11.55927], [34.96296, -11.57354], [34.64241, -11.57499], [34.57917, -11.87849], [34.82903, -12.04837], [34.70739, -12.15652], [34.46088, -12.0174], [34.37831, -12.17408], [34.60253, -13.48487], [34.86229, -13.48958], [35.47989, -14.15594], [35.5299, -14.27714], [35.86945, -14.67481], [35.87212, -14.89478], [35.91812, -14.89514], [35.78799, -15.17428], [35.85303, -15.41913], [35.80487, -16.03907], [35.70107, -16.10147], [35.52365, -16.15414], [35.43355, -16.11371], [35.30157, -16.2211], [35.25828, -16.4792], [35.14235, -16.56812], [35.27219, -16.69402], [35.30929, -16.82871], [35.27065, -16.93817], [35.3062, -17.1244], [35.0923, -17.13235], [35.04805, -17.00027], [35.17017, -16.93521], [35.13771, -16.81687], [35.04805, -16.83167], [34.40344, -16.20923], [34.43126, -16.04737], [34.25195, -15.90321], [34.44981, -15.60864], [34.43126, -15.44778], [34.57503, -15.30619], [34.61522, -14.99583], [34.567, -14.77345], [34.54503, -14.74672], [34.52057, -14.68263], [34.53516, -14.67782], [34.55112, -14.64494], [34.53962, -14.59776], [34.52366, -14.5667], [34.49636, -14.55091], [34.48932, -14.53646], [34.47628, -14.53363], [34.45053, -14.49873], [34.44641, -14.47746], [34.4192, -14.43191], [34.39277, -14.39467], [34.35843, -14.38652], [34.34453, -14.3985], [34.22355, -14.43607], [34.18733, -14.43823], [34.08588, -14.48893], [33.92898, -14.47929], [33.88503, -14.51652], [33.7247, -14.4989], [33.66677, -14.61306], [33.24249, -14.00019], [30.22098, -14.99447], [30.41902, -15.62269], [30.42568, -15.9962], [30.91597, -15.99924], [30.97761, -16.05848], [31.13171, -15.98019], [31.30563, -16.01193], [31.42451, -16.15154], [31.67988, -16.19595], [31.90223, -16.34388], [31.91324, -16.41569], [32.02772, -16.43892], [32.28529, -16.43892], [32.42838, -16.4727], [32.71017, -16.59932], [32.69917, -16.66893], [32.78943, -16.70267], [32.97655, -16.70689], [32.91051, -16.89446], [32.84113, -16.92259], [32.96554, -17.11971], [33.00517, -17.30477], [33.0426, -17.3468], [32.96554, -17.48964], [32.98536, -17.55891], [33.0492, -17.60298], [32.94133, -17.99705], [33.03159, -18.35054], [33.02278, -18.4696], [32.88629, -18.51344], [32.88629, -18.58023], [32.95013, -18.69079], [32.9017, -18.7992], [32.82465, -18.77419], [32.70137, -18.84712], [32.73439, -18.92628], [32.69917, -18.94293], [32.72118, -19.02204], [32.84006, -19.0262], [32.87088, -19.09279], [32.85107, -19.29238], [32.77966, -19.36098], [32.78282, -19.47513], [32.84446, -19.48343], [32.84666, -19.68462], [32.95013, -19.67219], [33.06461, -19.77787], [33.01178, -20.02007], [32.93032, -20.03868], [32.85987, -20.16686], [32.85987, -20.27841], [32.66174, -20.56106], [32.55167, -20.56312], [32.48122, -20.63319], [32.51644, -20.91929], [32.37115, -21.133], [32.48236, -21.32873], [32.41234, -21.31246], [31.38336, -22.36919], [31.30611, -22.422], [31.55779, -23.176], [31.56539, -23.47268], [31.67942, -23.60858], [31.70223, -23.72695], [31.77445, -23.90082], [31.87707, -23.95293], [31.90368, -24.18892], [31.9835, -24.29983], [32.03196, -25.10785], [32.01676, -25.38117], [31.97875, -25.46356], [32.00631, -25.65044], [31.92649, -25.84216], [31.974, -25.95387], [32.00916, -25.999], [32.08599, -26.00978], [32.10435, -26.15656], [32.07352, -26.40185], [32.13409, -26.5317], [32.13315, -26.84345], [32.19409, -26.84032], [32.22302, -26.84136], [32.29584, -26.852], [32.35222, -26.86027], [34.51034, -26.91792], [42.99868, -12.65261], [40.74206, -10.25691]]]]
26142           }
26143         }, {
26144           type: "Feature",
26145           properties: {
26146             iso1A2: "NA",
26147             iso1A3: "NAM",
26148             iso1N3: "516",
26149             wikidata: "Q1030",
26150             nameEn: "Namibia",
26151             groups: ["018", "202", "002", "UN"],
26152             driveSide: "left",
26153             callingCodes: ["264"]
26154           },
26155           geometry: {
26156             type: "MultiPolygon",
26157             coordinates: [[[[14.28743, -17.38814], [13.95896, -17.43141], [13.36212, -16.98048], [12.97145, -16.98567], [12.52111, -17.24495], [12.07076, -17.15165], [11.75063, -17.25013], [10.5065, -17.25284], [12.51595, -32.27486], [16.45332, -28.63117], [16.46592, -28.57126], [16.59922, -28.53246], [16.90446, -28.057], [17.15405, -28.08573], [17.4579, -28.68718], [18.99885, -28.89165], [19.99882, -28.42622], [19.99817, -24.76768], [19.99912, -21.99991], [20.99751, -22.00026], [20.99904, -18.31743], [21.45556, -18.31795], [23.0996, -18.00075], [23.29618, -17.99855], [23.61088, -18.4881], [24.19416, -18.01919], [24.40577, -17.95726], [24.57485, -18.07151], [24.6303, -17.9863], [24.71887, -17.9218], [24.73364, -17.89338], [24.95586, -17.79674], [25.05895, -17.84452], [25.16882, -17.78253], [25.26433, -17.79571], [25.00198, -17.58221], [24.70864, -17.49501], [24.5621, -17.52963], [24.38712, -17.46818], [24.32811, -17.49082], [24.23619, -17.47489], [23.47474, -17.62877], [21.42741, -18.02787], [21.14283, -17.94318], [18.84226, -17.80375], [18.39229, -17.38927], [14.28743, -17.38814]]]]
26158           }
26159         }, {
26160           type: "Feature",
26161           properties: {
26162             iso1A2: "NC",
26163             iso1A3: "NCL",
26164             iso1N3: "540",
26165             wikidata: "Q33788",
26166             nameEn: "New Caledonia",
26167             country: "FR",
26168             groups: ["Q1451600", "054", "009", "UN"],
26169             callingCodes: ["687"]
26170           },
26171           geometry: {
26172             type: "MultiPolygon",
26173             coordinates: [[[[159.77159, -28.41151], [174.245, -23.1974], [156.73836, -14.50464], [159.77159, -28.41151]]]]
26174           }
26175         }, {
26176           type: "Feature",
26177           properties: {
26178             iso1A2: "NE",
26179             iso1A3: "NER",
26180             iso1N3: "562",
26181             wikidata: "Q1032",
26182             nameEn: "Niger",
26183             aliases: ["RN"],
26184             groups: ["011", "202", "002", "UN"],
26185             callingCodes: ["227"]
26186           },
26187           geometry: {
26188             type: "MultiPolygon",
26189             coordinates: [[[[14.22918, 22.61719], [13.5631, 23.16574], [11.96886, 23.51735], [7.48273, 20.87258], [7.38361, 20.79165], [5.8153, 19.45101], [4.26651, 19.14224], [4.26762, 17.00432], [4.21787, 17.00118], [4.19893, 16.39923], [3.50368, 15.35934], [3.03134, 15.42221], [3.01806, 15.34571], [1.31275, 15.27978], [0.96711, 14.98275], [0.72632, 14.95898], [0.23859, 15.00135], [0.16936, 14.51654], [0.38051, 14.05575], [0.61924, 13.68491], [0.77377, 13.6866], [0.77637, 13.64442], [0.99514, 13.5668], [1.02813, 13.46635], [1.20088, 13.38951], [1.24429, 13.39373], [1.28509, 13.35488], [1.24516, 13.33968], [1.21217, 13.37853], [1.18873, 13.31771], [0.99253, 13.37515], [0.99167, 13.10727], [2.26349, 12.41915], [2.05785, 12.35539], [2.39723, 11.89473], [2.45824, 11.98672], [2.39657, 12.10952], [2.37783, 12.24804], [2.6593, 12.30631], [2.83978, 12.40585], [3.25352, 12.01467], [3.31613, 11.88495], [3.48187, 11.86092], [3.59375, 11.70269], [3.61075, 11.69181], [3.67988, 11.75429], [3.67122, 11.80865], [3.63063, 11.83042], [3.61955, 11.91847], [3.67775, 11.97599], [3.63136, 12.11826], [3.66364, 12.25884], [3.65111, 12.52223], [3.94339, 12.74979], [4.10006, 12.98862], [4.14367, 13.17189], [4.14186, 13.47586], [4.23456, 13.47725], [4.4668, 13.68286], [4.87425, 13.78], [4.9368, 13.7345], [5.07396, 13.75052], [5.21026, 13.73627], [5.27797, 13.75474], [5.35437, 13.83567], [5.52957, 13.8845], [6.15771, 13.64564], [6.27411, 13.67835], [6.43053, 13.6006], [6.69617, 13.34057], [6.94445, 12.99825], [7.0521, 13.00076], [7.12676, 13.02445], [7.22399, 13.1293], [7.39241, 13.09717], [7.81085, 13.34902], [8.07997, 13.30847], [8.25185, 13.20369], [8.41853, 13.06166], [8.49493, 13.07519], [8.60431, 13.01768], [8.64251, 12.93985], [8.97413, 12.83661], [9.65995, 12.80614], [10.00373, 13.18171], [10.19993, 13.27129], [10.46731, 13.28819], [10.66004, 13.36422], [11.4535, 13.37773], [11.88236, 13.2527], [12.04209, 13.14452], [12.16189, 13.10056], [12.19315, 13.12423], [12.47095, 13.06673], [12.58033, 13.27805], [12.6793, 13.29157], [12.87376, 13.48919], [13.05085, 13.53984], [13.19844, 13.52802], [13.33213, 13.71195], [13.6302, 13.71094], [13.47559, 14.40881], [13.48259, 14.46704], [13.68573, 14.55276], [13.67878, 14.64013], [13.809, 14.72915], [13.78991, 14.87519], [13.86301, 15.04043], [14.37425, 15.72591], [15.50373, 16.89649], [15.6032, 18.77402], [15.75098, 19.93002], [15.99632, 20.35364], [15.6721, 20.70069], [15.59841, 20.74039], [15.56004, 20.79488], [15.55382, 20.86507], [15.57248, 20.92138], [15.62515, 20.95395], [15.28332, 21.44557], [15.20213, 21.49365], [15.19692, 21.99339], [14.99751, 23.00539], [14.22918, 22.61719]]]]
26190           }
26191         }, {
26192           type: "Feature",
26193           properties: {
26194             iso1A2: "NF",
26195             iso1A3: "NFK",
26196             iso1N3: "574",
26197             wikidata: "Q31057",
26198             nameEn: "Norfolk Island",
26199             country: "AU",
26200             groups: ["053", "009", "UN"],
26201             driveSide: "left",
26202             callingCodes: ["672 3"]
26203           },
26204           geometry: {
26205             type: "MultiPolygon",
26206             coordinates: [[[[169.82316, -28.16667], [166.29505, -28.29175], [167.94076, -30.60745], [169.82316, -28.16667]]]]
26207           }
26208         }, {
26209           type: "Feature",
26210           properties: {
26211             iso1A2: "NG",
26212             iso1A3: "NGA",
26213             iso1N3: "566",
26214             wikidata: "Q1033",
26215             nameEn: "Nigeria",
26216             groups: ["011", "202", "002", "UN"],
26217             callingCodes: ["234"]
26218           },
26219           geometry: {
26220             type: "MultiPolygon",
26221             coordinates: [[[[6.15771, 13.64564], [5.52957, 13.8845], [5.35437, 13.83567], [5.27797, 13.75474], [5.21026, 13.73627], [5.07396, 13.75052], [4.9368, 13.7345], [4.87425, 13.78], [4.4668, 13.68286], [4.23456, 13.47725], [4.14186, 13.47586], [4.14367, 13.17189], [4.10006, 12.98862], [3.94339, 12.74979], [3.65111, 12.52223], [3.66364, 12.25884], [3.63136, 12.11826], [3.67775, 11.97599], [3.61955, 11.91847], [3.63063, 11.83042], [3.67122, 11.80865], [3.67988, 11.75429], [3.61075, 11.69181], [3.59375, 11.70269], [3.49175, 11.29765], [3.71505, 11.13015], [3.84243, 10.59316], [3.78292, 10.40538], [3.6844, 10.46351], [3.57275, 10.27185], [3.66908, 10.18136], [3.54429, 9.87739], [3.35383, 9.83641], [3.32099, 9.78032], [3.34726, 9.70696], [3.25093, 9.61632], [3.13928, 9.47167], [3.14147, 9.28375], [3.08017, 9.10006], [2.77907, 9.06924], [2.67523, 7.87825], [2.73095, 7.7755], [2.73405, 7.5423], [2.78668, 7.5116], [2.79442, 7.43486], [2.74489, 7.42565], [2.76965, 7.13543], [2.71702, 6.95722], [2.74024, 6.92802], [2.73405, 6.78508], [2.78823, 6.76356], [2.78204, 6.70514], [2.7325, 6.64057], [2.74334, 6.57291], [2.70464, 6.50831], [2.70566, 6.38038], [2.74181, 6.13349], [5.87055, 3.78489], [8.34397, 4.30689], [8.60302, 4.87353], [8.78027, 5.1243], [8.92029, 5.58403], [8.83687, 5.68483], [8.88156, 5.78857], [8.84209, 5.82562], [9.51757, 6.43874], [9.70674, 6.51717], [9.77824, 6.79088], [9.86314, 6.77756], [10.15135, 7.03781], [10.21466, 6.88996], [10.53639, 6.93432], [10.57214, 7.16345], [10.59746, 7.14719], [10.60789, 7.06885], [10.83727, 6.9358], [10.8179, 6.83377], [10.94302, 6.69325], [11.09644, 6.68437], [11.09495, 6.51717], [11.42041, 6.53789], [11.42264, 6.5882], [11.51499, 6.60892], [11.57755, 6.74059], [11.55818, 6.86186], [11.63117, 6.9905], [11.87396, 7.09398], [11.84864, 7.26098], [11.93205, 7.47812], [12.01844, 7.52981], [11.99908, 7.67302], [12.20909, 7.97553], [12.19271, 8.10826], [12.24782, 8.17904], [12.26123, 8.43696], [12.4489, 8.52536], [12.44146, 8.6152], [12.68722, 8.65938], [12.71701, 8.7595], [12.79, 8.75361], [12.81085, 8.91992], [12.90022, 9.11411], [12.91958, 9.33905], [12.85628, 9.36698], [13.02385, 9.49334], [13.22642, 9.57266], [13.25472, 9.76795], [13.29941, 9.8296], [13.25025, 9.86042], [13.24132, 9.91031], [13.27409, 9.93232], [13.286, 9.9822], [13.25323, 10.00127], [13.25025, 10.03647], [13.34111, 10.12299], [13.43644, 10.13326], [13.5705, 10.53183], [13.54964, 10.61236], [13.73434, 10.9255], [13.70753, 10.94451], [13.7403, 11.00593], [13.78945, 11.00154], [13.97489, 11.30258], [14.17821, 11.23831], [14.6124, 11.51283], [14.64591, 11.66166], [14.55207, 11.72001], [14.61612, 11.7798], [14.6474, 12.17466], [14.4843, 12.35223], [14.22215, 12.36533], [14.17523, 12.41916], [14.20204, 12.53405], [14.08251, 13.0797], [13.6302, 13.71094], [13.33213, 13.71195], [13.19844, 13.52802], [13.05085, 13.53984], [12.87376, 13.48919], [12.6793, 13.29157], [12.58033, 13.27805], [12.47095, 13.06673], [12.19315, 13.12423], [12.16189, 13.10056], [12.04209, 13.14452], [11.88236, 13.2527], [11.4535, 13.37773], [10.66004, 13.36422], [10.46731, 13.28819], [10.19993, 13.27129], [10.00373, 13.18171], [9.65995, 12.80614], [8.97413, 12.83661], [8.64251, 12.93985], [8.60431, 13.01768], [8.49493, 13.07519], [8.41853, 13.06166], [8.25185, 13.20369], [8.07997, 13.30847], [7.81085, 13.34902], [7.39241, 13.09717], [7.22399, 13.1293], [7.12676, 13.02445], [7.0521, 13.00076], [6.94445, 12.99825], [6.69617, 13.34057], [6.43053, 13.6006], [6.27411, 13.67835], [6.15771, 13.64564]]]]
26222           }
26223         }, {
26224           type: "Feature",
26225           properties: {
26226             iso1A2: "NI",
26227             iso1A3: "NIC",
26228             iso1N3: "558",
26229             wikidata: "Q811",
26230             nameEn: "Nicaragua",
26231             groups: ["013", "003", "419", "019", "UN"],
26232             callingCodes: ["505"]
26233           },
26234           geometry: {
26235             type: "MultiPolygon",
26236             coordinates: [[[[-83.13724, 15.00002], [-83.49268, 15.01158], [-83.62101, 14.89448], [-83.89551, 14.76697], [-84.10584, 14.76353], [-84.48373, 14.63249], [-84.70119, 14.68078], [-84.82596, 14.82212], [-84.90082, 14.80489], [-85.1575, 14.53934], [-85.18602, 14.24929], [-85.32149, 14.2562], [-85.45762, 14.11304], [-85.73964, 13.9698], [-85.75477, 13.8499], [-86.03458, 13.99181], [-86.00685, 14.08474], [-86.14801, 14.04317], [-86.35219, 13.77157], [-86.76812, 13.79605], [-86.71267, 13.30348], [-86.87066, 13.30641], [-86.93383, 13.18677], [-86.93197, 13.05313], [-87.03785, 12.98682], [-87.06306, 13.00892], [-87.37107, 12.98646], [-87.55124, 13.12523], [-87.7346, 13.13228], [-88.11443, 12.63306], [-86.14524, 11.09059], [-85.71223, 11.06868], [-85.60529, 11.22607], [-84.92439, 10.9497], [-84.68197, 11.07568], [-83.90838, 10.71161], [-83.66597, 10.79916], [-83.68276, 11.01562], [-82.56142, 11.91792], [-82.06974, 14.49418], [-83.04763, 15.03256], [-83.13724, 15.00002]]]]
26237           }
26238         }, {
26239           type: "Feature",
26240           properties: {
26241             iso1A2: "NL",
26242             iso1A3: "NLD",
26243             iso1N3: "528",
26244             wikidata: "Q29999",
26245             nameEn: "Kingdom of the Netherlands"
26246           },
26247           geometry: null
26248         }, {
26249           type: "Feature",
26250           properties: {
26251             iso1A2: "NO",
26252             iso1A3: "NOR",
26253             iso1N3: "578",
26254             wikidata: "Q20",
26255             nameEn: "Norway"
26256           },
26257           geometry: null
26258         }, {
26259           type: "Feature",
26260           properties: {
26261             iso1A2: "NP",
26262             iso1A3: "NPL",
26263             iso1N3: "524",
26264             wikidata: "Q837",
26265             nameEn: "Nepal",
26266             groups: ["034", "142", "UN"],
26267             driveSide: "left",
26268             callingCodes: ["977"]
26269           },
26270           geometry: {
26271             type: "MultiPolygon",
26272             coordinates: [[[[88.13378, 27.88015], [87.82681, 27.95248], [87.72718, 27.80938], [87.56996, 27.84517], [87.11696, 27.84104], [87.03757, 27.94835], [86.75582, 28.04182], [86.74181, 28.10638], [86.56265, 28.09569], [86.51609, 27.96623], [86.42736, 27.91122], [86.22966, 27.9786], [86.18607, 28.17364], [86.088, 28.09264], [86.08333, 28.02121], [86.12069, 27.93047], [86.06309, 27.90021], [85.94946, 27.9401], [85.97813, 27.99023], [85.90743, 28.05144], [85.84672, 28.18187], [85.74864, 28.23126], [85.71907, 28.38064], [85.69105, 28.38475], [85.60854, 28.25045], [85.59765, 28.30529], [85.4233, 28.32996], [85.38127, 28.28336], [85.10729, 28.34092], [85.18668, 28.54076], [85.19135, 28.62825], [85.06059, 28.68562], [84.85511, 28.58041], [84.62317, 28.73887], [84.47528, 28.74023], [84.2231, 28.89571], [84.24801, 29.02783], [84.18107, 29.23451], [83.97559, 29.33091], [83.82303, 29.30513], [83.63156, 29.16249], [83.44787, 29.30513], [83.28131, 29.56813], [83.07116, 29.61957], [82.73024, 29.81695], [82.5341, 29.9735], [82.38622, 30.02608], [82.16984, 30.0692], [82.19475, 30.16884], [82.10757, 30.23745], [82.10135, 30.35439], [81.99082, 30.33423], [81.62033, 30.44703], [81.5459, 30.37688], [81.41018, 30.42153], [81.39928, 30.21862], [81.33355, 30.15303], [81.2623, 30.14596], [81.29032, 30.08806], [81.24362, 30.0126], [81.12842, 30.01395], [81.03953, 30.20059], [80.92547, 30.17193], [80.91143, 30.22173], [80.86673, 30.17321], [80.8778, 30.13384], [80.67076, 29.95732], [80.60226, 29.95732], [80.57179, 29.91422], [80.56247, 29.86661], [80.48997, 29.79566], [80.43458, 29.80466], [80.41554, 29.79451], [80.36803, 29.73865], [80.38428, 29.68513], [80.41858, 29.63581], [80.37939, 29.57098], [80.24322, 29.44299], [80.31428, 29.30784], [80.28626, 29.20327], [80.24112, 29.21414], [80.26602, 29.13938], [80.23178, 29.11626], [80.18085, 29.13649], [80.05743, 28.91479], [80.06957, 28.82763], [80.12125, 28.82346], [80.37188, 28.63371], [80.44504, 28.63098], [80.52443, 28.54897], [80.50575, 28.6706], [80.55142, 28.69182], [81.03471, 28.40054], [81.19847, 28.36284], [81.32923, 28.13521], [81.38683, 28.17638], [81.48179, 28.12148], [81.47867, 28.08303], [81.91223, 27.84995], [81.97214, 27.93322], [82.06554, 27.92222], [82.46405, 27.6716], [82.70378, 27.72122], [82.74119, 27.49838], [82.93261, 27.50328], [82.94938, 27.46036], [83.19413, 27.45632], [83.27197, 27.38309], [83.2673, 27.36235], [83.29999, 27.32778], [83.35136, 27.33885], [83.38872, 27.39276], [83.39495, 27.4798], [83.61288, 27.47013], [83.85595, 27.35797], [83.86182, 27.4241], [83.93306, 27.44939], [84.02229, 27.43836], [84.10791, 27.52399], [84.21376, 27.45218], [84.25735, 27.44941], [84.29315, 27.39], [84.62161, 27.33885], [84.69166, 27.21294], [84.64496, 27.04669], [84.793, 26.9968], [84.82913, 27.01989], [84.85754, 26.98984], [84.96687, 26.95599], [84.97186, 26.9149], [85.00536, 26.89523], [85.05592, 26.88991], [85.02635, 26.85381], [85.15883, 26.86966], [85.19291, 26.86909], [85.18046, 26.80519], [85.21159, 26.75933], [85.34302, 26.74954], [85.47752, 26.79292], [85.56471, 26.84133], [85.5757, 26.85955], [85.59461, 26.85161], [85.61621, 26.86721], [85.66239, 26.84822], [85.73483, 26.79613], [85.72315, 26.67471], [85.76907, 26.63076], [85.83126, 26.61134], [85.85126, 26.60866], [85.8492, 26.56667], [86.02729, 26.66756], [86.13596, 26.60651], [86.22513, 26.58863], [86.26235, 26.61886], [86.31564, 26.61925], [86.49726, 26.54218], [86.54258, 26.53819], [86.57073, 26.49825], [86.61313, 26.48658], [86.62686, 26.46891], [86.69124, 26.45169], [86.74025, 26.42386], [86.76797, 26.45892], [86.82898, 26.43919], [86.94543, 26.52076], [86.95912, 26.52076], [87.01559, 26.53228], [87.04691, 26.58685], [87.0707, 26.58571], [87.09147, 26.45039], [87.14751, 26.40542], [87.18863, 26.40558], [87.24682, 26.4143], [87.26587, 26.40592], [87.26568, 26.37294], [87.34568, 26.34787], [87.37314, 26.40815], [87.46566, 26.44058], [87.51571, 26.43106], [87.55274, 26.40596], [87.59175, 26.38342], [87.66803, 26.40294], [87.67893, 26.43501], [87.76004, 26.40711], [87.7918, 26.46737], [87.84193, 26.43663], [87.89085, 26.48565], [87.90115, 26.44923], [88.00895, 26.36029], [88.09414, 26.43732], [88.09963, 26.54195], [88.16452, 26.64111], [88.1659, 26.68177], [88.19107, 26.75516], [88.12302, 26.95324], [88.13422, 26.98705], [88.11719, 26.98758], [87.9887, 27.11045], [88.01587, 27.21388], [88.01646, 27.21612], [88.07277, 27.43007], [88.04008, 27.49223], [88.19107, 27.79285], [88.1973, 27.85067], [88.13378, 27.88015]]]]
26273           }
26274         }, {
26275           type: "Feature",
26276           properties: {
26277             iso1A2: "NR",
26278             iso1A3: "NRU",
26279             iso1N3: "520",
26280             wikidata: "Q697",
26281             nameEn: "Nauru",
26282             groups: ["057", "009", "UN"],
26283             driveSide: "left",
26284             callingCodes: ["674"]
26285           },
26286           geometry: {
26287             type: "MultiPolygon",
26288             coordinates: [[[[166.95155, 0.14829], [166.21778, -0.7977], [167.60042, -0.88259], [166.95155, 0.14829]]]]
26289           }
26290         }, {
26291           type: "Feature",
26292           properties: {
26293             iso1A2: "NU",
26294             iso1A3: "NIU",
26295             iso1N3: "570",
26296             wikidata: "Q34020",
26297             nameEn: "Niue",
26298             country: "NZ",
26299             groups: ["061", "009", "UN"],
26300             driveSide: "left",
26301             callingCodes: ["683"]
26302           },
26303           geometry: {
26304             type: "MultiPolygon",
26305             coordinates: [[[[-170.83899, -18.53439], [-170.82274, -20.44429], [-168.63096, -18.60489], [-170.83899, -18.53439]]]]
26306           }
26307         }, {
26308           type: "Feature",
26309           properties: {
26310             iso1A2: "NZ",
26311             iso1A3: "NZL",
26312             iso1N3: "554",
26313             wikidata: "Q664",
26314             nameEn: "New Zealand"
26315           },
26316           geometry: null
26317         }, {
26318           type: "Feature",
26319           properties: {
26320             iso1A2: "OM",
26321             iso1A3: "OMN",
26322             iso1N3: "512",
26323             wikidata: "Q842",
26324             nameEn: "Oman",
26325             groups: ["145", "142", "UN"],
26326             callingCodes: ["968"]
26327           },
26328           geometry: {
26329             type: "MultiPolygon",
26330             coordinates: [[[[56.82555, 25.7713], [56.79239, 26.41236], [56.68954, 26.76645], [56.2644, 26.58649], [55.81777, 26.18798], [56.08666, 26.05038], [56.15498, 26.06828], [56.19334, 25.9795], [56.13963, 25.82765], [56.17416, 25.77239], [56.13579, 25.73524], [56.14826, 25.66351], [56.18363, 25.65508], [56.20473, 25.61119], [56.25365, 25.60211], [56.26636, 25.60643], [56.25341, 25.61443], [56.26534, 25.62825], [56.82555, 25.7713]]], [[[56.26062, 25.33108], [56.23362, 25.31253], [56.25008, 25.28843], [56.24465, 25.27505], [56.20838, 25.25668], [56.20872, 25.24104], [56.24341, 25.22867], [56.27628, 25.23404], [56.34438, 25.26653], [56.35172, 25.30681], [56.3111, 25.30107], [56.3005, 25.31815], [56.26062, 25.33108]], [[56.28423, 25.26344], [56.27086, 25.26128], [56.2716, 25.27916], [56.28102, 25.28486], [56.29379, 25.2754], [56.28423, 25.26344]]], [[[61.45114, 22.55394], [56.86325, 25.03856], [56.3227, 24.97284], [56.34873, 24.93205], [56.30269, 24.88334], [56.20568, 24.85063], [56.20062, 24.78565], [56.13684, 24.73699], [56.06128, 24.74457], [56.03535, 24.81161], [55.97836, 24.87673], [55.97467, 24.89639], [56.05106, 24.87461], [56.05715, 24.95727], [55.96316, 25.00857], [55.90849, 24.96771], [55.85094, 24.96858], [55.81116, 24.9116], [55.81348, 24.80102], [55.83408, 24.77858], [55.83271, 24.68567], [55.76461, 24.5287], [55.83271, 24.41521], [55.83395, 24.32776], [55.80747, 24.31069], [55.79145, 24.27914], [55.76781, 24.26209], [55.75939, 24.26114], [55.75382, 24.2466], [55.75257, 24.23466], [55.76558, 24.23227], [55.77658, 24.23476], [55.83367, 24.20193], [55.95472, 24.2172], [56.01799, 24.07426], [55.8308, 24.01633], [55.73301, 24.05994], [55.48677, 23.94946], [55.57358, 23.669], [55.22634, 23.10378], [55.2137, 22.71065], [55.66469, 21.99658], [54.99756, 20.00083], [52.00311, 19.00083], [52.78009, 17.35124], [52.74267, 17.29519], [52.81185, 17.28568], [57.49095, 8.14549], [61.45114, 22.55394]]]]
26331           }
26332         }, {
26333           type: "Feature",
26334           properties: {
26335             iso1A2: "PA",
26336             iso1A3: "PAN",
26337             iso1N3: "591",
26338             wikidata: "Q804",
26339             nameEn: "Panama",
26340             groups: ["013", "003", "419", "019", "UN"],
26341             callingCodes: ["507"]
26342           },
26343           geometry: {
26344             type: "MultiPolygon",
26345             coordinates: [[[[-77.32389, 8.81247], [-77.58292, 9.22278], [-78.79327, 9.93766], [-82.51044, 9.65379], [-82.56507, 9.57279], [-82.61345, 9.49881], [-82.66667, 9.49746], [-82.77206, 9.59573], [-82.87919, 9.62645], [-82.84871, 9.4973], [-82.93516, 9.46741], [-82.93516, 9.07687], [-82.72126, 8.97125], [-82.88253, 8.83331], [-82.91377, 8.774], [-82.92068, 8.74832], [-82.8794, 8.6981], [-82.82739, 8.60153], [-82.83975, 8.54755], [-82.83322, 8.52464], [-82.8382, 8.48117], [-82.8679, 8.44042], [-82.93056, 8.43465], [-83.05209, 8.33394], [-82.9388, 8.26634], [-82.88641, 8.10219], [-82.89137, 8.05755], [-82.89978, 8.04083], [-82.94503, 7.93865], [-82.13751, 6.97312], [-78.06168, 7.07793], [-77.89178, 7.22681], [-77.81426, 7.48319], [-77.72157, 7.47612], [-77.72514, 7.72348], [-77.57185, 7.51147], [-77.17257, 7.97422], [-77.45064, 8.49991], [-77.32389, 8.81247]]]]
26346           }
26347         }, {
26348           type: "Feature",
26349           properties: {
26350             iso1A2: "PE",
26351             iso1A3: "PER",
26352             iso1N3: "604",
26353             wikidata: "Q419",
26354             nameEn: "Peru",
26355             groups: ["005", "419", "019", "UN"],
26356             callingCodes: ["51"]
26357           },
26358           geometry: {
26359             type: "MultiPolygon",
26360             coordinates: [[[[-74.26675, -0.97229], [-74.42701, -0.50218], [-75.18513, -0.0308], [-75.25764, -0.11943], [-75.40192, -0.17196], [-75.61997, -0.10012], [-75.60169, -0.18708], [-75.53615, -0.19213], [-75.22862, -0.60048], [-75.22862, -0.95588], [-75.3872, -0.9374], [-75.57429, -1.55961], [-76.05203, -2.12179], [-76.6324, -2.58397], [-77.94147, -3.05454], [-78.19369, -3.36431], [-78.14324, -3.47653], [-78.22642, -3.51113], [-78.24589, -3.39907], [-78.34362, -3.38633], [-78.68394, -4.60754], [-78.85149, -4.66795], [-79.01659, -5.01481], [-79.1162, -4.97774], [-79.26248, -4.95167], [-79.59402, -4.46848], [-79.79722, -4.47558], [-80.13945, -4.29786], [-80.39256, -4.48269], [-80.46386, -4.41516], [-80.32114, -4.21323], [-80.45023, -4.20938], [-80.4822, -4.05477], [-80.46386, -4.01342], [-80.13232, -3.90317], [-80.19926, -3.68894], [-80.18741, -3.63994], [-80.19848, -3.59249], [-80.21642, -3.5888], [-80.20535, -3.51667], [-80.22629, -3.501], [-80.23651, -3.48652], [-80.24586, -3.48677], [-80.24123, -3.46124], [-80.20647, -3.431], [-80.30602, -3.39149], [-84.52388, -3.36941], [-85.71054, -21.15413], [-70.59118, -18.35072], [-70.378, -18.3495], [-70.31267, -18.31258], [-70.16394, -18.31737], [-69.96732, -18.25992], [-69.81607, -18.12582], [-69.75305, -17.94605], [-69.82868, -17.72048], [-69.79087, -17.65563], [-69.66483, -17.65083], [-69.46897, -17.4988], [-69.46863, -17.37466], [-69.62883, -17.28142], [-69.16896, -16.72233], [-69.00853, -16.66769], [-69.04027, -16.57214], [-68.98358, -16.42165], [-68.79464, -16.33272], [-68.96238, -16.194], [-69.09986, -16.22693], [-69.20291, -16.16668], [-69.40336, -15.61358], [-69.14856, -15.23478], [-69.36254, -14.94634], [-68.88135, -14.18639], [-69.05265, -13.68546], [-68.8864, -13.40792], [-68.85615, -12.87769], [-68.65044, -12.50689], [-68.98115, -11.8979], [-69.57156, -10.94555], [-69.57835, -10.94051], [-69.90896, -10.92744], [-70.38791, -11.07096], [-70.51395, -10.92249], [-70.64134, -11.0108], [-70.62487, -9.80666], [-70.55429, -9.76692], [-70.58453, -9.58303], [-70.53373, -9.42628], [-71.23394, -9.9668], [-72.14742, -9.98049], [-72.31883, -9.5184], [-72.72216, -9.41397], [-73.21498, -9.40904], [-72.92886, -9.04074], [-73.76576, -7.89884], [-73.65485, -7.77897], [-73.96938, -7.58465], [-73.77011, -7.28944], [-73.73986, -6.87919], [-73.12983, -6.43852], [-73.24579, -6.05764], [-72.83973, -5.14765], [-72.64391, -5.0391], [-71.87003, -4.51661], [-70.96814, -4.36915], [-70.77601, -4.15717], [-70.33236, -4.15214], [-70.19582, -4.3607], [-70.11305, -4.27281], [-70.00888, -4.37833], [-69.94708, -4.2431], [-70.3374, -3.79505], [-70.52393, -3.87553], [-70.71396, -3.7921], [-70.04609, -2.73906], [-70.94377, -2.23142], [-71.75223, -2.15058], [-72.92587, -2.44514], [-73.65312, -1.26222], [-74.26675, -0.97229]]]]
26361           }
26362         }, {
26363           type: "Feature",
26364           properties: {
26365             iso1A2: "PF",
26366             iso1A3: "PYF",
26367             iso1N3: "258",
26368             wikidata: "Q30971",
26369             nameEn: "French Polynesia",
26370             country: "FR",
26371             groups: ["Q1451600", "061", "009", "UN"],
26372             callingCodes: ["689"]
26373           },
26374           geometry: {
26375             type: "MultiPolygon",
26376             coordinates: [[[[-135.59706, -4.70473], [-156.48634, -15.52824], [-156.45576, -31.75456], [-133.59543, -28.4709], [-135.59706, -4.70473]]]]
26377           }
26378         }, {
26379           type: "Feature",
26380           properties: {
26381             iso1A2: "PG",
26382             iso1A3: "PNG",
26383             iso1N3: "598",
26384             wikidata: "Q691",
26385             nameEn: "Papua New Guinea",
26386             groups: ["054", "009", "UN"],
26387             driveSide: "left",
26388             callingCodes: ["675"]
26389           },
26390           geometry: {
26391             type: "MultiPolygon",
26392             coordinates: [[[[141.03157, 2.12829], [140.99813, -6.3233], [140.85295, -6.72996], [140.90448, -6.85033], [141.01763, -6.90181], [141.01842, -9.35091], [141.88934, -9.36111], [142.19246, -9.15378], [142.48658, -9.36754], [143.29772, -9.33993], [143.87386, -9.02382], [145.2855, -9.62524], [156.73836, -14.50464], [154.74815, -7.33315], [155.60735, -6.92266], [155.69784, -6.92661], [155.92557, -6.84664], [156.03993, -6.65703], [156.03296, -6.55528], [160.43769, -4.17974], [141.03157, 2.12829]]]]
26393           }
26394         }, {
26395           type: "Feature",
26396           properties: {
26397             iso1A2: "PH",
26398             iso1A3: "PHL",
26399             iso1N3: "608",
26400             wikidata: "Q928",
26401             nameEn: "Philippines",
26402             aliases: ["PI", "RP"],
26403             groups: ["035", "142", "UN"],
26404             callingCodes: ["63"]
26405           },
26406           geometry: {
26407             type: "MultiPolygon",
26408             coordinates: [[[[129.19694, 7.84182], [121.8109, 21.77688], [120.69238, 21.52331], [118.82252, 14.67191], [115.39742, 10.92666], [116.79524, 7.43869], [117.17735, 7.52841], [117.93857, 6.89845], [117.98544, 6.27477], [119.52945, 5.35672], [118.93936, 4.09009], [118.06469, 4.16638], [121.14448, 2.12444], [129.19694, 7.84182]]]]
26409           }
26410         }, {
26411           type: "Feature",
26412           properties: {
26413             iso1A2: "PK",
26414             iso1A3: "PAK",
26415             iso1N3: "586",
26416             wikidata: "Q843",
26417             nameEn: "Pakistan",
26418             groups: ["034", "142", "UN"],
26419             driveSide: "left",
26420             callingCodes: ["92"]
26421           },
26422           geometry: {
26423             type: "MultiPolygon",
26424             coordinates: [[[[75.72737, 36.7529], [75.45562, 36.71971], [75.40481, 36.95382], [75.13839, 37.02622], [74.56453, 37.03023], [74.53739, 36.96224], [74.43389, 37.00977], [74.04856, 36.82648], [73.82685, 36.91421], [72.6323, 36.84601], [72.18135, 36.71838], [71.80267, 36.49924], [71.60491, 36.39429], [71.19505, 36.04134], [71.37969, 35.95865], [71.55273, 35.71483], [71.49917, 35.6267], [71.65435, 35.4479], [71.54294, 35.31037], [71.5541, 35.28776], [71.67495, 35.21262], [71.52938, 35.09023], [71.55273, 35.02615], [71.49917, 35.00478], [71.50329, 34.97328], [71.29472, 34.87728], [71.28356, 34.80882], [71.08718, 34.69034], [71.11602, 34.63047], [71.0089, 34.54568], [71.02401, 34.44835], [71.17662, 34.36769], [71.12815, 34.26619], [71.13078, 34.16503], [71.09453, 34.13524], [71.09307, 34.11961], [71.06933, 34.10564], [71.07345, 34.06242], [70.88119, 33.97933], [70.54336, 33.9463], [69.90203, 34.04194], [69.87307, 33.9689], [69.85671, 33.93719], [70.00503, 33.73528], [70.14236, 33.71701], [70.14785, 33.6553], [70.20141, 33.64387], [70.17062, 33.53535], [70.32775, 33.34496], [70.13686, 33.21064], [70.07369, 33.22557], [70.02563, 33.14282], [69.85259, 33.09451], [69.79766, 33.13247], [69.71526, 33.09911], [69.57656, 33.09911], [69.49004, 33.01509], [69.49854, 32.88843], [69.5436, 32.8768], [69.47082, 32.85834], [69.38018, 32.76601], [69.43649, 32.7302], [69.44747, 32.6678], [69.38155, 32.56601], [69.2868, 32.53938], [69.23599, 32.45946], [69.27932, 32.29119], [69.27032, 32.14141], [69.3225, 31.93186], [69.20577, 31.85957], [69.11514, 31.70782], [69.00939, 31.62249], [68.95995, 31.64822], [68.91078, 31.59687], [68.79997, 31.61665], [68.6956, 31.75687], [68.57475, 31.83158], [68.44222, 31.76446], [68.27605, 31.75863], [68.25614, 31.80357], [68.1655, 31.82691], [68.00071, 31.6564], [67.86887, 31.63536], [67.72056, 31.52304], [67.58323, 31.52772], [67.62374, 31.40473], [67.7748, 31.4188], [67.78854, 31.33203], [67.29964, 31.19586], [67.03323, 31.24519], [67.04147, 31.31561], [66.83273, 31.26867], [66.72561, 31.20526], [66.68166, 31.07597], [66.58175, 30.97532], [66.42645, 30.95309], [66.39194, 30.9408], [66.28413, 30.57001], [66.34869, 30.404], [66.23609, 30.06321], [66.36042, 29.9583], [66.24175, 29.85181], [65.04005, 29.53957], [64.62116, 29.58903], [64.19796, 29.50407], [64.12966, 29.39157], [63.5876, 29.50456], [62.47751, 29.40782], [60.87231, 29.86514], [61.31508, 29.38903], [61.53765, 29.00507], [61.65978, 28.77937], [61.93581, 28.55284], [62.40259, 28.42703], [62.59499, 28.24842], [62.79412, 28.28108], [62.7638, 28.02992], [62.84905, 27.47627], [62.79684, 27.34381], [62.80604, 27.22412], [63.19649, 27.25674], [63.32283, 27.14437], [63.25005, 27.08692], [63.25005, 26.84212], [63.18688, 26.83844], [63.1889, 26.65072], [62.77352, 26.64099], [62.31484, 26.528], [62.21304, 26.26601], [62.05117, 26.31647], [61.89391, 26.26251], [61.83831, 26.07249], [61.83968, 25.7538], [61.683, 25.66638], [61.6433, 25.27541], [61.46682, 24.57869], [68.11329, 23.53945], [68.20763, 23.85849], [68.39339, 23.96838], [68.74643, 23.97027], [68.7416, 24.31904], [68.90914, 24.33156], [68.97781, 24.26021], [69.07806, 24.29777], [69.19341, 24.25646], [69.29778, 24.28712], [69.59579, 24.29777], [69.73335, 24.17007], [70.03428, 24.172], [70.11712, 24.30915], [70.5667, 24.43787], [70.57906, 24.27774], [70.71502, 24.23517], [70.88393, 24.27398], [70.85784, 24.30903], [70.94985, 24.3791], [71.04461, 24.34657], [71.12838, 24.42662], [71.00341, 24.46038], [70.97594, 24.60904], [71.09405, 24.69017], [70.94002, 24.92843], [70.89148, 25.15064], [70.66695, 25.39314], [70.67382, 25.68186], [70.60378, 25.71898], [70.53649, 25.68928], [70.37444, 25.67443], [70.2687, 25.71156], [70.0985, 25.93238], [70.08193, 26.08094], [70.17532, 26.24118], [70.17532, 26.55362], [70.05584, 26.60398], [69.88555, 26.56836], [69.50904, 26.74892], [69.58519, 27.18109], [70.03136, 27.56627], [70.12502, 27.8057], [70.37307, 28.01208], [70.60927, 28.02178], [70.79054, 27.68423], [71.89921, 27.96035], [71.9244, 28.11555], [72.20329, 28.3869], [72.29495, 28.66367], [72.40402, 28.78283], [72.94272, 29.02487], [73.01337, 29.16422], [73.05886, 29.1878], [73.28094, 29.56646], [73.3962, 29.94707], [73.58665, 30.01848], [73.80299, 30.06969], [73.97225, 30.19829], [73.95736, 30.28466], [73.88993, 30.36305], [74.5616, 31.04153], [74.67971, 31.05479], [74.6852, 31.12771], [74.60006, 31.13711], [74.60281, 31.10419], [74.56023, 31.08303], [74.51629, 31.13829], [74.53223, 31.30321], [74.59773, 31.4136], [74.64713, 31.45605], [74.59319, 31.50197], [74.61517, 31.55698], [74.57498, 31.60382], [74.47771, 31.72227], [74.58907, 31.87824], [74.79919, 31.95983], [74.86236, 32.04485], [74.9269, 32.0658], [75.00793, 32.03786], [75.25649, 32.10187], [75.38046, 32.26836], [75.28259, 32.36556], [75.03265, 32.49538], [74.97634, 32.45367], [74.84725, 32.49075], [74.68362, 32.49298], [74.67431, 32.56676], [74.65251, 32.56416], [74.64424, 32.60985], [74.69542, 32.66792], [74.65345, 32.71225], [74.7113, 32.84219], [74.64675, 32.82604], [74.6289, 32.75561], [74.45312, 32.77755], [74.41467, 32.90563], [74.31227, 32.92795], [74.34875, 32.97823], [74.31854, 33.02891], [74.17571, 33.07495], [74.15374, 33.13477], [74.02144, 33.18908], [74.01366, 33.25199], [74.08782, 33.26232], [74.17983, 33.3679], [74.18121, 33.4745], [74.10115, 33.56392], [74.03576, 33.56718], [73.97367, 33.64061], [73.98968, 33.66155], [73.96423, 33.73071], [74.00891, 33.75437], [74.05898, 33.82089], [74.14001, 33.83002], [74.26086, 33.92237], [74.25262, 34.01577], [74.21554, 34.03853], [73.91341, 34.01235], [73.88732, 34.05105], [73.90677, 34.10504], [73.98208, 34.2522], [73.90517, 34.35317], [73.8475, 34.32935], [73.74862, 34.34183], [73.74999, 34.3781], [73.88732, 34.48911], [73.89419, 34.54568], [73.93951, 34.57169], [73.93401, 34.63386], [73.96423, 34.68244], [74.12897, 34.70073], [74.31239, 34.79626], [74.58083, 34.77386], [74.6663, 34.703], [75.01479, 34.64629], [75.38009, 34.55021], [75.75438, 34.51827], [76.04614, 34.67566], [76.15463, 34.6429], [76.47186, 34.78965], [76.67648, 34.76371], [76.74377, 34.84039], [76.74514, 34.92488], [76.87193, 34.96906], [76.99251, 34.93349], [77.11796, 35.05419], [76.93465, 35.39866], [76.85088, 35.39754], [76.75475, 35.52617], [76.77323, 35.66062], [76.50961, 35.8908], [76.33453, 35.84296], [76.14913, 35.82848], [76.15325, 35.9264], [75.93028, 36.13136], [76.00906, 36.17511], [76.0324, 36.41198], [75.92391, 36.56986], [75.72737, 36.7529]]]]
26425           }
26426         }, {
26427           type: "Feature",
26428           properties: {
26429             iso1A2: "PL",
26430             iso1A3: "POL",
26431             iso1N3: "616",
26432             wikidata: "Q36",
26433             nameEn: "Poland",
26434             groups: ["EU", "151", "150", "UN"],
26435             callingCodes: ["48"]
26436           },
26437           geometry: {
26438             type: "MultiPolygon",
26439             coordinates: [[[[18.57853, 55.25302], [14.20811, 54.12784], [14.22634, 53.9291], [14.20647, 53.91671], [14.18544, 53.91258], [14.20823, 53.90776], [14.21323, 53.8664], [14.27249, 53.74464], [14.26782, 53.69866], [14.2836, 53.67721], [14.27133, 53.66613], [14.28477, 53.65955], [14.2853, 53.63392], [14.31904, 53.61581], [14.30416, 53.55499], [14.3273, 53.50587], [14.35209, 53.49506], [14.4215, 53.27724], [14.44133, 53.27427], [14.45125, 53.26241], [14.40662, 53.21098], [14.37853, 53.20405], [14.36696, 53.16444], [14.38679, 53.13669], [14.35044, 53.05829], [14.25954, 53.00264], [14.14056, 52.95786], [14.15873, 52.87715], [14.12256, 52.84311], [14.13806, 52.82392], [14.22071, 52.81175], [14.61073, 52.59847], [14.6289, 52.57136], [14.60081, 52.53116], [14.63056, 52.48993], [14.54423, 52.42568], [14.55228, 52.35264], [14.56378, 52.33838], [14.58149, 52.28007], [14.70139, 52.25038], [14.71319, 52.22144], [14.68344, 52.19612], [14.70616, 52.16927], [14.67683, 52.13936], [14.6917, 52.10283], [14.72971, 52.09167], [14.76026, 52.06624], [14.71339, 52.00337], [14.70488, 51.97679], [14.7139, 51.95643], [14.71836, 51.95606], [14.72163, 51.95188], [14.7177, 51.94048], [14.70601, 51.92944], [14.6933, 51.9044], [14.6588, 51.88359], [14.59089, 51.83302], [14.60493, 51.80473], [14.64625, 51.79472], [14.66386, 51.73282], [14.69065, 51.70842], [14.75392, 51.67445], [14.75759, 51.62318], [14.7727, 51.61263], [14.71125, 51.56209], [14.73047, 51.54606], [14.72652, 51.53902], [14.73219, 51.52922], [14.94749, 51.47155], [14.9652, 51.44793], [14.96899, 51.38367], [14.98008, 51.33449], [15.04288, 51.28387], [15.01242, 51.21285], [15.0047, 51.16874], [14.99311, 51.16249], [14.99414, 51.15813], [15.00083, 51.14974], [14.99646, 51.14365], [14.99079, 51.14284], [14.99689, 51.12205], [14.98229, 51.11354], [14.97938, 51.07742], [14.95529, 51.04552], [14.92942, 50.99744], [14.89252, 50.94999], [14.89681, 50.9422], [14.81664, 50.88148], [14.82803, 50.86966], [14.99852, 50.86817], [15.01088, 50.97984], [14.96419, 50.99108], [15.02433, 51.0242], [15.03895, 51.0123], [15.06218, 51.02269], [15.10152, 51.01095], [15.11937, 50.99021], [15.16744, 51.01959], [15.1743, 50.9833], [15.2361, 50.99886], [15.27043, 50.97724], [15.2773, 50.8907], [15.36656, 50.83956], [15.3803, 50.77187], [15.43798, 50.80833], [15.73186, 50.73885], [15.81683, 50.75666], [15.87331, 50.67188], [15.97219, 50.69799], [16.0175, 50.63009], [15.98317, 50.61528], [16.02437, 50.60046], [16.10265, 50.66405], [16.20839, 50.63096], [16.23174, 50.67101], [16.33611, 50.66579], [16.44597, 50.58041], [16.34572, 50.49575], [16.31413, 50.50274], [16.19526, 50.43291], [16.21585, 50.40627], [16.22821, 50.41054], [16.28118, 50.36891], [16.30289, 50.38292], [16.36495, 50.37679], [16.3622, 50.34875], [16.39379, 50.3207], [16.42674, 50.32509], [16.56407, 50.21009], [16.55446, 50.16613], [16.63137, 50.1142], [16.7014, 50.09659], [16.8456, 50.20834], [16.98018, 50.24172], [17.00353, 50.21449], [17.02825, 50.23118], [16.99803, 50.25753], [17.02138, 50.27772], [16.99803, 50.30316], [16.94448, 50.31281], [16.90877, 50.38642], [16.85933, 50.41093], [16.89229, 50.45117], [17.1224, 50.39494], [17.14498, 50.38117], [17.19579, 50.38817], [17.19991, 50.3654], [17.27681, 50.32246], [17.34273, 50.32947], [17.34548, 50.2628], [17.3702, 50.28123], [17.58889, 50.27837], [17.67764, 50.28977], [17.69292, 50.32859], [17.74648, 50.29966], [17.72176, 50.25665], [17.76296, 50.23382], [17.70528, 50.18812], [17.59404, 50.16437], [17.66683, 50.10275], [17.6888, 50.12037], [17.7506, 50.07896], [17.77669, 50.02253], [17.86886, 49.97452], [18.00191, 50.01723], [18.04585, 50.01194], [18.04585, 50.03311], [18.00396, 50.04954], [18.03212, 50.06574], [18.07898, 50.04535], [18.10628, 50.00223], [18.20241, 49.99958], [18.21752, 49.97309], [18.27107, 49.96779], [18.27794, 49.93863], [18.31914, 49.91565], [18.33278, 49.92415], [18.33562, 49.94747], [18.41604, 49.93498], [18.53423, 49.89906], [18.54495, 49.9079], [18.54299, 49.92537], [18.57697, 49.91565], [18.57045, 49.87849], [18.60341, 49.86256], [18.57183, 49.83334], [18.61278, 49.7618], [18.61368, 49.75426], [18.62645, 49.75002], [18.62943, 49.74603], [18.62676, 49.71983], [18.69817, 49.70473], [18.72838, 49.68163], [18.80479, 49.6815], [18.84786, 49.5446], [18.84521, 49.51672], [18.94536, 49.52143], [18.97283, 49.49914], [18.9742, 49.39557], [19.18019, 49.41165], [19.25435, 49.53391], [19.36009, 49.53747], [19.37795, 49.574], [19.45348, 49.61583], [19.52626, 49.57311], [19.53313, 49.52856], [19.57845, 49.46077], [19.64162, 49.45184], [19.6375, 49.40897], [19.72127, 49.39288], [19.78581, 49.41701], [19.82237, 49.27806], [19.75286, 49.20751], [19.86409, 49.19316], [19.90529, 49.23532], [19.98494, 49.22904], [20.08238, 49.1813], [20.13738, 49.31685], [20.21977, 49.35265], [20.31453, 49.34817], [20.31728, 49.39914], [20.39939, 49.3896], [20.46422, 49.41612], [20.5631, 49.375], [20.61666, 49.41791], [20.72274, 49.41813], [20.77971, 49.35383], [20.9229, 49.29626], [20.98733, 49.30774], [21.09799, 49.37176], [21.041, 49.41791], [21.12477, 49.43666], [21.19756, 49.4054], [21.27858, 49.45988], [21.43376, 49.41433], [21.62328, 49.4447], [21.77983, 49.35443], [21.82927, 49.39467], [21.96385, 49.3437], [22.04427, 49.22136], [22.56155, 49.08865], [22.89122, 49.00725], [22.86336, 49.10513], [22.72009, 49.20288], [22.748, 49.32759], [22.69444, 49.49378], [22.64534, 49.53094], [22.78304, 49.65543], [22.80261, 49.69098], [22.83179, 49.69875], [22.99329, 49.84249], [23.28221, 50.0957], [23.67635, 50.33385], [23.71382, 50.38248], [23.79445, 50.40481], [23.99563, 50.41289], [24.03668, 50.44507], [24.07048, 50.5071], [24.0996, 50.60752], [24.0595, 50.71625], [23.95925, 50.79271], [23.99254, 50.83847], [24.0952, 50.83262], [24.14524, 50.86128], [24.04576, 50.90196], [23.92217, 51.00836], [23.90376, 51.07697], [23.80678, 51.18405], [23.63858, 51.32182], [23.69905, 51.40871], [23.62751, 51.50512], [23.56236, 51.53673], [23.57053, 51.55938], [23.53198, 51.74298], [23.62691, 51.78208], [23.61523, 51.92066], [23.68733, 51.9906], [23.64066, 52.07626], [23.61, 52.11264], [23.54314, 52.12148], [23.47859, 52.18215], [23.20071, 52.22848], [23.18196, 52.28812], [23.34141, 52.44845], [23.45112, 52.53774], [23.58296, 52.59868], [23.73615, 52.6149], [23.93763, 52.71332], [23.91805, 52.94016], [23.94689, 52.95919], [23.92184, 53.02079], [23.87548, 53.0831], [23.91393, 53.16469], [23.85657, 53.22923], [23.81995, 53.24131], [23.62004, 53.60942], [23.51284, 53.95052], [23.48261, 53.98855], [23.52702, 54.04622], [23.49196, 54.14764], [23.45223, 54.17775], [23.42418, 54.17911], [23.39525, 54.21672], [23.3494, 54.25155], [23.24656, 54.25701], [23.15938, 54.29894], [23.15526, 54.31076], [23.13905, 54.31567], [23.104, 54.29794], [23.04323, 54.31567], [23.05726, 54.34565], [22.99649, 54.35927], [23.00584, 54.38514], [22.83756, 54.40827], [22.79705, 54.36264], [21.41123, 54.32395], [20.63871, 54.3706], [19.8038, 54.44203], [19.64312, 54.45423], [18.57853, 55.25302]]]]
26440           }
26441         }, {
26442           type: "Feature",
26443           properties: {
26444             iso1A2: "PM",
26445             iso1A3: "SPM",
26446             iso1N3: "666",
26447             wikidata: "Q34617",
26448             nameEn: "Saint Pierre and Miquelon",
26449             country: "FR",
26450             groups: ["Q1451600", "021", "003", "019", "UN"],
26451             callingCodes: ["508"]
26452           },
26453           geometry: {
26454             type: "MultiPolygon",
26455             coordinates: [[[[-56.72993, 46.65575], [-55.90758, 46.6223], [-56.27503, 47.39728], [-56.72993, 46.65575]]]]
26456           }
26457         }, {
26458           type: "Feature",
26459           properties: {
26460             iso1A2: "PN",
26461             iso1A3: "PCN",
26462             iso1N3: "612",
26463             wikidata: "Q35672",
26464             nameEn: "Pitcairn Islands",
26465             country: "GB",
26466             groups: ["BOTS", "061", "009", "UN"],
26467             driveSide: "left",
26468             callingCodes: ["64"]
26469           },
26470           geometry: {
26471             type: "MultiPolygon",
26472             coordinates: [[[[-133.59543, -28.4709], [-122.0366, -24.55017], [-133.61511, -21.93325], [-133.59543, -28.4709]]]]
26473           }
26474         }, {
26475           type: "Feature",
26476           properties: {
26477             iso1A2: "PR",
26478             iso1A3: "PRI",
26479             iso1N3: "630",
26480             wikidata: "Q1183",
26481             nameEn: "Puerto Rico",
26482             aliases: ["US-PR"],
26483             country: "US",
26484             groups: ["Q1352230", "029", "003", "419", "019", "UN"],
26485             roadSpeedUnit: "mph",
26486             callingCodes: ["1 787", "1 939"]
26487           },
26488           geometry: {
26489             type: "MultiPolygon",
26490             coordinates: [[[[-65.27974, 17.56928], [-65.02435, 18.73231], [-67.99519, 18.97186], [-68.23894, 17.84663], [-65.27974, 17.56928]]]]
26491           }
26492         }, {
26493           type: "Feature",
26494           properties: {
26495             iso1A2: "PS",
26496             iso1A3: "PSE",
26497             iso1N3: "275",
26498             wikidata: "Q219060",
26499             nameEn: "Palestine"
26500           },
26501           geometry: null
26502         }, {
26503           type: "Feature",
26504           properties: {
26505             iso1A2: "PT",
26506             iso1A3: "PRT",
26507             iso1N3: "620",
26508             wikidata: "Q45",
26509             nameEn: "Portugal"
26510           },
26511           geometry: null
26512         }, {
26513           type: "Feature",
26514           properties: {
26515             iso1A2: "PW",
26516             iso1A3: "PLW",
26517             iso1N3: "585",
26518             wikidata: "Q695",
26519             nameEn: "Palau",
26520             groups: ["057", "009", "UN"],
26521             roadSpeedUnit: "mph",
26522             callingCodes: ["680"]
26523           },
26524           geometry: {
26525             type: "MultiPolygon",
26526             coordinates: [[[[128.97621, 3.08804], [136.39296, 1.54187], [136.04605, 12.45908], [128.97621, 3.08804]]]]
26527           }
26528         }, {
26529           type: "Feature",
26530           properties: {
26531             iso1A2: "PY",
26532             iso1A3: "PRY",
26533             iso1N3: "600",
26534             wikidata: "Q733",
26535             nameEn: "Paraguay",
26536             groups: ["005", "419", "019", "UN"],
26537             callingCodes: ["595"]
26538           },
26539           geometry: {
26540             type: "MultiPolygon",
26541             coordinates: [[[[-58.16225, -20.16193], [-58.23216, -19.80058], [-59.06965, -19.29148], [-60.00638, -19.2981], [-61.73723, -19.63958], [-61.93912, -20.10053], [-62.26883, -20.55311], [-62.2757, -21.06657], [-62.64455, -22.25091], [-62.51761, -22.37684], [-62.22768, -22.55807], [-61.9756, -23.0507], [-61.0782, -23.62932], [-60.99754, -23.80934], [-60.28163, -24.04436], [-60.03367, -24.00701], [-59.45482, -24.34787], [-59.33886, -24.49935], [-58.33055, -24.97099], [-58.25492, -24.92528], [-57.80821, -25.13863], [-57.57431, -25.47269], [-57.87176, -25.93604], [-58.1188, -26.16704], [-58.3198, -26.83443], [-58.65321, -27.14028], [-58.59549, -27.29973], [-58.04205, -27.2387], [-56.85337, -27.5165], [-56.18313, -27.29851], [-55.89195, -27.3467], [-55.74475, -27.44485], [-55.59094, -27.32444], [-55.62322, -27.1941], [-55.39611, -26.97679], [-55.25243, -26.93808], [-55.16948, -26.96068], [-55.06351, -26.80195], [-55.00584, -26.78754], [-54.80868, -26.55669], [-54.70732, -26.45099], [-54.69333, -26.37705], [-54.67359, -25.98607], [-54.60664, -25.9691], [-54.62063, -25.91213], [-54.59398, -25.59224], [-54.59509, -25.53696], [-54.60196, -25.48397], [-54.62033, -25.46026], [-54.4423, -25.13381], [-54.28207, -24.07305], [-54.32807, -24.01865], [-54.6238, -23.83078], [-55.02691, -23.97317], [-55.0518, -23.98666], [-55.12292, -23.99669], [-55.41784, -23.9657], [-55.44117, -23.9185], [-55.43585, -23.87157], [-55.5555, -23.28237], [-55.52288, -23.2595], [-55.5446, -23.22811], [-55.63849, -22.95122], [-55.62493, -22.62765], [-55.68742, -22.58407], [-55.6986, -22.56268], [-55.72366, -22.5519], [-55.741, -22.52018], [-55.74941, -22.46436], [-55.8331, -22.29008], [-56.23206, -22.25347], [-56.45893, -22.08072], [-56.5212, -22.11556], [-56.6508, -22.28387], [-57.98625, -22.09157], [-57.94642, -21.73799], [-57.88239, -21.6868], [-57.93492, -21.65505], [-57.84536, -20.93155], [-58.16225, -20.16193]]]]
26542           }
26543         }, {
26544           type: "Feature",
26545           properties: {
26546             iso1A2: "QA",
26547             iso1A3: "QAT",
26548             iso1N3: "634",
26549             wikidata: "Q846",
26550             nameEn: "Qatar",
26551             groups: ["145", "142", "UN"],
26552             callingCodes: ["974"]
26553           },
26554           geometry: {
26555             type: "MultiPolygon",
26556             coordinates: [[[[50.92992, 24.54396], [51.09638, 24.46907], [51.29972, 24.50747], [51.39468, 24.62785], [51.58834, 24.66608], [51.83108, 24.71675], [51.83682, 26.70231], [50.93865, 26.30758], [50.81266, 25.88946], [50.86149, 25.6965], [50.7801, 25.595], [50.80824, 25.54641], [50.57069, 25.57887], [50.8133, 24.74049], [50.92992, 24.54396]]]]
26557           }
26558         }, {
26559           type: "Feature",
26560           properties: {
26561             iso1A2: "RE",
26562             iso1A3: "REU",
26563             iso1N3: "638",
26564             wikidata: "Q17070",
26565             nameEn: "R\xE9union",
26566             country: "FR",
26567             groups: ["Q3320166", "EU", "014", "202", "002", "UN"],
26568             callingCodes: ["262"]
26569           },
26570           geometry: {
26571             type: "MultiPolygon",
26572             coordinates: [[[[53.37984, -21.23941], [56.73473, -21.9174], [56.62373, -20.2711], [53.37984, -21.23941]]]]
26573           }
26574         }, {
26575           type: "Feature",
26576           properties: {
26577             iso1A2: "RO",
26578             iso1A3: "ROU",
26579             iso1N3: "642",
26580             wikidata: "Q218",
26581             nameEn: "Romania",
26582             groups: ["EU", "151", "150", "UN"],
26583             callingCodes: ["40"]
26584           },
26585           geometry: {
26586             type: "MultiPolygon",
26587             coordinates: [[[[27.15622, 47.98538], [27.02985, 48.09083], [27.04118, 48.12522], [26.96119, 48.13003], [26.98042, 48.15752], [26.94265, 48.1969], [26.87708, 48.19919], [26.81161, 48.25049], [26.62823, 48.25804], [26.55202, 48.22445], [26.33504, 48.18418], [26.17711, 47.99246], [26.05901, 47.9897], [25.77723, 47.93919], [25.63878, 47.94924], [25.23778, 47.89403], [25.11144, 47.75203], [24.88896, 47.7234], [24.81893, 47.82031], [24.70632, 47.84428], [24.61994, 47.95062], [24.43578, 47.97131], [24.34926, 47.9244], [24.22566, 47.90231], [24.11281, 47.91487], [24.06466, 47.95317], [24.02999, 47.95087], [24.00801, 47.968], [23.98553, 47.96076], [23.96337, 47.96672], [23.94192, 47.94868], [23.89352, 47.94512], [23.8602, 47.9329], [23.80904, 47.98142], [23.75188, 47.99705], [23.66262, 47.98786], [23.63894, 48.00293], [23.5653, 48.00499], [23.52803, 48.01818], [23.4979, 47.96858], [23.33577, 48.0237], [23.27397, 48.08245], [23.15999, 48.12188], [23.1133, 48.08061], [23.08858, 48.00716], [23.0158, 47.99338], [22.92241, 48.02002], [22.94301, 47.96672], [22.89849, 47.95851], [22.77991, 47.87211], [22.76617, 47.8417], [22.67247, 47.7871], [22.46559, 47.76583], [22.41979, 47.7391], [22.31816, 47.76126], [22.00917, 47.50492], [22.03389, 47.42508], [22.01055, 47.37767], [21.94463, 47.38046], [21.78395, 47.11104], [21.648, 47.03902], [21.68645, 46.99595], [21.59581, 46.91628], [21.59307, 46.86935], [21.52028, 46.84118], [21.48935, 46.7577], [21.5151, 46.72147], [21.43926, 46.65109], [21.33214, 46.63035], [21.26929, 46.4993], [21.28061, 46.44941], [21.16872, 46.30118], [21.06572, 46.24897], [20.86797, 46.28884], [20.74574, 46.25467], [20.76085, 46.21002], [20.63863, 46.12728], [20.49718, 46.18721], [20.45377, 46.14405], [20.35573, 46.16629], [20.28324, 46.1438], [20.26068, 46.12332], [20.35862, 45.99356], [20.54818, 45.89939], [20.65645, 45.82801], [20.70069, 45.7493], [20.77416, 45.75601], [20.78446, 45.78522], [20.82364, 45.77738], [20.80361, 45.65875], [20.76798, 45.60969], [20.83321, 45.53567], [20.77217, 45.49788], [20.86026, 45.47295], [20.87948, 45.42743], [21.09894, 45.30144], [21.17612, 45.32566], [21.20392, 45.2677], [21.29398, 45.24148], [21.48278, 45.19557], [21.51299, 45.15345], [21.4505, 45.04294], [21.35855, 45.01941], [21.54938, 44.9327], [21.56328, 44.89502], [21.48202, 44.87199], [21.44013, 44.87613], [21.35643, 44.86364], [21.38802, 44.78133], [21.55007, 44.77304], [21.60019, 44.75208], [21.61942, 44.67059], [21.67504, 44.67107], [21.71692, 44.65349], [21.7795, 44.66165], [21.99364, 44.63395], [22.08016, 44.49844], [22.13234, 44.47444], [22.18315, 44.48179], [22.30844, 44.6619], [22.45301, 44.7194], [22.61917, 44.61489], [22.69196, 44.61587], [22.76749, 44.54446], [22.70981, 44.51852], [22.61368, 44.55719], [22.56493, 44.53419], [22.54021, 44.47836], [22.45436, 44.47258], [22.56012, 44.30712], [22.68166, 44.28206], [22.67173, 44.21564], [23.04988, 44.07694], [23.01674, 44.01946], [22.87873, 43.9844], [22.83753, 43.88055], [22.85314, 43.84452], [23.05288, 43.79494], [23.26772, 43.84843], [23.4507, 43.84936], [23.61687, 43.79289], [23.73978, 43.80627], [24.18149, 43.68218], [24.35364, 43.70211], [24.50264, 43.76314], [24.62281, 43.74082], [24.73542, 43.68523], [24.96682, 43.72693], [25.10718, 43.6831], [25.17144, 43.70261], [25.39528, 43.61866], [25.72792, 43.69263], [25.94911, 43.85745], [26.05584, 43.90925], [26.10115, 43.96908], [26.38764, 44.04356], [26.62712, 44.05698], [26.95141, 44.13555], [27.26845, 44.12602], [27.39757, 44.0141], [27.60834, 44.01206], [27.64542, 44.04958], [27.73468, 43.95326], [27.92008, 44.00761], [27.99558, 43.84193], [28.23293, 43.76], [29.24336, 43.70874], [30.04414, 45.08461], [29.69272, 45.19227], [29.65428, 45.25629], [29.68175, 45.26885], [29.59798, 45.38857], [29.42632, 45.44545], [29.24779, 45.43388], [28.96077, 45.33164], [28.94292, 45.28045], [28.81383, 45.3384], [28.78911, 45.24179], [28.71358, 45.22631], [28.5735, 45.24759], [28.34554, 45.32102], [28.28504, 45.43907], [28.21139, 45.46895], [28.18741, 45.47358], [28.08927, 45.6051], [28.16568, 45.6421], [28.13111, 45.92819], [28.08612, 46.01105], [28.13684, 46.18099], [28.10937, 46.22852], [28.19864, 46.31869], [28.18902, 46.35283], [28.25769, 46.43334], [28.22281, 46.50481], [28.24808, 46.64305], [28.12173, 46.82283], [28.09095, 46.97621], [27.81892, 47.1381], [27.73172, 47.29248], [27.68706, 47.28962], [27.60263, 47.32507], [27.55731, 47.46637], [27.47942, 47.48113], [27.3979, 47.59473], [27.32202, 47.64009], [27.25519, 47.71366], [27.29069, 47.73722], [27.1618, 47.92391], [27.15622, 47.98538]]]]
26588           }
26589         }, {
26590           type: "Feature",
26591           properties: {
26592             iso1A2: "RS",
26593             iso1A3: "SRB",
26594             iso1N3: "688",
26595             wikidata: "Q403",
26596             nameEn: "Serbia",
26597             groups: ["039", "150", "UN"],
26598             callingCodes: ["381"]
26599           },
26600           geometry: {
26601             type: "MultiPolygon",
26602             coordinates: [[[[19.66007, 46.19005], [19.56113, 46.16824], [19.52473, 46.1171], [19.28826, 45.99694], [19.14543, 45.9998], [19.10388, 46.04015], [19.0791, 45.96458], [19.01284, 45.96529], [18.99712, 45.93537], [18.81394, 45.91329], [18.85783, 45.85493], [18.90305, 45.71863], [18.96691, 45.66731], [18.88776, 45.57253], [18.94562, 45.53712], [19.07471, 45.53086], [19.08364, 45.48804], [18.99918, 45.49333], [18.97446, 45.37528], [19.10774, 45.29547], [19.28208, 45.23813], [19.41941, 45.23475], [19.43589, 45.17137], [19.19144, 45.17863], [19.14063, 45.12972], [19.07952, 45.14668], [19.1011, 45.01191], [19.05205, 44.97692], [19.15573, 44.95409], [19.06853, 44.89915], [19.02871, 44.92541], [18.98957, 44.90645], [19.01994, 44.85493], [19.18183, 44.92055], [19.36722, 44.88164], [19.32543, 44.74058], [19.26388, 44.65412], [19.16699, 44.52197], [19.13369, 44.52521], [19.12278, 44.50132], [19.14837, 44.45253], [19.14681, 44.41463], [19.11785, 44.40313], [19.10749, 44.39421], [19.10704, 44.38249], [19.10365, 44.37795], [19.10298, 44.36924], [19.11865, 44.36712], [19.1083, 44.3558], [19.11547, 44.34218], [19.13556, 44.338], [19.13332, 44.31492], [19.16741, 44.28648], [19.18328, 44.28383], [19.20508, 44.2917], [19.23306, 44.26097], [19.26945, 44.26957], [19.32464, 44.27185], [19.34773, 44.23244], [19.3588, 44.18353], [19.40927, 44.16722], [19.43905, 44.13088], [19.47338, 44.15034], [19.48386, 44.14332], [19.47321, 44.1193], [19.51167, 44.08158], [19.55999, 44.06894], [19.57467, 44.04716], [19.61991, 44.05254], [19.61836, 44.01464], [19.56498, 43.99922], [19.52515, 43.95573], [19.38439, 43.96611], [19.24363, 44.01502], [19.23465, 43.98764], [19.3986, 43.79668], [19.5176, 43.71403], [19.50455, 43.58385], [19.42696, 43.57987], [19.41941, 43.54056], [19.36653, 43.60921], [19.33426, 43.58833], [19.2553, 43.5938], [19.24774, 43.53061], [19.22807, 43.5264], [19.22229, 43.47926], [19.44315, 43.38846], [19.48171, 43.32644], [19.52962, 43.31623], [19.54598, 43.25158], [19.62661, 43.2286], [19.64063, 43.19027], [19.76918, 43.16044], [19.79255, 43.11951], [19.92576, 43.08539], [19.96549, 43.11098], [19.98887, 43.0538], [20.04729, 43.02732], [20.05431, 42.99571], [20.12325, 42.96237], [20.14896, 42.99058], [20.16415, 42.97177], [20.34528, 42.90676], [20.35692, 42.8335], [20.40594, 42.84853], [20.43734, 42.83157], [20.53484, 42.8885], [20.48692, 42.93208], [20.59929, 43.01067], [20.64557, 43.00826], [20.69515, 43.09641], [20.59929, 43.20492], [20.68688, 43.21335], [20.73811, 43.25068], [20.82145, 43.26769], [20.88685, 43.21697], [20.83727, 43.17842], [20.96287, 43.12416], [21.00749, 43.13984], [21.05378, 43.10707], [21.08952, 43.13471], [21.14465, 43.11089], [21.16734, 42.99694], [21.2041, 43.02277], [21.23877, 43.00848], [21.23534, 42.95523], [21.2719, 42.8994], [21.32974, 42.90424], [21.36941, 42.87397], [21.44047, 42.87276], [21.39045, 42.74888], [21.47498, 42.74695], [21.59154, 42.72643], [21.58755, 42.70418], [21.6626, 42.67813], [21.75025, 42.70125], [21.79413, 42.65923], [21.75672, 42.62695], [21.7327, 42.55041], [21.70522, 42.54176], [21.7035, 42.51899], [21.62556, 42.45106], [21.64209, 42.41081], [21.62887, 42.37664], [21.59029, 42.38042], [21.57021, 42.3647], [21.53467, 42.36809], [21.5264, 42.33634], [21.56772, 42.30946], [21.58992, 42.25915], [21.70111, 42.23789], [21.77176, 42.2648], [21.84654, 42.3247], [21.91595, 42.30392], [21.94405, 42.34669], [22.02908, 42.29848], [22.16384, 42.32103], [22.29605, 42.37477], [22.29275, 42.34913], [22.34773, 42.31725], [22.45919, 42.33822], [22.47498, 42.3915], [22.51961, 42.3991], [22.55669, 42.50144], [22.43983, 42.56851], [22.4997, 42.74144], [22.43309, 42.82057], [22.54302, 42.87774], [22.74826, 42.88701], [22.78397, 42.98253], [22.89521, 43.03625], [22.98104, 43.11199], [23.00806, 43.19279], [22.89727, 43.22417], [22.82036, 43.33665], [22.53397, 43.47225], [22.47582, 43.6558], [22.41043, 43.69566], [22.35558, 43.81281], [22.41449, 44.00514], [22.61688, 44.06534], [22.61711, 44.16938], [22.67173, 44.21564], [22.68166, 44.28206], [22.56012, 44.30712], [22.45436, 44.47258], [22.54021, 44.47836], [22.56493, 44.53419], [22.61368, 44.55719], [22.70981, 44.51852], [22.76749, 44.54446], [22.69196, 44.61587], [22.61917, 44.61489], [22.45301, 44.7194], [22.30844, 44.6619], [22.18315, 44.48179], [22.13234, 44.47444], [22.08016, 44.49844], [21.99364, 44.63395], [21.7795, 44.66165], [21.71692, 44.65349], [21.67504, 44.67107], [21.61942, 44.67059], [21.60019, 44.75208], [21.55007, 44.77304], [21.38802, 44.78133], [21.35643, 44.86364], [21.44013, 44.87613], [21.48202, 44.87199], [21.56328, 44.89502], [21.54938, 44.9327], [21.35855, 45.01941], [21.4505, 45.04294], [21.51299, 45.15345], [21.48278, 45.19557], [21.29398, 45.24148], [21.20392, 45.2677], [21.17612, 45.32566], [21.09894, 45.30144], [20.87948, 45.42743], [20.86026, 45.47295], [20.77217, 45.49788], [20.83321, 45.53567], [20.76798, 45.60969], [20.80361, 45.65875], [20.82364, 45.77738], [20.78446, 45.78522], [20.77416, 45.75601], [20.70069, 45.7493], [20.65645, 45.82801], [20.54818, 45.89939], [20.35862, 45.99356], [20.26068, 46.12332], [20.09713, 46.17315], [20.03533, 46.14509], [20.01816, 46.17696], [19.93508, 46.17553], [19.81491, 46.1313], [19.66007, 46.19005]]]]
26603           }
26604         }, {
26605           type: "Feature",
26606           properties: {
26607             iso1A2: "RU",
26608             iso1A3: "RUS",
26609             iso1N3: "643",
26610             wikidata: "Q159",
26611             nameEn: "Russia"
26612           },
26613           geometry: null
26614         }, {
26615           type: "Feature",
26616           properties: {
26617             iso1A2: "RW",
26618             iso1A3: "RWA",
26619             iso1N3: "646",
26620             wikidata: "Q1037",
26621             nameEn: "Rwanda",
26622             groups: ["014", "202", "002", "UN"],
26623             callingCodes: ["250"]
26624           },
26625           geometry: {
26626             type: "MultiPolygon",
26627             coordinates: [[[[30.47194, -1.0555], [30.35212, -1.06896], [30.16369, -1.34303], [29.912, -1.48269], [29.82657, -1.31187], [29.59061, -1.39016], [29.53062, -1.40499], [29.45038, -1.5054], [29.36322, -1.50887], [29.24323, -1.66826], [29.24458, -1.69663], [29.11847, -1.90576], [29.17562, -2.12278], [29.105, -2.27043], [29.00051, -2.29001], [28.95642, -2.37321], [28.89601, -2.37321], [28.86826, -2.41888], [28.86846, -2.44866], [28.89132, -2.47557], [28.89342, -2.49017], [28.88846, -2.50493], [28.87497, -2.50887], [28.86209, -2.5231], [28.86193, -2.53185], [28.87943, -2.55165], [28.89288, -2.55848], [28.90226, -2.62385], [28.89793, -2.66111], [28.94346, -2.69124], [29.00357, -2.70596], [29.04081, -2.7416], [29.0562, -2.58632], [29.32234, -2.6483], [29.36805, -2.82933], [29.88237, -2.75105], [29.95911, -2.33348], [30.14034, -2.43626], [30.42933, -2.31064], [30.54501, -2.41404], [30.83915, -2.35795], [30.89303, -2.08223], [30.80802, -1.91477], [30.84079, -1.64652], [30.71974, -1.43244], [30.57123, -1.33264], [30.50889, -1.16412], [30.45116, -1.10641], [30.47194, -1.0555]]]]
26628           }
26629         }, {
26630           type: "Feature",
26631           properties: {
26632             iso1A2: "SA",
26633             iso1A3: "SAU",
26634             iso1N3: "682",
26635             wikidata: "Q851",
26636             nameEn: "Saudi Arabia",
26637             groups: ["145", "142", "UN"],
26638             callingCodes: ["966"]
26639           },
26640           geometry: {
26641             type: "MultiPolygon",
26642             coordinates: [[[[40.01521, 32.05667], [39.29903, 32.23259], [38.99233, 31.99721], [36.99791, 31.50081], [37.99354, 30.49998], [37.66395, 30.33245], [37.4971, 29.99949], [36.75083, 29.86903], [36.50005, 29.49696], [36.07081, 29.18469], [34.8812, 29.36878], [34.4454, 27.91479], [37.8565, 22.00903], [39.63762, 18.37348], [40.99158, 15.81743], [42.15205, 16.40211], [42.76801, 16.40371], [42.94625, 16.39721], [42.94351, 16.49467], [42.97215, 16.51093], [43.11601, 16.53166], [43.15274, 16.67248], [43.22066, 16.65179], [43.21325, 16.74416], [43.25857, 16.75304], [43.26303, 16.79479], [43.24801, 16.80613], [43.22956, 16.80613], [43.22012, 16.83932], [43.18338, 16.84852], [43.1398, 16.90696], [43.19328, 16.94703], [43.1813, 16.98438], [43.18233, 17.02673], [43.23967, 17.03428], [43.17787, 17.14717], [43.20156, 17.25901], [43.32653, 17.31179], [43.22533, 17.38343], [43.29185, 17.53224], [43.43005, 17.56148], [43.70631, 17.35762], [44.50126, 17.47475], [46.31018, 17.20464], [46.76494, 17.29151], [47.00571, 16.94765], [47.48245, 17.10808], [47.58351, 17.50366], [48.19996, 18.20584], [49.04884, 18.59899], [52.00311, 19.00083], [54.99756, 20.00083], [55.66469, 21.99658], [55.2137, 22.71065], [55.13599, 22.63334], [52.56622, 22.94341], [51.59617, 24.12041], [51.58871, 24.27256], [51.41644, 24.39615], [51.58834, 24.66608], [51.39468, 24.62785], [51.29972, 24.50747], [51.09638, 24.46907], [50.92992, 24.54396], [50.8133, 24.74049], [50.57069, 25.57887], [50.302, 25.87592], [50.26923, 26.08243], [50.38162, 26.53976], [50.71771, 26.73086], [50.37726, 27.89227], [49.98877, 27.87827], [49.00421, 28.81495], [48.42991, 28.53628], [47.70561, 28.5221], [47.59863, 28.66798], [47.58376, 28.83382], [47.46202, 29.0014], [46.5527, 29.10283], [46.42415, 29.05947], [44.72255, 29.19736], [42.97796, 30.48295], [42.97601, 30.72204], [40.01521, 32.05667]]]]
26643           }
26644         }, {
26645           type: "Feature",
26646           properties: {
26647             iso1A2: "SB",
26648             iso1A3: "SLB",
26649             iso1N3: "090",
26650             wikidata: "Q685",
26651             nameEn: "Solomon Islands",
26652             groups: ["054", "009", "UN"],
26653             driveSide: "left",
26654             callingCodes: ["677"]
26655           },
26656           geometry: {
26657             type: "MultiPolygon",
26658             coordinates: [[[[172.71443, -12.01327], [160.43769, -4.17974], [156.03296, -6.55528], [156.03993, -6.65703], [155.92557, -6.84664], [155.69784, -6.92661], [155.60735, -6.92266], [154.74815, -7.33315], [156.73836, -14.50464], [172.71443, -12.01327]]]]
26659           }
26660         }, {
26661           type: "Feature",
26662           properties: {
26663             iso1A2: "SC",
26664             iso1A3: "SYC",
26665             iso1N3: "690",
26666             wikidata: "Q1042",
26667             nameEn: "Seychelles",
26668             groups: ["014", "202", "002", "UN"],
26669             driveSide: "left",
26670             callingCodes: ["248"]
26671           },
26672           geometry: {
26673             type: "MultiPolygon",
26674             coordinates: [[[[43.75112, -10.38913], [54.83239, -10.93575], [66.3222, 5.65313], [43.75112, -10.38913]]]]
26675           }
26676         }, {
26677           type: "Feature",
26678           properties: {
26679             iso1A2: "SD",
26680             iso1A3: "SDN",
26681             iso1N3: "729",
26682             wikidata: "Q1049",
26683             nameEn: "Sudan",
26684             groups: ["015", "002", "UN"],
26685             callingCodes: ["249"]
26686           },
26687           geometry: {
26688             type: "MultiPolygon",
26689             coordinates: [[[[37.8565, 22.00903], [34.0765, 22.00501], [33.99686, 21.76784], [33.57251, 21.72406], [33.17563, 22.00405], [24.99885, 21.99535], [24.99794, 19.99661], [23.99715, 20.00038], [23.99539, 19.49944], [23.99997, 15.69575], [23.62785, 15.7804], [23.38812, 15.69649], [23.10792, 15.71297], [22.93201, 15.55107], [22.92579, 15.47007], [22.99584, 15.40105], [22.99584, 15.22989], [22.66115, 14.86308], [22.70474, 14.69149], [22.38562, 14.58907], [22.44944, 14.24986], [22.55997, 14.23024], [22.5553, 14.11704], [22.22995, 13.96754], [22.08674, 13.77863], [22.29689, 13.3731], [22.1599, 13.19281], [22.02914, 13.13976], [21.94819, 13.05637], [21.81432, 12.81362], [21.89371, 12.68001], [21.98711, 12.63292], [22.15679, 12.66634], [22.22684, 12.74682], [22.46345, 12.61925], [22.38873, 12.45514], [22.50548, 12.16769], [22.48369, 12.02766], [22.64092, 12.07485], [22.54907, 11.64372], [22.7997, 11.40424], [22.93124, 11.41645], [22.97249, 11.21955], [22.87758, 10.91915], [23.02221, 10.69235], [23.3128, 10.45214], [23.67164, 9.86923], [23.69155, 9.67566], [24.09319, 9.66572], [24.12744, 9.73784], [24.49389, 9.79962], [24.84653, 9.80643], [24.97739, 9.9081], [25.05688, 10.06776], [25.0918, 10.33718], [25.78141, 10.42599], [25.93163, 10.38159], [25.93241, 10.17941], [26.21338, 9.91545], [26.35815, 9.57946], [26.70685, 9.48735], [27.14427, 9.62858], [27.90704, 9.61323], [28.99983, 9.67155], [29.06988, 9.74826], [29.53844, 9.75133], [29.54, 10.07949], [29.94629, 10.29245], [30.00389, 10.28633], [30.53005, 9.95992], [30.82893, 9.71451], [30.84605, 9.7498], [31.28504, 9.75287], [31.77539, 10.28939], [31.99177, 10.65065], [32.46967, 11.04662], [32.39358, 11.18207], [32.39578, 11.70208], [32.10079, 11.95203], [32.73921, 11.95203], [32.73921, 12.22757], [33.25876, 12.22111], [33.13988, 11.43248], [33.26977, 10.83632], [33.24645, 10.77913], [33.52294, 10.64382], [33.66604, 10.44254], [33.80913, 10.32994], [33.90159, 10.17179], [33.96984, 10.15446], [33.99185, 9.99623], [33.96323, 9.80972], [33.9082, 9.762], [33.87958, 9.49937], [34.10229, 9.50238], [34.08717, 9.55243], [34.13186, 9.7492], [34.20484, 9.9033], [34.22718, 10.02506], [34.32102, 10.11599], [34.34783, 10.23914], [34.2823, 10.53508], [34.4372, 10.781], [34.59062, 10.89072], [34.77383, 10.74588], [34.77532, 10.69027], [34.86618, 10.74588], [34.86916, 10.78832], [34.97491, 10.86147], [34.97789, 10.91559], [34.93172, 10.95946], [35.01215, 11.19626], [34.95704, 11.24448], [35.09556, 11.56278], [35.05832, 11.71158], [35.11492, 11.85156], [35.24302, 11.91132], [35.70476, 12.67101], [36.01458, 12.72478], [36.14268, 12.70879], [36.16651, 12.88019], [36.13374, 12.92665], [36.24545, 13.36759], [36.38993, 13.56459], [36.48824, 13.83954], [36.44653, 13.95666], [36.54376, 14.25597], [36.44337, 15.14963], [36.54276, 15.23478], [36.69761, 15.75323], [36.76371, 15.80831], [36.92193, 16.23451], [36.99777, 17.07172], [37.42694, 17.04041], [37.50967, 17.32199], [38.13362, 17.53906], [38.37133, 17.66269], [38.45916, 17.87167], [38.57727, 17.98125], [39.63762, 18.37348], [37.8565, 22.00903]]]]
26690           }
26691         }, {
26692           type: "Feature",
26693           properties: {
26694             iso1A2: "SE",
26695             iso1A3: "SWE",
26696             iso1N3: "752",
26697             wikidata: "Q34",
26698             nameEn: "Sweden",
26699             groups: ["EU", "154", "150", "UN"],
26700             callingCodes: ["46"]
26701           },
26702           geometry: {
26703             type: "MultiPolygon",
26704             coordinates: [[[[24.15791, 65.85385], [23.90497, 66.15802], [23.71339, 66.21299], [23.64982, 66.30603], [23.67591, 66.3862], [23.63776, 66.43568], [23.85959, 66.56434], [23.89488, 66.772], [23.98059, 66.79585], [23.98563, 66.84149], [23.56214, 67.17038], [23.58735, 67.20752], [23.54701, 67.25435], [23.75372, 67.29914], [23.75372, 67.43688], [23.39577, 67.46974], [23.54701, 67.59306], [23.45627, 67.85297], [23.65793, 67.9497], [23.40081, 68.05545], [23.26469, 68.15134], [23.15377, 68.14759], [23.10336, 68.26551], [22.73028, 68.40881], [22.00429, 68.50692], [21.03001, 68.88969], [20.90649, 68.89696], [20.85104, 68.93142], [20.91658, 68.96764], [20.78802, 69.03087], [20.55258, 69.06069], [20.0695, 69.04469], [20.28444, 68.93283], [20.33435, 68.80174], [20.22027, 68.67246], [19.95647, 68.55546], [20.22027, 68.48759], [19.93508, 68.35911], [18.97255, 68.52416], [18.63032, 68.50849], [18.39503, 68.58672], [18.1241, 68.53721], [18.13836, 68.20874], [17.90787, 67.96537], [17.30416, 68.11591], [16.7409, 67.91037], [16.38441, 67.52923], [16.12774, 67.52106], [16.09922, 67.4364], [16.39154, 67.21653], [16.35589, 67.06419], [15.37197, 66.48217], [15.49318, 66.28509], [15.05113, 66.15572], [14.53778, 66.12399], [14.50926, 65.31786], [13.64276, 64.58402], [14.11117, 64.46674], [14.16051, 64.18725], [13.98222, 64.00953], [13.23411, 64.09087], [12.74105, 64.02171], [12.14928, 63.59373], [12.19919, 63.47935], [11.98529, 63.27487], [12.19919, 63.00104], [12.07085, 62.6297], [12.29187, 62.25699], [12.14746, 61.7147], [12.40595, 61.57226], [12.57707, 61.56547], [12.86939, 61.35427], [12.69115, 61.06584], [12.2277, 61.02442], [12.59133, 60.50559], [12.52003, 60.13846], [12.36317, 59.99259], [12.15641, 59.8926], [11.87121, 59.86039], [11.92112, 59.69531], [11.69297, 59.59442], [11.8213, 59.24985], [11.65732, 58.90177], [11.45199, 58.89604], [11.4601, 58.99022], [11.34459, 59.11672], [11.15367, 59.07862], [11.08911, 58.98745], [10.64958, 58.89391], [10.40861, 58.38489], [12.16597, 56.60205], [12.07466, 56.29488], [12.65312, 56.04345], [12.6372, 55.91371], [12.88472, 55.63369], [12.60345, 55.42675], [12.84405, 55.13257], [14.28399, 55.1553], [14.89259, 55.5623], [15.79951, 55.54655], [19.64795, 57.06466], [19.84909, 57.57876], [20.5104, 59.15546], [19.08191, 60.19152], [19.23413, 60.61414], [20.15877, 63.06556], [24.14112, 65.39731], [24.15107, 65.81427], [24.14798, 65.83466], [24.15791, 65.85385]]]]
26705           }
26706         }, {
26707           type: "Feature",
26708           properties: {
26709             iso1A2: "SG",
26710             iso1A3: "SGP",
26711             iso1N3: "702",
26712             wikidata: "Q334",
26713             nameEn: "Singapore",
26714             groups: ["035", "142", "UN"],
26715             driveSide: "left",
26716             callingCodes: ["65"]
26717           },
26718           geometry: {
26719             type: "MultiPolygon",
26720             coordinates: [[[[104.00131, 1.42405], [103.93384, 1.42926], [103.89565, 1.42841], [103.86383, 1.46288], [103.81181, 1.47953], [103.76395, 1.45183], [103.74161, 1.4502], [103.7219, 1.46108], [103.67468, 1.43166], [103.62738, 1.35255], [103.56591, 1.19719], [103.66049, 1.18825], [103.74084, 1.12902], [104.03085, 1.26954], [104.12282, 1.27714], [104.08072, 1.35998], [104.09162, 1.39694], [104.08871, 1.42015], [104.07348, 1.43322], [104.04622, 1.44691], [104.02277, 1.4438], [104.00131, 1.42405]]]]
26721           }
26722         }, {
26723           type: "Feature",
26724           properties: {
26725             iso1A2: "SH",
26726             iso1A3: "SHN",
26727             iso1N3: "654",
26728             wikidata: "Q192184",
26729             nameEn: "Saint Helena, Ascension and Tristan da Cunha",
26730             country: "GB"
26731           },
26732           geometry: null
26733         }, {
26734           type: "Feature",
26735           properties: {
26736             iso1A2: "SI",
26737             iso1A3: "SVN",
26738             iso1N3: "705",
26739             wikidata: "Q215",
26740             nameEn: "Slovenia",
26741             groups: ["EU", "039", "150", "UN"],
26742             callingCodes: ["386"]
26743           },
26744           geometry: {
26745             type: "MultiPolygon",
26746             coordinates: [[[[16.50139, 46.56684], [16.39217, 46.63673], [16.38594, 46.6549], [16.41863, 46.66238], [16.42641, 46.69228], [16.37816, 46.69975], [16.30966, 46.7787], [16.31303, 46.79838], [16.3408, 46.80641], [16.34547, 46.83836], [16.2941, 46.87137], [16.2365, 46.87775], [16.21892, 46.86961], [16.15711, 46.85434], [16.14365, 46.8547], [16.10983, 46.867], [16.05786, 46.83927], [15.99054, 46.82772], [15.99126, 46.78199], [15.98432, 46.74991], [15.99769, 46.7266], [16.02808, 46.71094], [16.04347, 46.68694], [16.04036, 46.6549], [15.99988, 46.67947], [15.98512, 46.68463], [15.94864, 46.68769], [15.87691, 46.7211], [15.8162, 46.71897], [15.78518, 46.70712], [15.76771, 46.69863], [15.73823, 46.70011], [15.72279, 46.69548], [15.69523, 46.69823], [15.67411, 46.70735], [15.6543, 46.70616], [15.6543, 46.69228], [15.6365, 46.6894], [15.63255, 46.68069], [15.62317, 46.67947], [15.59826, 46.68908], [15.54533, 46.66985], [15.55333, 46.64988], [15.54431, 46.6312], [15.46906, 46.61321], [15.45514, 46.63697], [15.41235, 46.65556], [15.23711, 46.63994], [15.14215, 46.66131], [15.01451, 46.641], [14.98024, 46.6009], [14.96002, 46.63459], [14.92283, 46.60848], [14.87129, 46.61], [14.86419, 46.59411], [14.83549, 46.56614], [14.81836, 46.51046], [14.72185, 46.49974], [14.66892, 46.44936], [14.5942, 46.43434], [14.56463, 46.37208], [14.52176, 46.42617], [14.45877, 46.41717], [14.42608, 46.44614], [14.314, 46.43327], [14.28326, 46.44315], [14.15989, 46.43327], [14.12097, 46.47724], [14.04002, 46.49117], [14.00422, 46.48474], [13.89837, 46.52331], [13.7148, 46.5222], [13.68684, 46.43881], [13.59777, 46.44137], [13.5763, 46.42613], [13.5763, 46.40915], [13.47019, 46.3621], [13.43418, 46.35992], [13.44808, 46.33507], [13.37671, 46.29668], [13.42218, 46.20758], [13.47587, 46.22725], [13.56114, 46.2054], [13.56682, 46.18703], [13.64451, 46.18966], [13.66472, 46.17392], [13.64053, 46.13587], [13.57072, 46.09022], [13.50104, 46.05986], [13.49568, 46.04839], [13.50998, 46.04498], [13.49702, 46.01832], [13.47474, 46.00546], [13.50104, 45.98078], [13.52963, 45.96588], [13.56759, 45.96991], [13.58903, 45.99009], [13.62074, 45.98388], [13.63458, 45.98947], [13.64307, 45.98326], [13.6329, 45.94894], [13.63815, 45.93607], [13.61931, 45.91782], [13.60857, 45.89907], [13.59565, 45.89446], [13.58644, 45.88173], [13.57563, 45.8425], [13.58858, 45.83503], [13.59784, 45.8072], [13.66986, 45.79955], [13.8235, 45.7176], [13.83332, 45.70855], [13.83422, 45.68703], [13.87933, 45.65207], [13.9191, 45.6322], [13.8695, 45.60835], [13.86771, 45.59898], [13.84106, 45.58185], [13.78445, 45.5825], [13.74587, 45.59811], [13.7198, 45.59352], [13.6076, 45.64761], [13.45644, 45.59464], [13.56979, 45.4895], [13.62902, 45.45898], [13.67398, 45.4436], [13.7785, 45.46787], [13.81742, 45.43729], [13.88124, 45.42637], [13.90771, 45.45149], [13.97309, 45.45258], [13.99488, 45.47551], [13.96063, 45.50825], [14.00578, 45.52352], [14.07116, 45.48752], [14.20348, 45.46896], [14.22371, 45.50388], [14.24239, 45.50607], [14.26611, 45.48239], [14.27681, 45.4902], [14.32487, 45.47142], [14.36693, 45.48642], [14.49769, 45.54424], [14.5008, 45.60852], [14.53816, 45.6205], [14.57397, 45.67165], [14.60977, 45.66403], [14.59576, 45.62812], [14.69694, 45.57366], [14.68605, 45.53006], [14.71718, 45.53442], [14.80124, 45.49515], [14.81992, 45.45913], [14.90554, 45.47769], [14.92266, 45.52788], [15.02385, 45.48533], [15.05187, 45.49079], [15.16862, 45.42309], [15.27758, 45.46678], [15.33051, 45.45258], [15.38188, 45.48752], [15.30249, 45.53224], [15.29837, 45.5841], [15.27747, 45.60504], [15.31027, 45.6303], [15.34695, 45.63382], [15.34214, 45.64702], [15.38952, 45.63682], [15.4057, 45.64727], [15.34919, 45.71623], [15.30872, 45.69014], [15.25423, 45.72275], [15.40836, 45.79491], [15.47531, 45.79802], [15.47325, 45.8253], [15.52234, 45.82195], [15.57952, 45.84953], [15.64185, 45.82915], [15.66662, 45.84085], [15.70411, 45.8465], [15.68232, 45.86819], [15.68383, 45.88867], [15.67967, 45.90455], [15.70636, 45.92116], [15.70327, 46.00015], [15.71246, 46.01196], [15.72977, 46.04682], [15.62317, 46.09103], [15.6083, 46.11992], [15.59909, 46.14761], [15.64904, 46.19229], [15.6434, 46.21396], [15.67395, 46.22478], [15.75436, 46.21969], [15.75479, 46.20336], [15.78817, 46.21719], [15.79284, 46.25811], [15.97965, 46.30652], [16.07616, 46.3463], [16.07314, 46.36458], [16.05065, 46.3833], [16.05281, 46.39141], [16.14859, 46.40547], [16.18824, 46.38282], [16.30233, 46.37837], [16.30162, 46.40437], [16.27329, 46.41467], [16.27398, 46.42875], [16.25124, 46.48067], [16.23961, 46.49653], [16.26759, 46.50566], [16.26733, 46.51505], [16.29793, 46.5121], [16.37193, 46.55008], [16.38771, 46.53608], [16.44036, 46.5171], [16.5007, 46.49644], [16.52604, 46.47831], [16.59527, 46.47524], [16.52604, 46.5051], [16.52885, 46.53303], [16.50139, 46.56684]]]]
26747           }
26748         }, {
26749           type: "Feature",
26750           properties: {
26751             iso1A2: "SJ",
26752             iso1A3: "SJM",
26753             iso1N3: "744",
26754             wikidata: "Q842829",
26755             nameEn: "Svalbard and Jan Mayen",
26756             country: "NO"
26757           },
26758           geometry: null
26759         }, {
26760           type: "Feature",
26761           properties: {
26762             iso1A2: "SK",
26763             iso1A3: "SVK",
26764             iso1N3: "703",
26765             wikidata: "Q214",
26766             nameEn: "Slovakia",
26767             groups: ["EU", "151", "150", "UN"],
26768             callingCodes: ["421"]
26769           },
26770           geometry: {
26771             type: "MultiPolygon",
26772             coordinates: [[[[19.82237, 49.27806], [19.78581, 49.41701], [19.72127, 49.39288], [19.6375, 49.40897], [19.64162, 49.45184], [19.57845, 49.46077], [19.53313, 49.52856], [19.52626, 49.57311], [19.45348, 49.61583], [19.37795, 49.574], [19.36009, 49.53747], [19.25435, 49.53391], [19.18019, 49.41165], [18.9742, 49.39557], [18.97283, 49.49914], [18.94536, 49.52143], [18.84521, 49.51672], [18.74761, 49.492], [18.67757, 49.50895], [18.6144, 49.49824], [18.57183, 49.51162], [18.53063, 49.49022], [18.54848, 49.47059], [18.44686, 49.39467], [18.4084, 49.40003], [18.4139, 49.36517], [18.36446, 49.3267], [18.18456, 49.28909], [18.15022, 49.24518], [18.1104, 49.08624], [18.06885, 49.03157], [17.91814, 49.01784], [17.87831, 48.92679], [17.77944, 48.92318], [17.73126, 48.87885], [17.7094, 48.86721], [17.5295, 48.81117], [17.45671, 48.85004], [17.3853, 48.80936], [17.29054, 48.85546], [17.19355, 48.87602], [17.11202, 48.82925], [17.00215, 48.70887], [16.93955, 48.60371], [16.94611, 48.53614], [16.85204, 48.44968], [16.8497, 48.38321], [16.83588, 48.3844], [16.83317, 48.38138], [16.84243, 48.35258], [16.90903, 48.32519], [16.89461, 48.31332], [16.97701, 48.17385], [17.02919, 48.13996], [17.05735, 48.14179], [17.09168, 48.09366], [17.07039, 48.0317], [17.16001, 48.00636], [17.23699, 48.02094], [17.71215, 47.7548], [18.02938, 47.75665], [18.29305, 47.73541], [18.56496, 47.76588], [18.66521, 47.76772], [18.74074, 47.8157], [18.8506, 47.82308], [18.76821, 47.87469], [18.76134, 47.97499], [18.82176, 48.04206], [19.01952, 48.07052], [19.23924, 48.0595], [19.28182, 48.08336], [19.47957, 48.09437], [19.52489, 48.19791], [19.63338, 48.25006], [19.92452, 48.1283], [20.24312, 48.2784], [20.29943, 48.26104], [20.5215, 48.53336], [20.83248, 48.5824], [21.11516, 48.49546], [21.44063, 48.58456], [21.6068, 48.50365], [21.67134, 48.3989], [21.72525, 48.34628], [21.8279, 48.33321], [21.83339, 48.36242], [22.14689, 48.4005], [22.16023, 48.56548], [22.21379, 48.6218], [22.34151, 48.68893], [22.42934, 48.92857], [22.48296, 48.99172], [22.54338, 49.01424], [22.56155, 49.08865], [22.04427, 49.22136], [21.96385, 49.3437], [21.82927, 49.39467], [21.77983, 49.35443], [21.62328, 49.4447], [21.43376, 49.41433], [21.27858, 49.45988], [21.19756, 49.4054], [21.12477, 49.43666], [21.041, 49.41791], [21.09799, 49.37176], [20.98733, 49.30774], [20.9229, 49.29626], [20.77971, 49.35383], [20.72274, 49.41813], [20.61666, 49.41791], [20.5631, 49.375], [20.46422, 49.41612], [20.39939, 49.3896], [20.31728, 49.39914], [20.31453, 49.34817], [20.21977, 49.35265], [20.13738, 49.31685], [20.08238, 49.1813], [19.98494, 49.22904], [19.90529, 49.23532], [19.86409, 49.19316], [19.75286, 49.20751], [19.82237, 49.27806]]]]
26773           }
26774         }, {
26775           type: "Feature",
26776           properties: {
26777             iso1A2: "SL",
26778             iso1A3: "SLE",
26779             iso1N3: "694",
26780             wikidata: "Q1044",
26781             nameEn: "Sierra Leone",
26782             groups: ["011", "202", "002", "UN"],
26783             callingCodes: ["232"]
26784           },
26785           geometry: {
26786             type: "MultiPolygon",
26787             coordinates: [[[[-10.27575, 8.48711], [-10.37257, 8.48941], [-10.54891, 8.31174], [-10.63934, 8.35326], [-10.70565, 8.29235], [-10.61422, 8.5314], [-10.47707, 8.67669], [-10.56197, 8.81225], [-10.5783, 9.06386], [-10.74484, 9.07998], [-10.6534, 9.29919], [-11.2118, 10.00098], [-11.89624, 9.99763], [-11.91023, 9.93927], [-12.12634, 9.87203], [-12.24262, 9.92386], [-12.47254, 9.86834], [-12.76788, 9.3133], [-12.94095, 9.26335], [-13.08953, 9.0409], [-13.18586, 9.0925], [-13.29911, 9.04245], [-14.36218, 8.64107], [-12.15048, 6.15992], [-11.50429, 6.92704], [-11.4027, 6.97746], [-11.29417, 7.21576], [-10.60422, 7.7739], [-10.60492, 8.04072], [-10.57523, 8.04829], [-10.51554, 8.1393], [-10.45023, 8.15627], [-10.35227, 8.15223], [-10.29839, 8.21283], [-10.31635, 8.28554], [-10.30084, 8.30008], [-10.27575, 8.48711]]]]
26788           }
26789         }, {
26790           type: "Feature",
26791           properties: {
26792             iso1A2: "SM",
26793             iso1A3: "SMR",
26794             iso1N3: "674",
26795             wikidata: "Q238",
26796             nameEn: "San Marino",
26797             groups: ["039", "150", "UN"],
26798             callingCodes: ["378"]
26799           },
26800           geometry: {
26801             type: "MultiPolygon",
26802             coordinates: [[[[12.45648, 43.89369], [12.48771, 43.89706], [12.49429, 43.90973], [12.49247, 43.91774], [12.49724, 43.92248], [12.50269, 43.92363], [12.50496, 43.93017], [12.51553, 43.94096], [12.51427, 43.94897], [12.50655, 43.95796], [12.50875, 43.96198], [12.50622, 43.97131], [12.51109, 43.97201], [12.51064, 43.98165], [12.5154, 43.98508], [12.51463, 43.99122], [12.50678, 43.99113], [12.49406, 43.98492], [12.47853, 43.98052], [12.46205, 43.97463], [12.44684, 43.96597], [12.43662, 43.95698], [12.42005, 43.9578], [12.41414, 43.95273], [12.40415, 43.95485], [12.40506, 43.94325], [12.41165, 43.93769], [12.41551, 43.92984], [12.40733, 43.92379], [12.41233, 43.90956], [12.40935, 43.9024], [12.41641, 43.89991], [12.44184, 43.90498], [12.45648, 43.89369]]]]
26803           }
26804         }, {
26805           type: "Feature",
26806           properties: {
26807             iso1A2: "SN",
26808             iso1A3: "SEN",
26809             iso1N3: "686",
26810             wikidata: "Q1041",
26811             nameEn: "Senegal",
26812             groups: ["011", "202", "002", "UN"],
26813             callingCodes: ["221"]
26814           },
26815           geometry: {
26816             type: "MultiPolygon",
26817             coordinates: [[[[-14.32144, 16.61495], [-15.00557, 16.64997], [-15.6509, 16.50315], [-16.27016, 16.51565], [-16.4429, 16.20605], [-16.44814, 16.09753], [-16.48967, 16.0496], [-16.50854, 16.09032], [-17.15288, 16.07139], [-18.35085, 14.63444], [-17.43598, 13.59273], [-15.47902, 13.58758], [-15.36504, 13.79313], [-14.93719, 13.80173], [-14.34721, 13.46578], [-13.8955, 13.59126], [-13.79409, 13.34472], [-14.36795, 13.23033], [-15.14917, 13.57989], [-15.26908, 13.37768], [-15.80478, 13.34832], [-15.80355, 13.16729], [-16.69343, 13.16791], [-16.74676, 13.06025], [-17.43966, 13.04579], [-17.4623, 11.92379], [-16.70562, 12.34803], [-16.38191, 12.36449], [-16.20591, 12.46157], [-15.67302, 12.42974], [-15.17582, 12.6847], [-13.70523, 12.68013], [-13.05296, 12.64003], [-13.06603, 12.49342], [-12.87336, 12.51892], [-12.35415, 12.32758], [-11.91331, 12.42008], [-11.46267, 12.44559], [-11.37536, 12.40788], [-11.39935, 12.97808], [-11.63025, 13.39174], [-11.83345, 13.33333], [-12.06897, 13.71049], [-11.93043, 13.84505], [-12.23936, 14.76324], [-13.11029, 15.52116], [-13.43135, 16.09022], [-13.80075, 16.13961], [-14.32144, 16.61495]]]]
26818           }
26819         }, {
26820           type: "Feature",
26821           properties: {
26822             iso1A2: "SO",
26823             iso1A3: "SOM",
26824             iso1N3: "706",
26825             wikidata: "Q1045",
26826             nameEn: "Somalia",
26827             groups: ["014", "202", "002", "UN"],
26828             callingCodes: ["252"]
26829           },
26830           geometry: {
26831             type: "MultiPolygon",
26832             coordinates: [[[[51.12877, 12.56479], [43.90659, 12.3823], [42.95776, 10.98533], [42.69452, 10.62672], [42.87643, 10.18441], [43.0937, 9.90579], [43.23518, 9.84605], [43.32613, 9.59205], [44.19222, 8.93028], [46.99339, 7.9989], [47.92477, 8.00111], [47.97917, 8.00124], [44.98104, 4.91821], [44.02436, 4.9451], [43.40263, 4.79289], [43.04177, 4.57923], [42.97746, 4.44032], [42.84526, 4.28357], [42.55853, 4.20518], [42.07619, 4.17667], [41.89488, 3.97375], [41.31368, 3.14314], [40.98767, 2.82959], [41.00099, -0.83068], [41.56, -1.59812], [41.56362, -1.66375], [41.75542, -1.85308], [57.49095, 8.14549], [51.12877, 12.56479]]]]
26833           }
26834         }, {
26835           type: "Feature",
26836           properties: {
26837             iso1A2: "SR",
26838             iso1A3: "SUR",
26839             iso1N3: "740",
26840             wikidata: "Q730",
26841             nameEn: "Suriname",
26842             groups: ["005", "419", "019", "UN"],
26843             driveSide: "left",
26844             callingCodes: ["597"]
26845           },
26846           geometry: {
26847             type: "MultiPolygon",
26848             coordinates: [[[[-54.26916, 5.26909], [-54.01877, 5.52789], [-54.01074, 5.68785], [-53.7094, 6.2264], [-56.84822, 6.73257], [-57.31629, 5.33714], [-57.22536, 5.15605], [-57.37442, 5.0208], [-57.8699, 4.89394], [-58.0307, 3.95513], [-57.35891, 3.32121], [-56.70519, 2.02964], [-56.55439, 2.02003], [-56.47045, 1.95135], [-55.99278, 1.83137], [-55.89863, 1.89861], [-55.92159, 2.05236], [-56.13054, 2.27723], [-55.96292, 2.53188], [-55.71493, 2.40342], [-55.01919, 2.564], [-54.6084, 2.32856], [-54.42864, 2.42442], [-54.28534, 2.67798], [-53.9849, 3.58697], [-53.98914, 3.627], [-54.05128, 3.63557], [-54.19367, 3.84387], [-54.38444, 4.13222], [-54.4717, 4.91964], [-54.26916, 5.26909]]]]
26849           }
26850         }, {
26851           type: "Feature",
26852           properties: {
26853             iso1A2: "SS",
26854             iso1A3: "SSD",
26855             iso1N3: "728",
26856             wikidata: "Q958",
26857             nameEn: "South Sudan",
26858             groups: ["014", "202", "002", "UN"],
26859             callingCodes: ["211"]
26860           },
26861           geometry: {
26862             type: "MultiPolygon",
26863             coordinates: [[[[34.10229, 9.50238], [33.87958, 9.49937], [33.9082, 9.762], [33.96323, 9.80972], [33.99185, 9.99623], [33.96984, 10.15446], [33.90159, 10.17179], [33.80913, 10.32994], [33.66604, 10.44254], [33.52294, 10.64382], [33.24645, 10.77913], [33.26977, 10.83632], [33.13988, 11.43248], [33.25876, 12.22111], [32.73921, 12.22757], [32.73921, 11.95203], [32.10079, 11.95203], [32.39578, 11.70208], [32.39358, 11.18207], [32.46967, 11.04662], [31.99177, 10.65065], [31.77539, 10.28939], [31.28504, 9.75287], [30.84605, 9.7498], [30.82893, 9.71451], [30.53005, 9.95992], [30.00389, 10.28633], [29.94629, 10.29245], [29.54, 10.07949], [29.53844, 9.75133], [29.06988, 9.74826], [28.99983, 9.67155], [27.90704, 9.61323], [27.14427, 9.62858], [26.70685, 9.48735], [26.35815, 9.57946], [26.21338, 9.91545], [25.93241, 10.17941], [25.93163, 10.38159], [25.78141, 10.42599], [25.0918, 10.33718], [25.05688, 10.06776], [24.97739, 9.9081], [24.84653, 9.80643], [24.49389, 9.79962], [24.12744, 9.73784], [24.09319, 9.66572], [23.69155, 9.67566], [23.62179, 9.53823], [23.64981, 9.44303], [23.64358, 9.28637], [23.56263, 9.19418], [23.4848, 9.16959], [23.44744, 8.99128], [23.59065, 8.99743], [23.51905, 8.71749], [24.25691, 8.69288], [24.13238, 8.36959], [24.35965, 8.26177], [24.85156, 8.16933], [24.98855, 7.96588], [25.25319, 7.8487], [25.29214, 7.66675], [25.20649, 7.61115], [25.20337, 7.50312], [25.35281, 7.42595], [25.37461, 7.33024], [25.90076, 7.09549], [26.38022, 6.63493], [26.32729, 6.36272], [26.58259, 6.1987], [26.51721, 6.09655], [27.22705, 5.71254], [27.22705, 5.62889], [27.28621, 5.56382], [27.23017, 5.37167], [27.26886, 5.25876], [27.44012, 5.07349], [27.56656, 4.89375], [27.65462, 4.89375], [27.76469, 4.79284], [27.79551, 4.59976], [28.20719, 4.35614], [28.6651, 4.42638], [28.8126, 4.48784], [29.03054, 4.48784], [29.22207, 4.34297], [29.43341, 4.50101], [29.49726, 4.7007], [29.82087, 4.56246], [29.79666, 4.37809], [30.06964, 4.13221], [30.1621, 4.10586], [30.22374, 3.93896], [30.27658, 3.95653], [30.47691, 3.83353], [30.55396, 3.84451], [30.57378, 3.74567], [30.56277, 3.62703], [30.78512, 3.67097], [30.80713, 3.60506], [30.85997, 3.5743], [30.85153, 3.48867], [30.97601, 3.693], [31.16666, 3.79853], [31.29476, 3.8015], [31.50478, 3.67814], [31.50776, 3.63652], [31.72075, 3.74354], [31.81459, 3.82083], [31.86821, 3.78664], [31.96205, 3.6499], [31.95907, 3.57408], [32.05187, 3.589], [32.08491, 3.56287], [32.08866, 3.53543], [32.19888, 3.50867], [32.20782, 3.6053], [32.41337, 3.748], [32.72021, 3.77327], [32.89746, 3.81339], [33.02852, 3.89296], [33.18356, 3.77812], [33.51264, 3.75068], [33.9873, 4.23316], [34.47601, 4.72162], [35.34151, 5.02364], [35.30992, 4.90402], [35.47843, 4.91872], [35.42366, 4.76969], [35.51424, 4.61643], [35.9419, 4.61933], [35.82118, 4.77382], [35.81968, 5.10757], [35.8576, 5.33413], [35.50792, 5.42431], [35.29938, 5.34042], [35.31188, 5.50106], [35.13058, 5.62118], [35.12611, 5.68937], [35.00546, 5.89387], [34.96227, 6.26415], [35.01738, 6.46991], [34.87736, 6.60161], [34.77459, 6.5957], [34.65096, 6.72589], [34.53776, 6.74808], [34.53925, 6.82794], [34.47669, 6.91076], [34.35753, 6.91963], [34.19369, 7.04382], [34.19369, 7.12807], [34.01495, 7.25664], [34.03878, 7.27437], [34.02984, 7.36449], [33.87642, 7.5491], [33.71407, 7.65983], [33.44745, 7.7543], [33.32531, 7.71297], [33.24637, 7.77939], [33.04944, 7.78989], [33.0006, 7.90333], [33.08401, 8.05822], [33.18083, 8.13047], [33.1853, 8.29264], [33.19721, 8.40317], [33.3119, 8.45474], [33.54575, 8.47094], [33.66938, 8.44442], [33.71407, 8.3678], [33.87195, 8.41938], [33.89579, 8.4842], [34.01346, 8.50041], [34.14453, 8.60204], [34.14304, 9.04654], [34.10229, 9.50238]]]]
26864           }
26865         }, {
26866           type: "Feature",
26867           properties: {
26868             iso1A2: "ST",
26869             iso1A3: "STP",
26870             iso1N3: "678",
26871             wikidata: "Q1039",
26872             nameEn: "S\xE3o Tom\xE9 and Principe",
26873             groups: ["017", "202", "002", "UN"],
26874             callingCodes: ["239"]
26875           },
26876           geometry: {
26877             type: "MultiPolygon",
26878             coordinates: [[[[4.34149, 1.91417], [6.6507, -0.28606], [7.9035, 1.92304], [4.34149, 1.91417]]]]
26879           }
26880         }, {
26881           type: "Feature",
26882           properties: {
26883             iso1A2: "SV",
26884             iso1A3: "SLV",
26885             iso1N3: "222",
26886             wikidata: "Q792",
26887             nameEn: "El Salvador",
26888             groups: ["013", "003", "419", "019", "UN"],
26889             callingCodes: ["503"]
26890           },
26891           geometry: {
26892             type: "MultiPolygon",
26893             coordinates: [[[[-89.34776, 14.43013], [-89.39028, 14.44561], [-89.57441, 14.41637], [-89.58814, 14.33165], [-89.50614, 14.26084], [-89.52397, 14.22628], [-89.61844, 14.21937], [-89.70756, 14.1537], [-89.75569, 14.07073], [-89.73251, 14.04133], [-89.76103, 14.02923], [-89.81807, 14.07073], [-89.88937, 14.0396], [-90.10505, 13.85104], [-90.11344, 13.73679], [-90.55276, 12.8866], [-88.11443, 12.63306], [-87.7346, 13.13228], [-87.55124, 13.12523], [-87.69751, 13.25228], [-87.73714, 13.32715], [-87.80177, 13.35689], [-87.84675, 13.41078], [-87.83467, 13.44655], [-87.77354, 13.45767], [-87.73841, 13.44169], [-87.72115, 13.46083], [-87.71657, 13.50577], [-87.78148, 13.52906], [-87.73106, 13.75443], [-87.68821, 13.80829], [-87.7966, 13.91353], [-88.00331, 13.86948], [-88.07641, 13.98447], [-88.23018, 13.99915], [-88.25791, 13.91108], [-88.48982, 13.86458], [-88.49738, 13.97224], [-88.70661, 14.04317], [-88.73182, 14.10919], [-88.815, 14.11652], [-88.85785, 14.17763], [-88.94608, 14.20207], [-89.04187, 14.33644], [-89.34776, 14.43013]]]]
26894           }
26895         }, {
26896           type: "Feature",
26897           properties: {
26898             iso1A2: "SX",
26899             iso1A3: "SXM",
26900             iso1N3: "534",
26901             wikidata: "Q26273",
26902             nameEn: "Sint Maarten",
26903             aliases: ["NL-SX"],
26904             country: "NL",
26905             groups: ["Q1451600", "029", "003", "419", "019", "UN"],
26906             callingCodes: ["1 721"]
26907           },
26908           geometry: {
26909             type: "MultiPolygon",
26910             coordinates: [[[[-63.33064, 17.9615], [-63.1055, 17.86651], [-62.93924, 18.02904], [-63.02323, 18.05757], [-63.04039, 18.05619], [-63.0579, 18.06614], [-63.07759, 18.04943], [-63.09686, 18.04608], [-63.11042, 18.05339], [-63.13502, 18.05445], [-63.33064, 17.9615]]]]
26911           }
26912         }, {
26913           type: "Feature",
26914           properties: {
26915             iso1A2: "SY",
26916             iso1A3: "SYR",
26917             iso1N3: "760",
26918             wikidata: "Q858",
26919             nameEn: "Syria",
26920             groups: ["145", "142", "UN"],
26921             callingCodes: ["963"]
26922           },
26923           geometry: {
26924             type: "MultiPolygon",
26925             coordinates: [[[[42.23683, 37.2863], [42.21548, 37.28026], [42.20454, 37.28715], [42.22381, 37.30238], [42.22257, 37.31395], [42.2112, 37.32491], [42.19301, 37.31323], [42.18225, 37.28569], [42.00894, 37.17209], [41.515, 37.08084], [41.21937, 37.07665], [40.90856, 37.13147], [40.69136, 37.0996], [39.81589, 36.75538], [39.21538, 36.66834], [39.03217, 36.70911], [38.74042, 36.70629], [38.55908, 36.84429], [38.38859, 36.90064], [38.21064, 36.91842], [37.81974, 36.76055], [37.68048, 36.75065], [37.49103, 36.66904], [37.47253, 36.63243], [37.21988, 36.6736], [37.16177, 36.66069], [37.10894, 36.6704], [37.08279, 36.63495], [37.02088, 36.66422], [37.01647, 36.69512], [37.04619, 36.71101], [37.04399, 36.73483], [36.99886, 36.74012], [36.99557, 36.75997], [36.66727, 36.82901], [36.61581, 36.74629], [36.62681, 36.71189], [36.57398, 36.65186], [36.58829, 36.58295], [36.54206, 36.49539], [36.6081, 36.33772], [36.65653, 36.33861], [36.68672, 36.23677], [36.6125, 36.22592], [36.50463, 36.2419], [36.4617, 36.20461], [36.39206, 36.22088], [36.37474, 36.01163], [36.33956, 35.98687], [36.30099, 36.00985], [36.28338, 36.00273], [36.29769, 35.96086], [36.27678, 35.94839], [36.25366, 35.96264], [36.19973, 35.95195], [36.17441, 35.92076], [36.1623, 35.80925], [36.14029, 35.81015], [36.13919, 35.83692], [36.11827, 35.85923], [35.99829, 35.88242], [36.01844, 35.92403], [36.00514, 35.94113], [35.98499, 35.94107], [35.931, 35.92109], [35.51152, 36.10954], [35.48515, 34.70851], [35.97386, 34.63322], [35.98718, 34.64977], [36.29165, 34.62991], [36.32399, 34.69334], [36.35135, 34.68516], [36.35384, 34.65447], [36.42941, 34.62505], [36.46003, 34.6378], [36.45299, 34.59438], [36.41429, 34.61175], [36.39846, 34.55672], [36.3369, 34.52629], [36.34745, 34.5002], [36.4442, 34.50165], [36.46179, 34.46541], [36.55853, 34.41609], [36.53039, 34.3798], [36.56556, 34.31881], [36.60778, 34.31009], [36.58667, 34.27667], [36.59195, 34.2316], [36.62537, 34.20251], [36.5128, 34.09916], [36.50576, 34.05982], [36.41078, 34.05253], [36.28589, 33.91981], [36.38263, 33.86579], [36.3967, 33.83365], [36.14517, 33.85118], [36.06778, 33.82927], [35.9341, 33.6596], [36.05723, 33.57904], [35.94465, 33.52774], [35.94816, 33.47886], [35.88668, 33.43183], [35.82577, 33.40479], [35.81324, 33.36354], [35.77477, 33.33609], [35.813, 33.3172], [35.77513, 33.27342], [35.81295, 33.24841], [35.81647, 33.2028], [35.83846, 33.19397], [35.84285, 33.16673], [35.81911, 33.1336], [35.81911, 33.11077], [35.84802, 33.1031], [35.87188, 32.98028], [35.89298, 32.9456], [35.87012, 32.91976], [35.84021, 32.8725], [35.83758, 32.82817], [35.78745, 32.77938], [35.75983, 32.74803], [35.88405, 32.71321], [35.93307, 32.71966], [35.96633, 32.66237], [36.02239, 32.65911], [36.08074, 32.51463], [36.20379, 32.52751], [36.20875, 32.49529], [36.23948, 32.50108], [36.40959, 32.37908], [36.83946, 32.31293], [38.79171, 33.37328], [40.64314, 34.31604], [40.97676, 34.39788], [41.12388, 34.65742], [41.2345, 34.80049], [41.21654, 35.1508], [41.26569, 35.42708], [41.38184, 35.62502], [41.37027, 35.84095], [41.2564, 36.06012], [41.28864, 36.35368], [41.40058, 36.52502], [41.81736, 36.58782], [42.36697, 37.0627], [42.35724, 37.10998], [42.32313, 37.17814], [42.34735, 37.22548], [42.2824, 37.2798], [42.26039, 37.27017], [42.23683, 37.2863]]]]
26926           }
26927         }, {
26928           type: "Feature",
26929           properties: {
26930             iso1A2: "SZ",
26931             iso1A3: "SWZ",
26932             iso1N3: "748",
26933             wikidata: "Q1050",
26934             nameEn: "Eswatini",
26935             aliases: ["Swaziland"],
26936             groups: ["018", "202", "002", "UN"],
26937             driveSide: "left",
26938             callingCodes: ["268"]
26939           },
26940           geometry: {
26941             type: "MultiPolygon",
26942             coordinates: [[[[31.86881, -25.99973], [31.4175, -25.71886], [31.31237, -25.7431], [31.13073, -25.91558], [30.95819, -26.26303], [30.78927, -26.48271], [30.81101, -26.84722], [30.88826, -26.79622], [30.97757, -26.92706], [30.96088, -27.0245], [31.15027, -27.20151], [31.49834, -27.31549], [31.97592, -27.31675], [31.97463, -27.11057], [32.00893, -26.8096], [32.09664, -26.80721], [32.13315, -26.84345], [32.13409, -26.5317], [32.07352, -26.40185], [32.10435, -26.15656], [32.08599, -26.00978], [32.00916, -25.999], [31.974, -25.95387], [31.86881, -25.99973]]]]
26943           }
26944         }, {
26945           type: "Feature",
26946           properties: {
26947             iso1A2: "TA",
26948             iso1A3: "TAA",
26949             wikidata: "Q220982",
26950             nameEn: "Tristan da Cunha",
26951             aliases: ["SH-TA"],
26952             country: "GB",
26953             groups: ["SH", "BOTS", "011", "202", "002", "UN"],
26954             isoStatus: "excRes",
26955             driveSide: "left",
26956             roadSpeedUnit: "mph",
26957             roadHeightUnit: "ft",
26958             callingCodes: ["290 8", "44 20"]
26959           },
26960           geometry: {
26961             type: "MultiPolygon",
26962             coordinates: [[[[-13.38232, -34.07258], [-16.67337, -41.9188], [-5.88482, -41.4829], [-13.38232, -34.07258]]]]
26963           }
26964         }, {
26965           type: "Feature",
26966           properties: {
26967             iso1A2: "TC",
26968             iso1A3: "TCA",
26969             iso1N3: "796",
26970             wikidata: "Q18221",
26971             nameEn: "Turks and Caicos Islands",
26972             country: "GB",
26973             groups: ["BOTS", "029", "003", "419", "019", "UN"],
26974             driveSide: "left",
26975             roadSpeedUnit: "mph",
26976             roadHeightUnit: "ft",
26977             callingCodes: ["1 649"]
26978           },
26979           geometry: {
26980             type: "MultiPolygon",
26981             coordinates: [[[[-71.70065, 25.7637], [-72.98446, 20.4801], [-69.80718, 21.35956], [-71.70065, 25.7637]]]]
26982           }
26983         }, {
26984           type: "Feature",
26985           properties: {
26986             iso1A2: "TD",
26987             iso1A3: "TCD",
26988             iso1N3: "148",
26989             wikidata: "Q657",
26990             nameEn: "Chad",
26991             groups: ["017", "202", "002", "UN"],
26992             callingCodes: ["235"]
26993           },
26994           geometry: {
26995             type: "MultiPolygon",
26996             coordinates: [[[[23.99539, 19.49944], [15.99566, 23.49639], [14.99751, 23.00539], [15.19692, 21.99339], [15.20213, 21.49365], [15.28332, 21.44557], [15.62515, 20.95395], [15.57248, 20.92138], [15.55382, 20.86507], [15.56004, 20.79488], [15.59841, 20.74039], [15.6721, 20.70069], [15.99632, 20.35364], [15.75098, 19.93002], [15.6032, 18.77402], [15.50373, 16.89649], [14.37425, 15.72591], [13.86301, 15.04043], [13.78991, 14.87519], [13.809, 14.72915], [13.67878, 14.64013], [13.68573, 14.55276], [13.48259, 14.46704], [13.47559, 14.40881], [13.6302, 13.71094], [14.08251, 13.0797], [14.46881, 13.08259], [14.56101, 12.91036], [14.55058, 12.78256], [14.83314, 12.62963], [14.90827, 12.3269], [14.89019, 12.16593], [14.96952, 12.0925], [15.00146, 12.1223], [15.0349, 12.10698], [15.05786, 12.0608], [15.04808, 11.8731], [15.11579, 11.79313], [15.06595, 11.71126], [15.13149, 11.5537], [15.0585, 11.40481], [15.10021, 11.04101], [15.04957, 11.02347], [15.09127, 10.87431], [15.06737, 10.80921], [15.15532, 10.62846], [15.14936, 10.53915], [15.23724, 10.47764], [15.30874, 10.31063], [15.50535, 10.1098], [15.68761, 9.99344], [15.41408, 9.92876], [15.24618, 9.99246], [15.14043, 9.99246], [15.05999, 9.94845], [14.95722, 9.97926], [14.80082, 9.93818], [14.4673, 10.00264], [14.20411, 10.00055], [14.1317, 9.82413], [14.01793, 9.73169], [13.97544, 9.6365], [14.37094, 9.2954], [14.35707, 9.19611], [14.83566, 8.80557], [15.09484, 8.65982], [15.20426, 8.50892], [15.50743, 7.79302], [15.59272, 7.7696], [15.56964, 7.58936], [15.49743, 7.52179], [15.73118, 7.52006], [15.79942, 7.44149], [16.40703, 7.68809], [16.41583, 7.77971], [16.58315, 7.88657], [16.59415, 7.76444], [16.658, 7.75353], [16.6668, 7.67281], [16.8143, 7.53971], [17.67288, 7.98905], [17.93926, 7.95853], [18.02731, 8.01085], [18.6085, 8.05009], [18.64153, 8.08714], [18.62612, 8.14163], [18.67455, 8.22226], [18.79783, 8.25929], [19.11044, 8.68172], [18.86388, 8.87971], [19.06421, 9.00367], [20.36748, 9.11019], [20.82979, 9.44696], [21.26348, 9.97642], [21.34934, 9.95907], [21.52766, 10.2105], [21.63553, 10.217], [21.71479, 10.29932], [21.72139, 10.64136], [22.45889, 11.00246], [22.87758, 10.91915], [22.97249, 11.21955], [22.93124, 11.41645], [22.7997, 11.40424], [22.54907, 11.64372], [22.64092, 12.07485], [22.48369, 12.02766], [22.50548, 12.16769], [22.38873, 12.45514], [22.46345, 12.61925], [22.22684, 12.74682], [22.15679, 12.66634], [21.98711, 12.63292], [21.89371, 12.68001], [21.81432, 12.81362], [21.94819, 13.05637], [22.02914, 13.13976], [22.1599, 13.19281], [22.29689, 13.3731], [22.08674, 13.77863], [22.22995, 13.96754], [22.5553, 14.11704], [22.55997, 14.23024], [22.44944, 14.24986], [22.38562, 14.58907], [22.70474, 14.69149], [22.66115, 14.86308], [22.99584, 15.22989], [22.99584, 15.40105], [22.92579, 15.47007], [22.93201, 15.55107], [23.10792, 15.71297], [23.38812, 15.69649], [23.62785, 15.7804], [23.99997, 15.69575], [23.99539, 19.49944]]]]
26997           }
26998         }, {
26999           type: "Feature",
27000           properties: {
27001             iso1A2: "TF",
27002             iso1A3: "ATF",
27003             iso1N3: "260",
27004             wikidata: "Q129003",
27005             nameEn: "French Southern Territories",
27006             country: "FR"
27007           },
27008           geometry: null
27009         }, {
27010           type: "Feature",
27011           properties: {
27012             iso1A2: "TG",
27013             iso1A3: "TGO",
27014             iso1N3: "768",
27015             wikidata: "Q945",
27016             nameEn: "Togo",
27017             groups: ["011", "202", "002", "UN"],
27018             callingCodes: ["228"]
27019           },
27020           geometry: {
27021             type: "MultiPolygon",
27022             coordinates: [[[[0.50388, 11.01011], [-0.13493, 11.14075], [-0.14462, 11.10811], [-0.05733, 11.08628], [-0.0275, 11.11202], [-514e-5, 11.10763], [342e-5, 11.08317], [0.02395, 11.06229], [0.03355, 10.9807], [-63e-4, 10.96417], [-908e-5, 10.91644], [-0.02685, 10.8783], [-0.0228, 10.81916], [-0.07183, 10.76794], [-0.07327, 10.71845], [-0.09141, 10.7147], [-0.05945, 10.63458], [0.12886, 10.53149], [0.18846, 10.4096], [0.29453, 10.41546], [0.33028, 10.30408], [0.39584, 10.31112], [0.35293, 10.09412], [0.41371, 10.06361], [0.41252, 10.02018], [0.36366, 10.03309], [0.32075, 9.72781], [0.34816, 9.71607], [0.34816, 9.66907], [0.32313, 9.6491], [0.28261, 9.69022], [0.26712, 9.66437], [0.29334, 9.59387], [0.36008, 9.6256], [0.38153, 9.58682], [0.23851, 9.57389], [0.2409, 9.52335], [0.30406, 9.521], [0.31241, 9.50337], [0.2254, 9.47869], [0.25758, 9.42696], [0.33148, 9.44812], [0.36485, 9.49749], [0.49118, 9.48339], [0.56388, 9.40697], [0.45424, 9.04581], [0.52455, 8.87746], [0.37319, 8.75262], [0.47211, 8.59945], [0.64731, 8.48866], [0.73432, 8.29529], [0.63897, 8.25873], [0.5913, 8.19622], [0.61156, 8.18324], [0.6056, 8.13959], [0.58891, 8.12779], [0.62943, 7.85751], [0.58295, 7.62368], [0.51979, 7.58706], [0.52455, 7.45354], [0.57223, 7.39326], [0.62943, 7.41099], [0.65327, 7.31643], [0.59606, 7.01252], [0.52217, 6.9723], [0.52098, 6.94391], [0.56508, 6.92971], [0.52853, 6.82921], [0.57406, 6.80348], [0.58176, 6.76049], [0.6497, 6.73682], [0.63659, 6.63857], [0.74862, 6.56517], [0.71048, 6.53083], [0.89283, 6.33779], [0.99652, 6.33779], [1.03108, 6.24064], [1.05969, 6.22998], [1.09187, 6.17074], [1.19966, 6.17069], [1.19771, 6.11522], [1.27574, 5.93551], [1.67336, 6.02702], [1.62913, 6.24075], [1.79826, 6.28221], [1.76906, 6.43189], [1.58105, 6.68619], [1.61812, 6.74843], [1.55877, 6.99737], [1.64249, 6.99562], [1.61838, 9.0527], [1.5649, 9.16941], [1.41746, 9.3226], [1.33675, 9.54765], [1.36624, 9.5951], [1.35507, 9.99525], [0.77666, 10.37665], [0.80358, 10.71459], [0.8804, 10.803], [0.91245, 10.99597], [0.66104, 10.99964], [0.4958, 10.93269], [0.50521, 10.98035], [0.48852, 10.98561], [0.50388, 11.01011]]]]
27023           }
27024         }, {
27025           type: "Feature",
27026           properties: {
27027             iso1A2: "TH",
27028             iso1A3: "THA",
27029             iso1N3: "764",
27030             wikidata: "Q869",
27031             nameEn: "Thailand",
27032             groups: ["035", "142", "UN"],
27033             driveSide: "left",
27034             callingCodes: ["66"]
27035           },
27036           geometry: {
27037             type: "MultiPolygon",
27038             coordinates: [[[[100.08404, 20.36626], [99.95721, 20.46301], [99.91616, 20.44986], [99.90499, 20.4487], [99.89692, 20.44789], [99.89301, 20.44311], [99.89168, 20.44548], [99.88451, 20.44596], [99.88211, 20.44488], [99.86383, 20.44371], [99.81096, 20.33687], [99.68255, 20.32077], [99.46008, 20.39673], [99.46077, 20.36198], [99.5569, 20.20676], [99.52943, 20.14811], [99.416, 20.08614], [99.20328, 20.12877], [99.0735, 20.10298], [98.98679, 19.7419], [98.83661, 19.80931], [98.56065, 19.67807], [98.51182, 19.71303], [98.24884, 19.67876], [98.13829, 19.78541], [98.03314, 19.80941], [98.04364, 19.65755], [97.84715, 19.55782], [97.88423, 19.5041], [97.78769, 19.39429], [97.84186, 19.29526], [97.78606, 19.26769], [97.84024, 19.22217], [97.83479, 19.09972], [97.73797, 19.04261], [97.73654, 18.9812], [97.66487, 18.9371], [97.73836, 18.88478], [97.76752, 18.58097], [97.5258, 18.4939], [97.36444, 18.57138], [97.34522, 18.54596], [97.50383, 18.26844], [97.56219, 18.33885], [97.64116, 18.29778], [97.60841, 18.23846], [97.73723, 17.97912], [97.66794, 17.88005], [97.76407, 17.71595], [97.91829, 17.54504], [98.11185, 17.36829], [98.10439, 17.33847], [98.34566, 17.04822], [98.39441, 17.06266], [98.52624, 16.89979], [98.49603, 16.8446], [98.53833, 16.81934], [98.46994, 16.73613], [98.50253, 16.7139], [98.49713, 16.69022], [98.51043, 16.70107], [98.51579, 16.69433], [98.51472, 16.68521], [98.51833, 16.676], [98.51113, 16.64503], [98.5695, 16.62826], [98.57912, 16.55983], [98.63817, 16.47424], [98.68074, 16.27068], [98.84485, 16.42354], [98.92656, 16.36425], [98.8376, 16.11706], [98.69585, 16.13353], [98.57019, 16.04578], [98.59853, 15.87197], [98.541, 15.65406], [98.58598, 15.46821], [98.56027, 15.33471], [98.4866, 15.39154], [98.39351, 15.34177], [98.41906, 15.27103], [98.40522, 15.25268], [98.30446, 15.30667], [98.22, 15.21327], [98.18821, 15.13125], [98.24874, 14.83013], [98.56762, 14.37701], [98.97356, 14.04868], [99.16695, 13.72621], [99.20617, 13.20575], [99.12225, 13.19847], [99.10646, 13.05804], [99.18748, 12.9898], [99.18905, 12.84799], [99.29254, 12.68921], [99.409, 12.60603], [99.47519, 12.1353], [99.56445, 12.14805], [99.53424, 12.02317], [99.64891, 11.82699], [99.64108, 11.78948], [99.5672, 11.62732], [99.47598, 11.62434], [99.39485, 11.3925], [99.31573, 11.32081], [99.32756, 11.28545], [99.06938, 10.94857], [99.02337, 10.97217], [98.99701, 10.92962], [99.0069, 10.85485], [98.86819, 10.78336], [98.78511, 10.68351], [98.77275, 10.62548], [98.81944, 10.52761], [98.7391, 10.31488], [98.55174, 9.92804], [98.52291, 9.92389], [98.47298, 9.95782], [98.33094, 9.91973], [98.12555, 9.44056], [97.63455, 9.60854], [97.19814, 8.18901], [99.31854, 5.99868], [99.50117, 6.44501], [99.91873, 6.50233], [100.0756, 6.4045], [100.12, 6.42105], [100.19511, 6.72559], [100.29651, 6.68439], [100.30828, 6.66462], [100.31618, 6.66781], [100.31884, 6.66423], [100.32671, 6.66526], [100.32607, 6.65933], [100.31929, 6.65413], [100.35413, 6.54932], [100.41152, 6.52299], [100.41791, 6.5189], [100.42351, 6.51762], [100.43027, 6.52389], [100.66986, 6.45086], [100.74361, 6.50811], [100.74822, 6.46231], [100.81045, 6.45086], [100.85884, 6.24929], [101.10313, 6.25617], [101.12618, 6.19431], [101.06165, 6.14161], [101.12388, 6.11411], [101.087, 5.9193], [101.02708, 5.91013], [100.98815, 5.79464], [101.14062, 5.61613], [101.25755, 5.71065], [101.25524, 5.78633], [101.58019, 5.93534], [101.69773, 5.75881], [101.75074, 5.79091], [101.80144, 5.74505], [101.89188, 5.8386], [101.91776, 5.84269], [101.92819, 5.85511], [101.94712, 5.98421], [101.9714, 6.00575], [101.97114, 6.01992], [101.99209, 6.04075], [102.01835, 6.05407], [102.09182, 6.14161], [102.07732, 6.193], [102.08127, 6.22679], [102.09086, 6.23546], [102.46318, 7.22462], [102.47649, 9.66162], [102.52395, 11.25257], [102.91449, 11.65512], [102.90973, 11.75613], [102.83957, 11.8519], [102.78427, 11.98746], [102.77026, 12.06815], [102.70176, 12.1686], [102.73134, 12.37091], [102.78116, 12.40284], [102.7796, 12.43781], [102.57567, 12.65358], [102.51963, 12.66117], [102.4994, 12.71736], [102.53053, 12.77506], [102.49335, 12.92711], [102.48694, 12.97537], [102.52275, 12.99813], [102.46011, 13.08057], [102.43422, 13.09061], [102.36146, 13.26006], [102.36001, 13.31142], [102.34611, 13.35618], [102.35692, 13.38274], [102.35563, 13.47307], [102.361, 13.50551], [102.33828, 13.55613], [102.36859, 13.57488], [102.44601, 13.5637], [102.5358, 13.56933], [102.57573, 13.60461], [102.62483, 13.60883], [102.58635, 13.6286], [102.5481, 13.6589], [102.56848, 13.69366], [102.72727, 13.77806], [102.77864, 13.93374], [102.91251, 14.01531], [102.93275, 14.19044], [103.16469, 14.33075], [103.39353, 14.35639], [103.53518, 14.42575], [103.71109, 14.4348], [103.70175, 14.38052], [103.93836, 14.3398], [104.27616, 14.39861], [104.55014, 14.36091], [104.69335, 14.42726], [104.97667, 14.38806], [105.02804, 14.23722], [105.08408, 14.20402], [105.14012, 14.23873], [105.17748, 14.34432], [105.20894, 14.34967], [105.43783, 14.43865], [105.53864, 14.55731], [105.5121, 14.80802], [105.61162, 15.00037], [105.46661, 15.13132], [105.58043, 15.32724], [105.50662, 15.32054], [105.4692, 15.33709], [105.47635, 15.3796], [105.58191, 15.41031], [105.60446, 15.53301], [105.61756, 15.68792], [105.46573, 15.74742], [105.42285, 15.76971], [105.37959, 15.84074], [105.34115, 15.92737], [105.38508, 15.987], [105.42001, 16.00657], [105.06204, 16.09792], [105.00262, 16.25627], [104.88057, 16.37311], [104.73349, 16.565], [104.76099, 16.69302], [104.7397, 16.81005], [104.76442, 16.84752], [104.7373, 16.91125], [104.73712, 17.01404], [104.80716, 17.19025], [104.80061, 17.39367], [104.69867, 17.53038], [104.45404, 17.66788], [104.35432, 17.82871], [104.2757, 17.86139], [104.21776, 17.99335], [104.10927, 18.10826], [104.06533, 18.21656], [103.97725, 18.33631], [103.93916, 18.33914], [103.85642, 18.28666], [103.82449, 18.33979], [103.699, 18.34125], [103.60957, 18.40528], [103.47773, 18.42841], [103.41044, 18.4486], [103.30977, 18.4341], [103.24779, 18.37807], [103.23818, 18.34875], [103.29757, 18.30475], [103.17093, 18.2618], [103.14994, 18.23172], [103.1493, 18.17799], [103.07343, 18.12351], [103.07823, 18.03833], [103.0566, 18.00144], [103.01998, 17.97095], [102.9912, 17.9949], [102.95812, 18.0054], [102.86323, 17.97531], [102.81988, 17.94233], [102.79044, 17.93612], [102.75954, 17.89561], [102.68538, 17.86653], [102.67543, 17.84529], [102.69946, 17.81686], [102.68194, 17.80151], [102.59485, 17.83537], [102.5896, 17.84889], [102.61432, 17.92273], [102.60971, 17.95411], [102.59234, 17.96127], [102.45523, 17.97106], [102.11359, 18.21532], [101.88485, 18.02474], [101.78087, 18.07559], [101.72294, 17.92867], [101.44667, 17.7392], [101.15108, 17.47586], [100.96541, 17.57926], [101.02185, 17.87637], [101.1793, 18.0544], [101.19118, 18.2125], [101.15108, 18.25624], [101.18227, 18.34367], [101.06047, 18.43247], [101.27585, 18.68875], [101.22832, 18.73377], [101.25803, 18.89545], [101.35606, 19.04716], [101.261, 19.12717], [101.24911, 19.33334], [101.20604, 19.35296], [101.21347, 19.46223], [101.26991, 19.48324], [101.26545, 19.59242], [101.08928, 19.59748], [100.90302, 19.61901], [100.77231, 19.48324], [100.64606, 19.55884], [100.58219, 19.49164], [100.49604, 19.53504], [100.398, 19.75047], [100.5094, 19.87904], [100.58808, 20.15791], [100.55218, 20.17741], [100.51052, 20.14928], [100.47567, 20.19133], [100.4537, 20.19971], [100.44992, 20.23644], [100.41473, 20.25625], [100.37439, 20.35156], [100.33383, 20.4028], [100.25769, 20.3992], [100.22076, 20.31598], [100.16668, 20.2986], [100.1712, 20.24324], [100.11785, 20.24787], [100.09337, 20.26293], [100.09999, 20.31614], [100.08404, 20.36626]]]]
27039           }
27040         }, {
27041           type: "Feature",
27042           properties: {
27043             iso1A2: "TJ",
27044             iso1A3: "TJK",
27045             iso1N3: "762",
27046             wikidata: "Q863",
27047             nameEn: "Tajikistan",
27048             groups: ["143", "142", "UN"],
27049             callingCodes: ["992"]
27050           },
27051           geometry: {
27052             type: "MultiPolygon",
27053             coordinates: [[[[70.45251, 41.04438], [70.38028, 41.02014], [70.36655, 40.90296], [69.69434, 40.62615], [69.59441, 40.70181], [69.53021, 40.77621], [69.38327, 40.7918], [69.32834, 40.70233], [69.3455, 40.57988], [69.2643, 40.57506], [69.21063, 40.54469], [69.27066, 40.49274], [69.28525, 40.41894], [69.30774, 40.36102], [69.33794, 40.34819], [69.32833, 40.29794], [69.30808, 40.2821], [69.24817, 40.30357], [69.25229, 40.26362], [69.30104, 40.24502], [69.30448, 40.18774], [69.2074, 40.21488], [69.15659, 40.2162], [69.04544, 40.22904], [68.85832, 40.20885], [68.84357, 40.18604], [68.79276, 40.17555], [68.77902, 40.20492], [68.5332, 40.14826], [68.52771, 40.11676], [68.62796, 40.07789], [69.01523, 40.15771], [69.01935, 40.11466], [68.96579, 40.06949], [68.84906, 40.04952], [68.93695, 39.91167], [68.88889, 39.87163], [68.63071, 39.85265], [68.61972, 39.68905], [68.54166, 39.53929], [68.12053, 39.56317], [67.70992, 39.66156], [67.62889, 39.60234], [67.44899, 39.57799], [67.46547, 39.53564], [67.39681, 39.52505], [67.46822, 39.46146], [67.45998, 39.315], [67.36522, 39.31287], [67.33226, 39.23739], [67.67833, 39.14479], [67.68915, 39.00775], [68.09704, 39.02589], [68.19743, 38.85985], [68.06948, 38.82115], [68.12877, 38.73677], [68.05598, 38.71641], [68.0807, 38.64136], [68.05873, 38.56087], [68.11366, 38.47169], [68.06274, 38.39435], [68.13289, 38.40822], [68.40343, 38.19484], [68.27159, 37.91477], [68.12635, 37.93], [67.81566, 37.43107], [67.8474, 37.31594], [67.78329, 37.1834], [67.7803, 37.08978], [67.87917, 37.0591], [68.02194, 36.91923], [68.18542, 37.02074], [68.27605, 37.00977], [68.29253, 37.10621], [68.41201, 37.10402], [68.41888, 37.13906], [68.61851, 37.19815], [68.6798, 37.27906], [68.81438, 37.23862], [68.80889, 37.32494], [68.91189, 37.26704], [68.88168, 37.33368], [68.96407, 37.32603], [69.03274, 37.25174], [69.25152, 37.09426], [69.39529, 37.16752], [69.45022, 37.23315], [69.36645, 37.40462], [69.44954, 37.4869], [69.51888, 37.5844], [69.80041, 37.5746], [69.84435, 37.60616], [69.93362, 37.61378], [69.95971, 37.5659], [70.15015, 37.52519], [70.28243, 37.66706], [70.27694, 37.81258], [70.1863, 37.84296], [70.17206, 37.93276], [70.4898, 38.12546], [70.54673, 38.24541], [70.60407, 38.28046], [70.61526, 38.34774], [70.64966, 38.34999], [70.69189, 38.37031], [70.6761, 38.39144], [70.67438, 38.40597], [70.69807, 38.41861], [70.72485, 38.4131], [70.75455, 38.4252], [70.77132, 38.45548], [70.78581, 38.45502], [70.78702, 38.45031], [70.79766, 38.44944], [70.80521, 38.44447], [70.81697, 38.44507], [70.82538, 38.45394], [70.84376, 38.44688], [70.88719, 38.46826], [70.92728, 38.43021], [70.98693, 38.48862], [71.03545, 38.44779], [71.0556, 38.40176], [71.09542, 38.42517], [71.10592, 38.42077], [71.10957, 38.40671], [71.1451, 38.40106], [71.21291, 38.32797], [71.33114, 38.30339], [71.33869, 38.27335], [71.37803, 38.25641], [71.36444, 38.15358], [71.29878, 38.04429], [71.28922, 38.01272], [71.27622, 37.99946], [71.27278, 37.96496], [71.24969, 37.93031], [71.2809, 37.91995], [71.296, 37.93403], [71.32871, 37.88564], [71.51565, 37.95349], [71.58843, 37.92425], [71.59255, 37.79956], [71.55752, 37.78677], [71.54324, 37.77104], [71.53053, 37.76534], [71.55234, 37.73209], [71.54186, 37.69691], [71.51972, 37.61945], [71.5065, 37.60912], [71.49693, 37.53527], [71.50616, 37.50733], [71.5256, 37.47971], [71.49612, 37.4279], [71.47685, 37.40281], [71.4862, 37.33405], [71.49821, 37.31975], [71.50674, 37.31502], [71.48536, 37.26017], [71.4824, 37.24921], [71.48339, 37.23937], [71.47386, 37.2269], [71.4555, 37.21418], [71.4494, 37.18137], [71.44127, 37.11856], [71.43097, 37.05855], [71.45578, 37.03094], [71.46923, 36.99925], [71.48481, 36.93218], [71.51502, 36.89128], [71.57195, 36.74943], [71.67083, 36.67346], [71.83229, 36.68084], [72.31676, 36.98115], [72.54095, 37.00007], [72.66381, 37.02014], [72.79693, 37.22222], [73.06884, 37.31729], [73.29633, 37.46495], [73.77197, 37.4417], [73.76647, 37.33913], [73.61129, 37.27469], [73.64974, 37.23643], [73.82552, 37.22659], [73.8564, 37.26158], [74.20308, 37.34208], [74.23339, 37.41116], [74.41055, 37.3948], [74.56161, 37.37734], [74.68383, 37.3948], [74.8294, 37.3435], [74.88887, 37.23275], [75.12328, 37.31839], [75.09719, 37.37297], [75.15899, 37.41443], [75.06011, 37.52779], [74.94338, 37.55501], [74.8912, 37.67576], [75.00935, 37.77486], [74.92416, 37.83428], [74.9063, 38.03033], [74.82665, 38.07359], [74.80331, 38.19889], [74.69894, 38.22155], [74.69619, 38.42947], [74.51217, 38.47034], [74.17022, 38.65504], [73.97933, 38.52945], [73.79806, 38.61106], [73.80656, 38.66449], [73.7033, 38.84782], [73.7445, 38.93867], [73.82964, 38.91517], [73.81728, 39.04007], [73.75823, 39.023], [73.60638, 39.24534], [73.54572, 39.27567], [73.55396, 39.3543], [73.5004, 39.38402], [73.59241, 39.40843], [73.59831, 39.46425], [73.45096, 39.46677], [73.31912, 39.38615], [73.18454, 39.35536], [72.85934, 39.35116], [72.62027, 39.39696], [72.33173, 39.33093], [72.23834, 39.17248], [72.17242, 39.2661], [72.09689, 39.26823], [72.04059, 39.36704], [71.90601, 39.27674], [71.79202, 39.27355], [71.7522, 39.32031], [71.80164, 39.40631], [71.76816, 39.45456], [71.62688, 39.44056], [71.5517, 39.45722], [71.55856, 39.57588], [71.49814, 39.61397], [71.08752, 39.50704], [71.06418, 39.41586], [70.7854, 39.38933], [70.64087, 39.58792], [70.44757, 39.60128], [70.2869, 39.53141], [70.11111, 39.58223], [69.87491, 39.53882], [69.68677, 39.59281], [69.3594, 39.52516], [69.26938, 39.8127], [69.35649, 40.01994], [69.43134, 39.98431], [69.43557, 39.92877], [69.53615, 39.93991], [69.5057, 40.03277], [69.53855, 40.0887], [69.53794, 40.11833], [69.55555, 40.12296], [69.57615, 40.10524], [69.64704, 40.12165], [69.67001, 40.10639], [70.01283, 40.23288], [70.58297, 40.00891], [70.57384, 39.99394], [70.47557, 39.93216], [70.55033, 39.96619], [70.58912, 39.95211], [70.65946, 39.9878], [70.65827, 40.0981], [70.7928, 40.12797], [70.80495, 40.16813], [70.9818, 40.22392], [70.8607, 40.217], [70.62342, 40.17396], [70.56394, 40.26421], [70.57149, 40.3442], [70.37511, 40.38605], [70.32626, 40.45174], [70.49871, 40.52503], [70.80009, 40.72825], [70.45251, 41.04438]]], [[[70.68112, 40.90612], [70.6158, 40.97661], [70.56077, 41.00642], [70.54223, 40.98787], [70.57501, 40.98941], [70.6721, 40.90555], [70.68112, 40.90612]]], [[[70.74189, 39.86319], [70.53651, 39.89155], [70.52631, 39.86989], [70.54998, 39.85137], [70.59667, 39.83542], [70.63105, 39.77923], [70.74189, 39.86319]]]]
27054           }
27055         }, {
27056           type: "Feature",
27057           properties: {
27058             iso1A2: "TK",
27059             iso1A3: "TKL",
27060             iso1N3: "772",
27061             wikidata: "Q36823",
27062             nameEn: "Tokelau",
27063             country: "NZ",
27064             groups: ["061", "009", "UN"],
27065             driveSide: "left",
27066             callingCodes: ["690"]
27067           },
27068           geometry: {
27069             type: "MultiPolygon",
27070             coordinates: [[[[-168.251, -9.44289], [-174.18635, -7.80441], [-174.17993, -10.13616], [-168.251, -9.44289]]]]
27071           }
27072         }, {
27073           type: "Feature",
27074           properties: {
27075             iso1A2: "TL",
27076             iso1A3: "TLS",
27077             iso1N3: "626",
27078             wikidata: "Q574",
27079             nameEn: "East Timor",
27080             aliases: ["Timor-Leste", "TP"],
27081             groups: ["035", "142", "UN"],
27082             driveSide: "left",
27083             callingCodes: ["670"]
27084           },
27085           geometry: {
27086             type: "MultiPolygon",
27087             coordinates: [[[[124.46701, -9.13002], [124.94011, -8.85617], [124.97742, -9.08128], [125.11764, -8.96359], [125.18632, -9.03142], [125.18907, -9.16434], [125.09434, -9.19669], [125.04044, -9.17093], [124.97892, -9.19281], [125.09025, -9.46406], [125.68138, -9.85176], [127.55165, -9.05052], [127.42116, -8.22471], [125.87691, -8.31789], [125.58506, -7.95311], [124.92337, -8.75859], [124.33472, -9.11416], [124.04628, -9.22671], [124.04286, -9.34243], [124.10539, -9.41206], [124.14517, -9.42324], [124.21247, -9.36904], [124.28115, -9.42189], [124.28115, -9.50453], [124.3535, -9.48493], [124.35258, -9.43002], [124.38554, -9.3582], [124.45971, -9.30263], [124.46701, -9.13002]]]]
27088           }
27089         }, {
27090           type: "Feature",
27091           properties: {
27092             iso1A2: "TM",
27093             iso1A3: "TKM",
27094             iso1N3: "795",
27095             wikidata: "Q874",
27096             nameEn: "Turkmenistan",
27097             groups: ["143", "142", "UN"],
27098             callingCodes: ["993"]
27099           },
27100           geometry: {
27101             type: "MultiPolygon",
27102             coordinates: [[[[60.5078, 41.21694], [60.06581, 41.4363], [60.18117, 41.60082], [60.06032, 41.76287], [60.08504, 41.80997], [60.33223, 41.75058], [59.95046, 41.97966], [60.0356, 42.01028], [60.04659, 42.08982], [59.96419, 42.1428], [60.00539, 42.212], [59.94633, 42.27655], [59.4341, 42.29738], [59.2955, 42.37064], [59.17317, 42.52248], [58.93422, 42.5407], [58.6266, 42.79314], [58.57991, 42.64988], [58.27504, 42.69632], [58.14321, 42.62159], [58.29427, 42.56497], [58.51674, 42.30348], [58.40688, 42.29535], [58.3492, 42.43335], [57.99214, 42.50021], [57.90975, 42.4374], [57.92897, 42.24047], [57.84932, 42.18555], [57.6296, 42.16519], [57.30275, 42.14076], [57.03633, 41.92043], [56.96218, 41.80383], [57.03359, 41.41777], [57.13796, 41.36625], [57.03423, 41.25435], [56.00314, 41.32584], [55.45471, 41.25609], [54.95182, 41.92424], [54.20635, 42.38477], [52.97575, 42.1308], [52.47884, 41.78034], [52.26048, 41.69249], [51.7708, 40.29239], [53.89734, 37.3464], [54.24565, 37.32047], [54.36211, 37.34912], [54.58664, 37.45809], [54.67247, 37.43532], [54.77822, 37.51597], [54.81804, 37.61285], [54.77684, 37.62264], [54.851, 37.75739], [55.13412, 37.94705], [55.44152, 38.08564], [55.76561, 38.12238], [55.97847, 38.08024], [56.33278, 38.08132], [56.32454, 38.18502], [56.43303, 38.26054], [56.62255, 38.24005], [56.73928, 38.27887], [57.03453, 38.18717], [57.21169, 38.28965], [57.37236, 38.09321], [57.35042, 37.98546], [57.79534, 37.89299], [58.21399, 37.77281], [58.22999, 37.6856], [58.39959, 37.63134], [58.47786, 37.6433], [58.5479, 37.70526], [58.6921, 37.64548], [58.9338, 37.67374], [59.22905, 37.51161], [59.33507, 37.53146], [59.39797, 37.47892], [59.39385, 37.34257], [59.55178, 37.13594], [59.74678, 37.12499], [60.00768, 37.04102], [60.34767, 36.63214], [61.14516, 36.64644], [61.18187, 36.55348], [61.1393, 36.38782], [61.22719, 36.12759], [61.12007, 35.95992], [61.22444, 35.92879], [61.26152, 35.80749], [61.22719, 35.67038], [61.27371, 35.61482], [61.58742, 35.43803], [61.77693, 35.41341], [61.97743, 35.4604], [62.05709, 35.43803], [62.15871, 35.33278], [62.29191, 35.25964], [62.29878, 35.13312], [62.48006, 35.28796], [62.62288, 35.22067], [62.74098, 35.25432], [62.90853, 35.37086], [63.0898, 35.43131], [63.12276, 35.53196], [63.10079, 35.63024], [63.23262, 35.67487], [63.10318, 35.81782], [63.12276, 35.86208], [63.29579, 35.85985], [63.53475, 35.90881], [63.56496, 35.95106], [63.98519, 36.03773], [64.05385, 36.10433], [64.43288, 36.24401], [64.57295, 36.34362], [64.62514, 36.44311], [64.61141, 36.6351], [64.97945, 37.21913], [65.51778, 37.23881], [65.64263, 37.34388], [65.64137, 37.45061], [65.72274, 37.55438], [66.30993, 37.32409], [66.55743, 37.35409], [66.52303, 37.39827], [66.65761, 37.45497], [66.52852, 37.58568], [66.53676, 37.80084], [66.67684, 37.96776], [66.56697, 38.0435], [66.41042, 38.02403], [66.24013, 38.16238], [65.83913, 38.25733], [65.55873, 38.29052], [64.32576, 38.98691], [64.19086, 38.95561], [63.70778, 39.22349], [63.6913, 39.27666], [62.43337, 39.98528], [62.34273, 40.43206], [62.11751, 40.58242], [61.87856, 41.12257], [61.4446, 41.29407], [61.39732, 41.19873], [61.33199, 41.14946], [61.22212, 41.14946], [61.03261, 41.25691], [60.5078, 41.21694]]]]
27103           }
27104         }, {
27105           type: "Feature",
27106           properties: {
27107             iso1A2: "TN",
27108             iso1A3: "TUN",
27109             iso1N3: "788",
27110             wikidata: "Q948",
27111             nameEn: "Tunisia",
27112             groups: ["015", "002", "UN"],
27113             callingCodes: ["216"]
27114           },
27115           geometry: {
27116             type: "MultiPolygon",
27117             coordinates: [[[[11.2718, 37.6713], [7.89009, 38.19924], [8.59123, 37.14286], [8.64044, 36.9401], [8.62972, 36.86499], [8.67706, 36.8364], [8.57613, 36.78062], [8.46537, 36.7706], [8.47609, 36.66607], [8.16167, 36.48817], [8.18936, 36.44939], [8.40731, 36.42208], [8.2626, 35.91733], [8.26472, 35.73669], [8.35371, 35.66373], [8.36086, 35.47774], [8.30329, 35.29884], [8.47318, 35.23376], [8.3555, 35.10007], [8.30727, 34.95378], [8.25189, 34.92009], [8.29655, 34.72798], [8.20482, 34.57575], [7.86264, 34.3987], [7.81242, 34.21841], [7.74207, 34.16492], [7.66174, 34.20167], [7.52851, 34.06493], [7.54088, 33.7726], [7.73687, 33.42114], [7.83028, 33.18851], [8.11433, 33.10175], [8.1179, 33.05086], [8.31895, 32.83483], [8.35999, 32.50101], [9.07483, 32.07865], [9.55544, 30.23971], [9.76848, 30.34366], [9.88152, 30.34074], [10.29516, 30.90337], [10.12239, 31.42098], [10.31364, 31.72648], [10.48497, 31.72956], [10.62788, 31.96629], [10.7315, 31.97235], [11.04234, 32.2145], [11.53898, 32.4138], [11.57828, 32.48013], [11.46037, 32.6307], [11.51549, 33.09826], [11.55852, 33.1409], [11.58941, 33.36891], [11.2718, 37.6713]]]]
27118           }
27119         }, {
27120           type: "Feature",
27121           properties: {
27122             iso1A2: "TO",
27123             iso1A3: "TON",
27124             iso1N3: "776",
27125             wikidata: "Q678",
27126             nameEn: "Tonga",
27127             groups: ["061", "009", "UN"],
27128             driveSide: "left",
27129             callingCodes: ["676"]
27130           },
27131           geometry: {
27132             type: "MultiPolygon",
27133             coordinates: [[[[-176.74538, -22.89767], [-180, -22.90585], [-180, -24.21376], [-173.10761, -24.19665], [-173.13438, -14.94228], [-176.76826, -14.95183], [-176.74538, -22.89767]]]]
27134           }
27135         }, {
27136           type: "Feature",
27137           properties: {
27138             iso1A2: "TR",
27139             iso1A3: "TUR",
27140             iso1N3: "792",
27141             wikidata: "Q43",
27142             nameEn: "Turkey",
27143             groups: ["145", "142", "UN"],
27144             callingCodes: ["90"]
27145           },
27146           geometry: {
27147             type: "MultiPolygon",
27148             coordinates: [[[[41.54366, 41.52185], [40.89217, 41.72528], [34.8305, 42.4581], [28.32297, 41.98371], [28.02971, 41.98066], [27.91479, 41.97902], [27.83492, 41.99709], [27.81235, 41.94803], [27.69949, 41.97515], [27.55191, 41.90928], [27.52379, 41.93756], [27.45478, 41.96591], [27.27411, 42.10409], [27.22376, 42.10152], [27.19251, 42.06028], [27.08486, 42.08735], [27.03277, 42.0809], [26.95638, 42.00741], [26.79143, 41.97386], [26.62996, 41.97644], [26.56051, 41.92995], [26.57961, 41.90024], [26.53968, 41.82653], [26.36952, 41.82265], [26.33589, 41.76802], [26.32952, 41.73637], [26.35957, 41.71149], [26.47958, 41.67037], [26.5209, 41.62592], [26.59196, 41.60491], [26.59742, 41.48058], [26.61767, 41.42281], [26.62997, 41.34613], [26.5837, 41.32131], [26.5209, 41.33993], [26.39861, 41.25053], [26.32259, 41.24929], [26.31928, 41.07386], [26.3606, 41.02027], [26.33297, 40.98388], [26.35894, 40.94292], [26.32259, 40.94042], [26.28623, 40.93005], [26.29441, 40.89119], [26.26169, 40.9168], [26.20856, 40.86048], [26.21351, 40.83298], [26.15685, 40.80709], [26.12854, 40.77339], [26.12495, 40.74283], [26.08638, 40.73214], [26.0754, 40.72772], [26.03489, 40.73051], [25.94795, 40.72797], [26.04292, 40.3958], [25.61285, 40.17161], [25.94257, 39.39358], [26.43357, 39.43096], [26.70773, 39.0312], [26.61814, 38.81372], [26.21136, 38.65436], [26.32173, 38.48731], [26.24183, 38.44695], [26.21136, 38.17558], [27.05537, 37.9131], [27.16428, 37.72343], [26.99377, 37.69034], [26.95583, 37.64989], [27.14757, 37.32], [27.20312, 36.94571], [27.45627, 36.9008], [27.24613, 36.71622], [27.46117, 36.53789], [27.89482, 36.69898], [27.95037, 36.46155], [28.23708, 36.56812], [29.30783, 36.01033], [29.48192, 36.18377], [29.61002, 36.1731], [29.61805, 36.14179], [29.69611, 36.10365], [29.73302, 35.92555], [32.82353, 35.70297], [35.51152, 36.10954], [35.931, 35.92109], [35.98499, 35.94107], [36.00514, 35.94113], [36.01844, 35.92403], [35.99829, 35.88242], [36.11827, 35.85923], [36.13919, 35.83692], [36.14029, 35.81015], [36.1623, 35.80925], [36.17441, 35.92076], [36.19973, 35.95195], [36.25366, 35.96264], [36.27678, 35.94839], [36.29769, 35.96086], [36.28338, 36.00273], [36.30099, 36.00985], [36.33956, 35.98687], [36.37474, 36.01163], [36.39206, 36.22088], [36.4617, 36.20461], [36.50463, 36.2419], [36.6125, 36.22592], [36.68672, 36.23677], [36.65653, 36.33861], [36.6081, 36.33772], [36.54206, 36.49539], [36.58829, 36.58295], [36.57398, 36.65186], [36.62681, 36.71189], [36.61581, 36.74629], [36.66727, 36.82901], [36.99557, 36.75997], [36.99886, 36.74012], [37.04399, 36.73483], [37.04619, 36.71101], [37.01647, 36.69512], [37.02088, 36.66422], [37.08279, 36.63495], [37.10894, 36.6704], [37.16177, 36.66069], [37.21988, 36.6736], [37.47253, 36.63243], [37.49103, 36.66904], [37.68048, 36.75065], [37.81974, 36.76055], [38.21064, 36.91842], [38.38859, 36.90064], [38.55908, 36.84429], [38.74042, 36.70629], [39.03217, 36.70911], [39.21538, 36.66834], [39.81589, 36.75538], [40.69136, 37.0996], [40.90856, 37.13147], [41.21937, 37.07665], [41.515, 37.08084], [42.00894, 37.17209], [42.18225, 37.28569], [42.19301, 37.31323], [42.2112, 37.32491], [42.22257, 37.31395], [42.22381, 37.30238], [42.20454, 37.28715], [42.21548, 37.28026], [42.23683, 37.2863], [42.26039, 37.27017], [42.2824, 37.2798], [42.34735, 37.22548], [42.32313, 37.17814], [42.35724, 37.10998], [42.56725, 37.14878], [42.78887, 37.38615], [42.93705, 37.32015], [43.11403, 37.37436], [43.30083, 37.30629], [43.33508, 37.33105], [43.50787, 37.24436], [43.56702, 37.25675], [43.63085, 37.21957], [43.7009, 37.23692], [43.8052, 37.22825], [43.82699, 37.19477], [43.84878, 37.22205], [43.90949, 37.22453], [44.02002, 37.33229], [44.13521, 37.32486], [44.2613, 37.25055], [44.27998, 37.16501], [44.22239, 37.15756], [44.18503, 37.09551], [44.25975, 36.98119], [44.30645, 36.97373], [44.35937, 37.02843], [44.35315, 37.04955], [44.38117, 37.05825], [44.42631, 37.05825], [44.63179, 37.19229], [44.76698, 37.16162], [44.78319, 37.1431], [44.7868, 37.16644], [44.75986, 37.21549], [44.81021, 37.2915], [44.58449, 37.45018], [44.61401, 37.60165], [44.56887, 37.6429], [44.62096, 37.71985], [44.55498, 37.783], [44.45948, 37.77065], [44.3883, 37.85433], [44.22509, 37.88859], [44.42476, 38.25763], [44.50115, 38.33939], [44.44386, 38.38295], [44.38309, 38.36117], [44.3119, 38.37887], [44.3207, 38.49799], [44.32058, 38.62752], [44.28065, 38.6465], [44.26155, 38.71427], [44.30322, 38.81581], [44.18863, 38.93881], [44.20946, 39.13975], [44.1043, 39.19842], [44.03667, 39.39223], [44.22452, 39.4169], [44.29818, 39.378], [44.37921, 39.4131], [44.42832, 39.4131], [44.41849, 39.56659], [44.48111, 39.61579], [44.47298, 39.68788], [44.6137, 39.78393], [44.65422, 39.72163], [44.71806, 39.71124], [44.81043, 39.62677], [44.80977, 39.65768], [44.75779, 39.7148], [44.61845, 39.8281], [44.46635, 39.97733], [44.26973, 40.04866], [44.1778, 40.02845], [44.1057, 40.03555], [43.92307, 40.01787], [43.65688, 40.11199], [43.65221, 40.14889], [43.71136, 40.16673], [43.59928, 40.34019], [43.60862, 40.43267], [43.54791, 40.47413], [43.63664, 40.54159], [43.7425, 40.66805], [43.74872, 40.7365], [43.67712, 40.84846], [43.67712, 40.93084], [43.58683, 40.98961], [43.47319, 41.02251], [43.44984, 41.0988], [43.4717, 41.12611], [43.44973, 41.17666], [43.36118, 41.2028], [43.23096, 41.17536], [43.1945, 41.25242], [43.13373, 41.25503], [43.21707, 41.30331], [43.02956, 41.37891], [42.8785, 41.50516], [42.84899, 41.47265], [42.78995, 41.50126], [42.84471, 41.58912], [42.72794, 41.59714], [42.59202, 41.58183], [42.51772, 41.43606], [42.26387, 41.49346], [41.95134, 41.52466], [41.81939, 41.43621], [41.7124, 41.47417], [41.7148, 41.4932], [41.54366, 41.52185]]]]
27149           }
27150         }, {
27151           type: "Feature",
27152           properties: {
27153             iso1A2: "TT",
27154             iso1A3: "TTO",
27155             iso1N3: "780",
27156             wikidata: "Q754",
27157             nameEn: "Trinidad and Tobago",
27158             groups: ["029", "003", "419", "019", "UN"],
27159             driveSide: "left",
27160             callingCodes: ["1 868"]
27161           },
27162           geometry: {
27163             type: "MultiPolygon",
27164             coordinates: [[[[-61.62505, 11.18974], [-62.08693, 10.04435], [-60.89962, 9.81445], [-60.07172, 11.77667], [-61.62505, 11.18974]]]]
27165           }
27166         }, {
27167           type: "Feature",
27168           properties: {
27169             iso1A2: "TV",
27170             iso1A3: "TUV",
27171             iso1N3: "798",
27172             wikidata: "Q672",
27173             nameEn: "Tuvalu",
27174             groups: ["061", "009", "UN"],
27175             driveSide: "left",
27176             callingCodes: ["688"]
27177           },
27178           geometry: {
27179             type: "MultiPolygon",
27180             coordinates: [[[[174, -5], [174, -11.5], [179.99999, -11.5], [179.99999, -5], [174, -5]]]]
27181           }
27182         }, {
27183           type: "Feature",
27184           properties: {
27185             iso1A2: "TW",
27186             iso1A3: "TWN",
27187             iso1N3: "158",
27188             wikidata: "Q865",
27189             nameEn: "Taiwan",
27190             aliases: ["RC"],
27191             groups: ["030", "142"],
27192             callingCodes: ["886"]
27193           },
27194           geometry: {
27195             type: "MultiPolygon",
27196             coordinates: [[[[121.8109, 21.77688], [122.26612, 25.98197], [120.49232, 25.22863], [118.56434, 24.49266], [118.42453, 24.54644], [118.35291, 24.51645], [118.28244, 24.51231], [118.11703, 24.39734], [120.69238, 21.52331], [121.8109, 21.77688]]]]
27197           }
27198         }, {
27199           type: "Feature",
27200           properties: {
27201             iso1A2: "TZ",
27202             iso1A3: "TZA",
27203             iso1N3: "834",
27204             wikidata: "Q924",
27205             nameEn: "Tanzania",
27206             groups: ["014", "202", "002", "UN"],
27207             driveSide: "left",
27208             callingCodes: ["255"]
27209           },
27210           geometry: {
27211             type: "MultiPolygon",
27212             coordinates: [[[[30.80408, -0.99911], [30.76635, -0.9852], [30.70631, -1.01175], [30.64166, -1.06601], [30.47194, -1.0555], [30.45116, -1.10641], [30.50889, -1.16412], [30.57123, -1.33264], [30.71974, -1.43244], [30.84079, -1.64652], [30.80802, -1.91477], [30.89303, -2.08223], [30.83915, -2.35795], [30.54501, -2.41404], [30.41789, -2.66266], [30.52747, -2.65841], [30.40662, -2.86151], [30.4987, -2.9573], [30.57926, -2.89791], [30.6675, -2.98987], [30.83823, -2.97837], [30.84165, -3.25152], [30.45915, -3.56532], [30.22042, -4.01738], [30.03323, -4.26631], [29.88172, -4.35743], [29.82885, -4.36153], [29.77289, -4.41733], [29.75109, -4.45836], [29.63827, -4.44681], [29.43673, -4.44845], [29.52552, -6.2731], [30.2567, -7.14121], [30.79243, -8.27382], [31.00796, -8.58615], [31.37533, -8.60769], [31.57147, -8.70619], [31.57147, -8.81388], [31.71158, -8.91386], [31.81587, -8.88618], [31.94663, -8.93846], [31.94196, -9.02303], [31.98866, -9.07069], [32.08206, -9.04609], [32.16146, -9.05993], [32.25486, -9.13371], [32.43543, -9.11988], [32.49147, -9.14754], [32.53661, -9.24281], [32.75611, -9.28583], [32.76233, -9.31963], [32.95389, -9.40138], [32.99397, -9.36712], [33.14925, -9.49322], [33.31581, -9.48554], [33.48052, -9.62442], [33.76677, -9.58516], [33.93298, -9.71647], [33.9638, -9.62206], [33.95829, -9.54066], [34.03865, -9.49398], [34.54499, -10.0678], [34.51911, -10.12279], [34.57581, -10.56271], [34.65946, -10.6828], [34.67047, -10.93796], [34.61161, -11.01611], [34.63305, -11.11731], [34.79375, -11.32245], [34.91153, -11.39799], [34.96296, -11.57354], [35.63599, -11.55927], [35.82767, -11.41081], [36.19094, -11.57593], [36.19094, -11.70008], [36.62068, -11.72884], [36.80309, -11.56836], [37.3936, -11.68949], [37.76614, -11.53352], [37.8388, -11.3123], [37.93618, -11.26228], [38.21598, -11.27289], [38.47258, -11.4199], [38.88996, -11.16978], [39.24395, -11.17433], [39.58249, -10.96043], [40.00295, -10.80255], [40.44265, -10.4618], [40.74206, -10.25691], [40.14328, -4.64201], [39.62121, -4.68136], [39.44306, -4.93877], [39.21631, -4.67835], [37.81321, -3.69179], [37.75036, -3.54243], [37.63099, -3.50723], [37.5903, -3.42735], [37.71745, -3.304], [37.67199, -3.06222], [34.0824, -1.02264], [34.03084, -1.05101], [34.02286, -1.00779], [33.93107, -0.99298], [30.80408, -0.99911]]]]
27213           }
27214         }, {
27215           type: "Feature",
27216           properties: {
27217             iso1A2: "UA",
27218             iso1A3: "UKR",
27219             iso1N3: "804",
27220             wikidata: "Q212",
27221             nameEn: "Ukraine",
27222             groups: ["151", "150", "UN"],
27223             callingCodes: ["380"]
27224           },
27225           geometry: {
27226             type: "MultiPolygon",
27227             coordinates: [[[[33.57318, 46.10317], [33.61467, 46.13561], [33.63854, 46.14147], [33.61517, 46.22615], [33.646, 46.23028], [33.74047, 46.18555], [33.79715, 46.20482], [33.85234, 46.19863], [33.91549, 46.15938], [34.05272, 46.10838], [34.07311, 46.11769], [34.12929, 46.10494], [34.181, 46.06804], [34.25111, 46.0532], [34.33912, 46.06114], [34.41221, 46.00245], [34.44155, 45.95995], [34.48729, 45.94267], [34.52011, 45.95097], [34.55889, 45.99347], [34.60861, 45.99347], [34.66679, 45.97136], [34.75479, 45.90705], [34.80153, 45.90047], [34.79905, 45.81009], [34.96015, 45.75634], [35.23066, 45.79231], [37.62608, 46.82615], [38.12112, 46.86078], [38.3384, 46.98085], [38.22955, 47.12069], [38.23049, 47.2324], [38.32112, 47.2585], [38.33074, 47.30508], [38.22225, 47.30788], [38.28954, 47.39255], [38.28679, 47.53552], [38.35062, 47.61631], [38.76379, 47.69346], [38.79628, 47.81109], [38.87979, 47.87719], [39.73935, 47.82876], [39.82213, 47.96396], [39.77544, 48.04206], [39.88256, 48.04482], [39.83724, 48.06501], [39.94847, 48.22811], [40.00752, 48.22445], [39.99241, 48.31768], [39.97325, 48.31399], [39.9693, 48.29904], [39.95248, 48.29972], [39.91465, 48.26743], [39.90041, 48.3049], [39.84273, 48.30947], [39.84136, 48.33321], [39.94847, 48.35055], [39.88794, 48.44226], [39.86196, 48.46633], [39.84548, 48.57821], [39.79764, 48.58668], [39.67226, 48.59368], [39.71765, 48.68673], [39.73104, 48.7325], [39.79466, 48.83739], [39.97182, 48.79398], [40.08168, 48.87443], [40.03636, 48.91957], [39.98967, 48.86901], [39.78368, 48.91596], [39.74874, 48.98675], [39.72649, 48.9754], [39.71353, 48.98959], [39.6683, 48.99454], [39.6836, 49.05121], [39.93437, 49.05709], [40.01988, 49.1761], [40.22176, 49.25683], [40.18331, 49.34996], [40.14912, 49.37681], [40.1141, 49.38798], [40.03087, 49.45452], [40.03636, 49.52321], [40.16683, 49.56865], [40.13249, 49.61672], [39.84548, 49.56064], [39.65047, 49.61761], [39.59142, 49.73758], [39.44496, 49.76067], [39.27968, 49.75976], [39.1808, 49.88911], [38.9391, 49.79524], [38.90477, 49.86787], [38.73311, 49.90238], [38.68677, 50.00904], [38.65688, 49.97176], [38.35408, 50.00664], [38.32524, 50.08866], [38.18517, 50.08161], [38.21675, 49.98104], [38.02999, 49.90592], [38.02999, 49.94482], [37.90776, 50.04194], [37.79515, 50.08425], [37.75807, 50.07896], [37.61113, 50.21976], [37.62879, 50.24481], [37.62486, 50.29966], [37.47243, 50.36277], [37.48204, 50.46079], [37.08468, 50.34935], [36.91762, 50.34963], [36.69377, 50.26982], [36.64571, 50.218], [36.56655, 50.2413], [36.58371, 50.28563], [36.47817, 50.31457], [36.30101, 50.29088], [36.20763, 50.3943], [36.06893, 50.45205], [35.8926, 50.43829], [35.80388, 50.41356], [35.73659, 50.35489], [35.61711, 50.35707], [35.58003, 50.45117], [35.47463, 50.49247], [35.39464, 50.64751], [35.48116, 50.66405], [35.47704, 50.77274], [35.41367, 50.80227], [35.39307, 50.92145], [35.32598, 50.94524], [35.40837, 51.04119], [35.31774, 51.08434], [35.20375, 51.04723], [35.12685, 51.16191], [35.14058, 51.23162], [34.97304, 51.2342], [34.82472, 51.17483], [34.6874, 51.18], [34.6613, 51.25053], [34.38802, 51.2746], [34.31661, 51.23936], [34.23009, 51.26429], [34.33446, 51.363], [34.22048, 51.4187], [34.30562, 51.5205], [34.17599, 51.63253], [34.07765, 51.67065], [34.42922, 51.72852], [34.41136, 51.82793], [34.09413, 52.00835], [34.11199, 52.14087], [34.05239, 52.20132], [33.78789, 52.37204], [33.55718, 52.30324], [33.48027, 52.31499], [33.51323, 52.35779], [33.18913, 52.3754], [32.89937, 52.2461], [32.85405, 52.27888], [32.69475, 52.25535], [32.54781, 52.32423], [32.3528, 52.32842], [32.38988, 52.24946], [32.33083, 52.23685], [32.34044, 52.1434], [32.2777, 52.10266], [32.23331, 52.08085], [32.08813, 52.03319], [31.92159, 52.05144], [31.96141, 52.08015], [31.85018, 52.11305], [31.81722, 52.09955], [31.7822, 52.11406], [31.38326, 52.12991], [31.25142, 52.04131], [31.13332, 52.1004], [30.95589, 52.07775], [30.90897, 52.00699], [30.76443, 51.89739], [30.68804, 51.82806], [30.51946, 51.59649], [30.64992, 51.35014], [30.56203, 51.25655], [30.36153, 51.33984], [30.34642, 51.42555], [30.17888, 51.51025], [29.77376, 51.4461], [29.7408, 51.53417], [29.54372, 51.48372], [29.49773, 51.39814], [29.42357, 51.4187], [29.32881, 51.37843], [29.25191, 51.49828], [29.25603, 51.57089], [29.20659, 51.56918], [29.16402, 51.64679], [29.1187, 51.65872], [28.99098, 51.56833], [28.95528, 51.59222], [28.81795, 51.55552], [28.76027, 51.48802], [28.78224, 51.45294], [28.75615, 51.41442], [28.73143, 51.46236], [28.69161, 51.44695], [28.64429, 51.5664], [28.47051, 51.59734], [28.37592, 51.54505], [28.23452, 51.66988], [28.10658, 51.57857], [27.95827, 51.56065], [27.91844, 51.61952], [27.85253, 51.62293], [27.76052, 51.47604], [27.67125, 51.50854], [27.71932, 51.60672], [27.55727, 51.63486], [27.51058, 51.5854], [27.47212, 51.61184], [27.24828, 51.60161], [27.26613, 51.65957], [27.20948, 51.66713], [27.20602, 51.77291], [26.99422, 51.76933], [26.9489, 51.73788], [26.80043, 51.75777], [26.69759, 51.82284], [26.46962, 51.80501], [26.39367, 51.87315], [26.19084, 51.86781], [26.00408, 51.92967], [25.83217, 51.92587], [25.80574, 51.94556], [25.73673, 51.91973], [25.46163, 51.92205], [25.20228, 51.97143], [24.98784, 51.91273], [24.37123, 51.88222], [24.29021, 51.80841], [24.3163, 51.75063], [24.13075, 51.66979], [23.99907, 51.58369], [23.8741, 51.59734], [23.91118, 51.63316], [23.7766, 51.66809], [23.60906, 51.62122], [23.6736, 51.50255], [23.62751, 51.50512], [23.69905, 51.40871], [23.63858, 51.32182], [23.80678, 51.18405], [23.90376, 51.07697], [23.92217, 51.00836], [24.04576, 50.90196], [24.14524, 50.86128], [24.0952, 50.83262], [23.99254, 50.83847], [23.95925, 50.79271], [24.0595, 50.71625], [24.0996, 50.60752], [24.07048, 50.5071], [24.03668, 50.44507], [23.99563, 50.41289], [23.79445, 50.40481], [23.71382, 50.38248], [23.67635, 50.33385], [23.28221, 50.0957], [22.99329, 49.84249], [22.83179, 49.69875], [22.80261, 49.69098], [22.78304, 49.65543], [22.64534, 49.53094], [22.69444, 49.49378], [22.748, 49.32759], [22.72009, 49.20288], [22.86336, 49.10513], [22.89122, 49.00725], [22.56155, 49.08865], [22.54338, 49.01424], [22.48296, 48.99172], [22.42934, 48.92857], [22.34151, 48.68893], [22.21379, 48.6218], [22.16023, 48.56548], [22.14689, 48.4005], [22.2083, 48.42534], [22.38133, 48.23726], [22.49806, 48.25189], [22.59007, 48.15121], [22.58733, 48.10813], [22.66835, 48.09162], [22.73427, 48.12005], [22.81804, 48.11363], [22.87847, 48.04665], [22.84276, 47.98602], [22.89849, 47.95851], [22.94301, 47.96672], [22.92241, 48.02002], [23.0158, 47.99338], [23.08858, 48.00716], [23.1133, 48.08061], [23.15999, 48.12188], [23.27397, 48.08245], [23.33577, 48.0237], [23.4979, 47.96858], [23.52803, 48.01818], [23.5653, 48.00499], [23.63894, 48.00293], [23.66262, 47.98786], [23.75188, 47.99705], [23.80904, 47.98142], [23.8602, 47.9329], [23.89352, 47.94512], [23.94192, 47.94868], [23.96337, 47.96672], [23.98553, 47.96076], [24.00801, 47.968], [24.02999, 47.95087], [24.06466, 47.95317], [24.11281, 47.91487], [24.22566, 47.90231], [24.34926, 47.9244], [24.43578, 47.97131], [24.61994, 47.95062], [24.70632, 47.84428], [24.81893, 47.82031], [24.88896, 47.7234], [25.11144, 47.75203], [25.23778, 47.89403], [25.63878, 47.94924], [25.77723, 47.93919], [26.05901, 47.9897], [26.17711, 47.99246], [26.33504, 48.18418], [26.55202, 48.22445], [26.62823, 48.25804], [26.6839, 48.35828], [26.79239, 48.29071], [26.82809, 48.31629], [26.71274, 48.40388], [26.85556, 48.41095], [26.93384, 48.36558], [27.03821, 48.37653], [27.0231, 48.42485], [27.08078, 48.43214], [27.13434, 48.37288], [27.27855, 48.37534], [27.32159, 48.4434], [27.37604, 48.44398], [27.37741, 48.41026], [27.44333, 48.41209], [27.46942, 48.454], [27.5889, 48.49224], [27.59027, 48.46311], [27.6658, 48.44034], [27.74422, 48.45926], [27.79225, 48.44244], [27.81902, 48.41874], [27.87533, 48.4037], [27.88391, 48.36699], [27.95883, 48.32368], [28.04527, 48.32661], [28.09873, 48.3124], [28.07504, 48.23494], [28.17666, 48.25963], [28.19314, 48.20749], [28.2856, 48.23202], [28.32508, 48.23384], [28.35519, 48.24957], [28.36996, 48.20543], [28.34912, 48.1787], [28.30586, 48.1597], [28.30609, 48.14018], [28.34009, 48.13147], [28.38712, 48.17567], [28.43701, 48.15832], [28.42454, 48.12047], [28.48428, 48.0737], [28.53921, 48.17453], [28.69896, 48.13106], [28.85232, 48.12506], [28.8414, 48.03392], [28.9306, 47.96255], [29.1723, 47.99013], [29.19839, 47.89261], [29.27804, 47.88893], [29.20663, 47.80367], [29.27255, 47.79953], [29.22242, 47.73607], [29.22414, 47.60012], [29.11743, 47.55001], [29.18603, 47.43387], [29.3261, 47.44664], [29.39889, 47.30179], [29.47854, 47.30366], [29.48678, 47.36043], [29.5733, 47.36508], [29.59665, 47.25521], [29.54996, 47.24962], [29.57696, 47.13581], [29.49732, 47.12878], [29.53044, 47.07851], [29.61038, 47.09932], [29.62137, 47.05069], [29.57056, 46.94766], [29.72986, 46.92234], [29.75458, 46.8604], [29.87405, 46.88199], [29.98814, 46.82358], [29.94522, 46.80055], [29.9743, 46.75325], [29.94409, 46.56002], [29.88916, 46.54302], [30.02511, 46.45132], [30.16794, 46.40967], [30.09103, 46.38694], [29.94114, 46.40114], [29.88329, 46.35851], [29.74496, 46.45605], [29.66359, 46.4215], [29.6763, 46.36041], [29.5939, 46.35472], [29.49914, 46.45889], [29.35357, 46.49505], [29.24886, 46.37912], [29.23547, 46.55435], [29.02409, 46.49582], [29.01241, 46.46177], [28.9306, 46.45699], [29.004, 46.31495], [28.98478, 46.31803], [28.94953, 46.25852], [29.06656, 46.19716], [28.94643, 46.09176], [29.00613, 46.04962], [28.98004, 46.00385], [28.74383, 45.96664], [28.78503, 45.83475], [28.69852, 45.81753], [28.70401, 45.78019], [28.52823, 45.73803], [28.47879, 45.66994], [28.51587, 45.6613], [28.54196, 45.58062], [28.49252, 45.56716], [28.51449, 45.49982], [28.43072, 45.48538], [28.41836, 45.51715], [28.30201, 45.54744], [28.21139, 45.46895], [28.28504, 45.43907], [28.34554, 45.32102], [28.5735, 45.24759], [28.71358, 45.22631], [28.78911, 45.24179], [28.81383, 45.3384], [28.94292, 45.28045], [28.96077, 45.33164], [29.24779, 45.43388], [29.42632, 45.44545], [29.59798, 45.38857], [29.68175, 45.26885], [29.65428, 45.25629], [29.69272, 45.19227], [30.04414, 45.08461], [31.62627, 45.50633], [33.54017, 46.0123], [33.59087, 46.06013], [33.57318, 46.10317]]]]
27228           }
27229         }, {
27230           type: "Feature",
27231           properties: {
27232             iso1A2: "UG",
27233             iso1A3: "UGA",
27234             iso1N3: "800",
27235             wikidata: "Q1036",
27236             nameEn: "Uganda",
27237             groups: ["014", "202", "002", "UN"],
27238             driveSide: "left",
27239             callingCodes: ["256"]
27240           },
27241           geometry: {
27242             type: "MultiPolygon",
27243             coordinates: [[[[33.93107, -0.99298], [33.9264, -0.54188], [33.98449, -0.13079], [33.90936, 0.10581], [34.10067, 0.36372], [34.08727, 0.44713], [34.11408, 0.48884], [34.13493, 0.58118], [34.20196, 0.62289], [34.27345, 0.63182], [34.31516, 0.75693], [34.40041, 0.80266], [34.43349, 0.85254], [34.52369, 1.10692], [34.57427, 1.09868], [34.58029, 1.14712], [34.67562, 1.21265], [34.80223, 1.22754], [34.82606, 1.26626], [34.82606, 1.30944], [34.7918, 1.36752], [34.87819, 1.5596], [34.92734, 1.56109], [34.9899, 1.6668], [34.98692, 1.97348], [34.90947, 2.42447], [34.95267, 2.47209], [34.77244, 2.70272], [34.78137, 2.76223], [34.73967, 2.85447], [34.65774, 2.8753], [34.60114, 2.93034], [34.56242, 3.11478], [34.45815, 3.18319], [34.40006, 3.37949], [34.41794, 3.44342], [34.39112, 3.48802], [34.44922, 3.51627], [34.45815, 3.67385], [34.15429, 3.80464], [34.06046, 4.15235], [33.9873, 4.23316], [33.51264, 3.75068], [33.18356, 3.77812], [33.02852, 3.89296], [32.89746, 3.81339], [32.72021, 3.77327], [32.41337, 3.748], [32.20782, 3.6053], [32.19888, 3.50867], [32.08866, 3.53543], [32.08491, 3.56287], [32.05187, 3.589], [31.95907, 3.57408], [31.96205, 3.6499], [31.86821, 3.78664], [31.81459, 3.82083], [31.72075, 3.74354], [31.50776, 3.63652], [31.50478, 3.67814], [31.29476, 3.8015], [31.16666, 3.79853], [30.97601, 3.693], [30.85153, 3.48867], [30.94081, 3.50847], [30.93486, 3.40737], [30.84251, 3.26908], [30.77101, 3.04897], [30.8574, 2.9508], [30.8857, 2.83923], [30.75612, 2.5863], [30.74271, 2.43601], [30.83059, 2.42559], [30.91102, 2.33332], [30.96911, 2.41071], [31.06593, 2.35862], [31.07934, 2.30207], [31.12104, 2.27676], [31.1985, 2.29462], [31.20148, 2.2217], [31.28042, 2.17853], [31.30127, 2.11006], [30.48503, 1.21675], [30.24671, 1.14974], [30.22139, 0.99635], [30.1484, 0.89805], [29.98307, 0.84295], [29.95477, 0.64486], [29.97413, 0.52124], [29.87284, 0.39166], [29.81922, 0.16824], [29.77454, 0.16675], [29.7224, 0.07291], [29.72687, -0.08051], [29.65091, -0.46777], [29.67474, -0.47969], [29.67176, -0.55714], [29.62708, -0.71055], [29.63006, -0.8997], [29.58388, -0.89821], [29.59061, -1.39016], [29.82657, -1.31187], [29.912, -1.48269], [30.16369, -1.34303], [30.35212, -1.06896], [30.47194, -1.0555], [30.64166, -1.06601], [30.70631, -1.01175], [30.76635, -0.9852], [30.80408, -0.99911], [33.93107, -0.99298]]]]
27244           }
27245         }, {
27246           type: "Feature",
27247           properties: {
27248             iso1A2: "UM",
27249             iso1A3: "UMI",
27250             iso1N3: "581",
27251             wikidata: "Q16645",
27252             nameEn: "United States Minor Outlying Islands",
27253             country: "US"
27254           },
27255           geometry: null
27256         }, {
27257           type: "Feature",
27258           properties: {
27259             iso1A2: "UN",
27260             wikidata: "Q1065",
27261             nameEn: "United Nations",
27262             level: "unitedNations",
27263             isoStatus: "excRes"
27264           },
27265           geometry: null
27266         }, {
27267           type: "Feature",
27268           properties: {
27269             iso1A2: "US",
27270             iso1A3: "USA",
27271             iso1N3: "840",
27272             wikidata: "Q30",
27273             nameEn: "United States of America"
27274           },
27275           geometry: null
27276         }, {
27277           type: "Feature",
27278           properties: {
27279             iso1A2: "UY",
27280             iso1A3: "URY",
27281             iso1N3: "858",
27282             wikidata: "Q77",
27283             nameEn: "Uruguay",
27284             groups: ["005", "419", "019", "UN"],
27285             callingCodes: ["598"]
27286           },
27287           geometry: {
27288             type: "MultiPolygon",
27289             coordinates: [[[[-57.65132, -30.19229], [-57.61478, -30.25165], [-57.64859, -30.35095], [-57.89115, -30.49572], [-57.8024, -30.77193], [-57.89476, -30.95994], [-57.86729, -31.06352], [-57.9908, -31.34924], [-57.98127, -31.3872], [-58.07569, -31.44916], [-58.0023, -31.53084], [-58.00076, -31.65016], [-58.20252, -31.86966], [-58.10036, -32.25338], [-58.22362, -32.52416], [-58.1224, -32.98842], [-58.40475, -33.11777], [-58.44442, -33.84033], [-58.34425, -34.15035], [-57.83001, -34.69099], [-54.78916, -36.21945], [-52.83257, -34.01481], [-53.37138, -33.74313], [-53.39593, -33.75169], [-53.44031, -33.69344], [-53.52794, -33.68908], [-53.53459, -33.16843], [-53.1111, -32.71147], [-53.37671, -32.57005], [-53.39572, -32.58596], [-53.76024, -32.0751], [-54.17384, -31.86168], [-55.50821, -30.91349], [-55.50841, -30.9027], [-55.51862, -30.89828], [-55.52712, -30.89997], [-55.53276, -30.90218], [-55.53431, -30.89714], [-55.54572, -30.89051], [-55.55218, -30.88193], [-55.55373, -30.8732], [-55.5634, -30.8686], [-55.58866, -30.84117], [-55.87388, -31.05053], [-56.4619, -30.38457], [-56.4795, -30.3899], [-56.49267, -30.39471], [-56.90236, -30.02578], [-57.22502, -30.26121], [-57.65132, -30.19229]]]]
27290           }
27291         }, {
27292           type: "Feature",
27293           properties: {
27294             iso1A2: "UZ",
27295             iso1A3: "UZB",
27296             iso1N3: "860",
27297             wikidata: "Q265",
27298             nameEn: "Uzbekistan",
27299             groups: ["143", "142", "UN"],
27300             callingCodes: ["998"]
27301           },
27302           geometry: {
27303             type: "MultiPolygon",
27304             coordinates: [[[[65.85194, 42.85481], [65.53277, 43.31856], [65.18666, 43.48835], [64.96464, 43.74748], [64.53885, 43.56941], [63.34656, 43.64003], [62.01711, 43.51008], [61.01475, 44.41383], [58.59711, 45.58671], [55.97842, 44.99622], [55.97832, 44.99622], [55.97822, 44.99617], [55.97811, 44.99617], [55.97801, 44.99612], [55.97801, 44.99607], [55.97791, 44.99607], [55.9778, 44.99607], [55.9777, 44.99601], [55.9777, 44.99596], [55.9776, 44.99591], [55.97749, 44.99591], [55.97739, 44.99591], [55.97739, 44.99586], [55.97729, 44.99586], [55.97718, 44.99581], [55.97708, 44.99576], [55.97698, 44.9957], [55.97698, 44.99565], [55.97687, 44.9956], [55.97677, 44.9956], [55.97677, 44.99555], [55.97677, 44.9955], [55.97667, 44.99545], [55.97656, 44.99539], [55.97646, 44.99534], [55.97646, 44.99529], [55.97636, 44.99524], [55.97636, 44.99519], [55.97625, 44.99514], [55.97615, 44.99508], [55.97615, 44.99503], [55.97615, 44.99498], [55.97615, 44.99493], [55.97615, 44.99483], [55.97615, 44.99477], [55.97605, 44.99477], [55.97605, 44.99467], [55.97605, 44.99462], [55.97605, 44.99457], [55.97605, 44.99452], [55.97594, 44.99446], [55.97584, 44.99441], [55.97584, 44.99436], [55.97584, 44.99431], [55.97584, 44.99426], [55.97584, 44.99421], [55.97584, 44.99415], [55.97584, 44.99405], [55.97584, 44.994], [55.97584, 44.9939], [55.97584, 44.99384], [55.97584, 44.99374], [55.97584, 44.99369], [55.97584, 44.99359], [55.97584, 44.99353], [55.97584, 44.99348], [55.97584, 44.99343], [55.97584, 44.99338], [55.97584, 44.99328], [55.97584, 44.99322], [56.00314, 41.32584], [57.03423, 41.25435], [57.13796, 41.36625], [57.03359, 41.41777], [56.96218, 41.80383], [57.03633, 41.92043], [57.30275, 42.14076], [57.6296, 42.16519], [57.84932, 42.18555], [57.92897, 42.24047], [57.90975, 42.4374], [57.99214, 42.50021], [58.3492, 42.43335], [58.40688, 42.29535], [58.51674, 42.30348], [58.29427, 42.56497], [58.14321, 42.62159], [58.27504, 42.69632], [58.57991, 42.64988], [58.6266, 42.79314], [58.93422, 42.5407], [59.17317, 42.52248], [59.2955, 42.37064], [59.4341, 42.29738], [59.94633, 42.27655], [60.00539, 42.212], [59.96419, 42.1428], [60.04659, 42.08982], [60.0356, 42.01028], [59.95046, 41.97966], [60.33223, 41.75058], [60.08504, 41.80997], [60.06032, 41.76287], [60.18117, 41.60082], [60.06581, 41.4363], [60.5078, 41.21694], [61.03261, 41.25691], [61.22212, 41.14946], [61.33199, 41.14946], [61.39732, 41.19873], [61.4446, 41.29407], [61.87856, 41.12257], [62.11751, 40.58242], [62.34273, 40.43206], [62.43337, 39.98528], [63.6913, 39.27666], [63.70778, 39.22349], [64.19086, 38.95561], [64.32576, 38.98691], [65.55873, 38.29052], [65.83913, 38.25733], [66.24013, 38.16238], [66.41042, 38.02403], [66.56697, 38.0435], [66.67684, 37.96776], [66.53676, 37.80084], [66.52852, 37.58568], [66.65761, 37.45497], [66.52303, 37.39827], [66.55743, 37.35409], [66.64699, 37.32958], [66.95598, 37.40162], [67.08232, 37.35469], [67.13039, 37.27168], [67.2224, 37.24545], [67.2581, 37.17216], [67.51868, 37.26102], [67.78329, 37.1834], [67.8474, 37.31594], [67.81566, 37.43107], [68.12635, 37.93], [68.27159, 37.91477], [68.40343, 38.19484], [68.13289, 38.40822], [68.06274, 38.39435], [68.11366, 38.47169], [68.05873, 38.56087], [68.0807, 38.64136], [68.05598, 38.71641], [68.12877, 38.73677], [68.06948, 38.82115], [68.19743, 38.85985], [68.09704, 39.02589], [67.68915, 39.00775], [67.67833, 39.14479], [67.33226, 39.23739], [67.36522, 39.31287], [67.45998, 39.315], [67.46822, 39.46146], [67.39681, 39.52505], [67.46547, 39.53564], [67.44899, 39.57799], [67.62889, 39.60234], [67.70992, 39.66156], [68.12053, 39.56317], [68.54166, 39.53929], [68.61972, 39.68905], [68.63071, 39.85265], [68.88889, 39.87163], [68.93695, 39.91167], [68.84906, 40.04952], [68.96579, 40.06949], [69.01935, 40.11466], [69.01523, 40.15771], [68.62796, 40.07789], [68.52771, 40.11676], [68.5332, 40.14826], [68.77902, 40.20492], [68.79276, 40.17555], [68.84357, 40.18604], [68.85832, 40.20885], [69.04544, 40.22904], [69.15659, 40.2162], [69.2074, 40.21488], [69.30448, 40.18774], [69.30104, 40.24502], [69.25229, 40.26362], [69.24817, 40.30357], [69.30808, 40.2821], [69.32833, 40.29794], [69.33794, 40.34819], [69.30774, 40.36102], [69.28525, 40.41894], [69.27066, 40.49274], [69.21063, 40.54469], [69.2643, 40.57506], [69.3455, 40.57988], [69.32834, 40.70233], [69.38327, 40.7918], [69.53021, 40.77621], [69.59441, 40.70181], [69.69434, 40.62615], [70.36655, 40.90296], [70.38028, 41.02014], [70.45251, 41.04438], [70.80009, 40.72825], [70.49871, 40.52503], [70.32626, 40.45174], [70.37511, 40.38605], [70.57149, 40.3442], [70.56394, 40.26421], [70.62342, 40.17396], [70.8607, 40.217], [70.9818, 40.22392], [70.95789, 40.28761], [71.05901, 40.28765], [71.13042, 40.34106], [71.36663, 40.31593], [71.4246, 40.28619], [71.51215, 40.26943], [71.51549, 40.22986], [71.61725, 40.20615], [71.61931, 40.26775], [71.68386, 40.26984], [71.70569, 40.20391], [71.69621, 40.18492], [71.71719, 40.17886], [71.73054, 40.14818], [71.82646, 40.21872], [71.85002, 40.25647], [72.05464, 40.27586], [71.96401, 40.31907], [72.18648, 40.49893], [72.24368, 40.46091], [72.40346, 40.4007], [72.44191, 40.48222], [72.41513, 40.50856], [72.38384, 40.51535], [72.41714, 40.55736], [72.34406, 40.60144], [72.40517, 40.61917], [72.47795, 40.5532], [72.66713, 40.5219], [72.66713, 40.59076], [72.69579, 40.59778], [72.73995, 40.58409], [72.74768, 40.58051], [72.74862, 40.57131], [72.75982, 40.57273], [72.74894, 40.59592], [72.74866, 40.60873], [72.80137, 40.67856], [72.84754, 40.67229], [72.85372, 40.7116], [72.8722, 40.71111], [72.93296, 40.73089], [72.99133, 40.76457], [73.0612, 40.76678], [73.13412, 40.79122], [73.13267, 40.83512], [73.01869, 40.84681], [72.94454, 40.8094], [72.84291, 40.85512], [72.68157, 40.84942], [72.59136, 40.86947], [72.55109, 40.96046], [72.48742, 40.97136], [72.45206, 41.03018], [72.38511, 41.02785], [72.36138, 41.04384], [72.34757, 41.06104], [72.34026, 41.04539], [72.324, 41.03381], [72.18339, 40.99571], [72.17594, 41.02377], [72.21061, 41.05607], [72.1792, 41.10621], [72.14864, 41.13363], [72.17594, 41.15522], [72.16433, 41.16483], [72.10745, 41.15483], [72.07249, 41.11739], [71.85964, 41.19081], [71.91457, 41.2982], [71.83914, 41.3546], [71.76625, 41.4466], [71.71132, 41.43012], [71.73054, 41.54713], [71.65914, 41.49599], [71.6787, 41.42111], [71.57227, 41.29175], [71.46688, 41.31883], [71.43814, 41.19644], [71.46148, 41.13958], [71.40198, 41.09436], [71.34877, 41.16807], [71.27187, 41.11015], [71.25813, 41.18796], [71.11806, 41.15359], [71.02193, 41.19494], [70.9615, 41.16393], [70.86263, 41.23833], [70.77885, 41.24813], [70.78572, 41.36419], [70.67586, 41.47953], [70.48909, 41.40335], [70.17682, 41.5455], [70.69777, 41.92554], [71.28719, 42.18033], [71.13263, 42.28356], [70.94483, 42.26238], [69.49545, 41.545], [69.45751, 41.56863], [69.39485, 41.51518], [69.45081, 41.46246], [69.37468, 41.46555], [69.35554, 41.47211], [69.29778, 41.43673], [69.25059, 41.46693], [69.23332, 41.45847], [69.22671, 41.46298], [69.20439, 41.45391], [69.18528, 41.45175], [69.17701, 41.43769], [69.15137, 41.43078], [69.05006, 41.36183], [69.01308, 41.22804], [68.7217, 41.05025], [68.73945, 40.96989], [68.65662, 40.93861], [68.62221, 41.03019], [68.49983, 40.99669], [68.58444, 40.91447], [68.63, 40.59358], [68.49983, 40.56437], [67.96736, 40.83798], [68.1271, 41.0324], [68.08273, 41.08148], [67.98511, 41.02794], [67.9644, 41.14611], [66.69129, 41.1311], [66.53302, 41.87388], [66.00546, 41.94455], [66.09482, 42.93426], [65.85194, 42.85481]], [[70.68112, 40.90612], [70.6721, 40.90555], [70.57501, 40.98941], [70.54223, 40.98787], [70.56077, 41.00642], [70.6158, 40.97661], [70.68112, 40.90612]]], [[[71.21139, 40.03369], [71.12218, 40.03052], [71.06305, 40.1771], [71.00236, 40.18154], [71.01035, 40.05481], [71.11037, 40.01984], [71.11668, 39.99291], [71.09063, 39.99], [71.10501, 39.95568], [71.04979, 39.89808], [71.10531, 39.91354], [71.16101, 39.88423], [71.23067, 39.93581], [71.1427, 39.95026], [71.21139, 40.03369]]], [[[71.86463, 39.98598], [71.78838, 40.01404], [71.71511, 39.96348], [71.7504, 39.93701], [71.84316, 39.95582], [71.86463, 39.98598]]]]
27305           }
27306         }, {
27307           type: "Feature",
27308           properties: {
27309             iso1A2: "VA",
27310             iso1A3: "VAT",
27311             iso1N3: "336",
27312             wikidata: "Q237",
27313             nameEn: "Vatican City",
27314             aliases: ["Holy See"],
27315             groups: ["039", "150"],
27316             callingCodes: ["379", "39 06"]
27317           },
27318           geometry: {
27319             type: "MultiPolygon",
27320             coordinates: [[[[12.45181, 41.90056], [12.45446, 41.90028], [12.45435, 41.90143], [12.45626, 41.90172], [12.45691, 41.90125], [12.4577, 41.90115], [12.45834, 41.90174], [12.45826, 41.90281], [12.45755, 41.9033], [12.45762, 41.9058], [12.45561, 41.90629], [12.45543, 41.90738], [12.45091, 41.90625], [12.44984, 41.90545], [12.44815, 41.90326], [12.44582, 41.90194], [12.44834, 41.90095], [12.45181, 41.90056]]]]
27321           }
27322         }, {
27323           type: "Feature",
27324           properties: {
27325             iso1A2: "VC",
27326             iso1A3: "VCT",
27327             iso1N3: "670",
27328             wikidata: "Q757",
27329             nameEn: "St. Vincent and the Grenadines",
27330             aliases: ["WV"],
27331             groups: ["029", "003", "419", "019", "UN"],
27332             driveSide: "left",
27333             roadSpeedUnit: "mph",
27334             callingCodes: ["1 784"]
27335           },
27336           geometry: {
27337             type: "MultiPolygon",
27338             coordinates: [[[[-62.64026, 12.69984], [-59.94058, 12.34011], [-61.69315, 14.26451], [-62.64026, 12.69984]]]]
27339           }
27340         }, {
27341           type: "Feature",
27342           properties: {
27343             iso1A2: "VE",
27344             iso1A3: "VEN",
27345             iso1N3: "862",
27346             wikidata: "Q717",
27347             nameEn: "Venezuela",
27348             aliases: ["YV"],
27349             groups: ["005", "419", "019", "UN"],
27350             callingCodes: ["58"]
27351           },
27352           geometry: {
27353             type: "MultiPolygon",
27354             coordinates: [[[[-71.22331, 13.01387], [-70.92579, 11.96275], [-71.3275, 11.85], [-71.9675, 11.65536], [-72.24983, 11.14138], [-72.4767, 11.1117], [-72.88002, 10.44309], [-72.98085, 9.85253], [-73.36905, 9.16636], [-73.02119, 9.27584], [-72.94052, 9.10663], [-72.77415, 9.10165], [-72.65474, 8.61428], [-72.4042, 8.36513], [-72.36987, 8.19976], [-72.35163, 8.01163], [-72.39137, 8.03534], [-72.47213, 7.96106], [-72.48801, 7.94329], [-72.48183, 7.92909], [-72.47042, 7.92306], [-72.45806, 7.91141], [-72.46183, 7.90682], [-72.44454, 7.86031], [-72.46763, 7.79518], [-72.47827, 7.65604], [-72.45321, 7.57232], [-72.47415, 7.48928], [-72.43132, 7.40034], [-72.19437, 7.37034], [-72.04895, 7.03837], [-71.82441, 7.04314], [-71.44118, 7.02116], [-71.42212, 7.03854], [-71.37234, 7.01588], [-71.03941, 6.98163], [-70.7596, 7.09799], [-70.10716, 6.96516], [-69.41843, 6.1072], [-67.60654, 6.2891], [-67.4625, 6.20625], [-67.43513, 5.98835], [-67.58558, 5.84537], [-67.63914, 5.64963], [-67.59141, 5.5369], [-67.83341, 5.31104], [-67.85358, 4.53249], [-67.62671, 3.74303], [-67.50067, 3.75812], [-67.30945, 3.38393], [-67.85862, 2.86727], [-67.85862, 2.79173], [-67.65696, 2.81691], [-67.21967, 2.35778], [-66.85795, 1.22998], [-66.28507, 0.74585], [-65.6727, 1.01353], [-65.50158, 0.92086], [-65.57288, 0.62856], [-65.11657, 1.12046], [-64.38932, 1.5125], [-64.34654, 1.35569], [-64.08274, 1.64792], [-64.06135, 1.94722], [-63.39827, 2.16098], [-63.39114, 2.4317], [-64.0257, 2.48156], [-64.02908, 2.79797], [-64.48379, 3.7879], [-64.84028, 4.24665], [-64.72977, 4.28931], [-64.57648, 4.12576], [-64.14512, 4.12932], [-63.99183, 3.90172], [-63.86082, 3.94796], [-63.70218, 3.91417], [-63.67099, 4.01731], [-63.50611, 3.83592], [-63.42233, 3.89995], [-63.4464, 3.9693], [-63.21111, 3.96219], [-62.98296, 3.59935], [-62.7655, 3.73099], [-62.74411, 4.03331], [-62.57656, 4.04754], [-62.44822, 4.18621], [-62.13094, 4.08309], [-61.54629, 4.2822], [-61.48569, 4.43149], [-61.29675, 4.44216], [-61.31457, 4.54167], [-61.15703, 4.49839], [-60.98303, 4.54167], [-60.86539, 4.70512], [-60.5802, 4.94312], [-60.73204, 5.20931], [-61.4041, 5.95304], [-61.15058, 6.19558], [-61.20762, 6.58174], [-61.13632, 6.70922], [-60.54873, 6.8631], [-60.39419, 6.94847], [-60.28074, 7.1162], [-60.44116, 7.20817], [-60.54098, 7.14804], [-60.63367, 7.25061], [-60.59802, 7.33194], [-60.71923, 7.55817], [-60.64793, 7.56877], [-60.51959, 7.83373], [-60.38056, 7.8302], [-60.02407, 8.04557], [-59.97059, 8.20791], [-59.83156, 8.23261], [-59.80661, 8.28906], [-59.85562, 8.35213], [-59.98508, 8.53046], [-59.54058, 8.6862], [-60.89962, 9.81445], [-62.08693, 10.04435], [-61.62505, 11.18974], [-63.73917, 11.92623], [-63.19938, 16.44103], [-67.89186, 12.4116], [-68.01417, 11.77722], [-68.33524, 11.78151], [-68.99639, 11.79035], [-71.22331, 13.01387]]]]
27355           }
27356         }, {
27357           type: "Feature",
27358           properties: {
27359             iso1A2: "VG",
27360             iso1A3: "VGB",
27361             iso1N3: "092",
27362             wikidata: "Q25305",
27363             nameEn: "British Virgin Islands",
27364             country: "GB",
27365             groups: ["BOTS", "029", "003", "419", "019", "UN"],
27366             driveSide: "left",
27367             roadSpeedUnit: "mph",
27368             roadHeightUnit: "ft",
27369             callingCodes: ["1 284"]
27370           },
27371           geometry: {
27372             type: "MultiPolygon",
27373             coordinates: [[[[-64.47127, 17.55688], [-63.88746, 19.15706], [-65.02435, 18.73231], [-64.86027, 18.39056], [-64.64673, 18.36549], [-64.47127, 17.55688]]]]
27374           }
27375         }, {
27376           type: "Feature",
27377           properties: {
27378             iso1A2: "VI",
27379             iso1A3: "VIR",
27380             iso1N3: "850",
27381             wikidata: "Q11703",
27382             nameEn: "United States Virgin Islands",
27383             aliases: ["US-VI"],
27384             country: "US",
27385             groups: ["Q1352230", "029", "003", "419", "019", "UN"],
27386             driveSide: "left",
27387             roadSpeedUnit: "mph",
27388             roadHeightUnit: "ft",
27389             callingCodes: ["1 340"]
27390           },
27391           geometry: {
27392             type: "MultiPolygon",
27393             coordinates: [[[[-65.02435, 18.73231], [-65.27974, 17.56928], [-64.47127, 17.55688], [-64.64673, 18.36549], [-64.86027, 18.39056], [-65.02435, 18.73231]]]]
27394           }
27395         }, {
27396           type: "Feature",
27397           properties: {
27398             iso1A2: "VN",
27399             iso1A3: "VNM",
27400             iso1N3: "704",
27401             wikidata: "Q881",
27402             nameEn: "Vietnam",
27403             groups: ["035", "142", "UN"],
27404             callingCodes: ["84"]
27405           },
27406           geometry: {
27407             type: "MultiPolygon",
27408             coordinates: [[[[108.10003, 21.47338], [108.0569, 21.53604], [108.02926, 21.54997], [107.97932, 21.54503], [107.97383, 21.53961], [107.97074, 21.54072], [107.96774, 21.53601], [107.95232, 21.5388], [107.92652, 21.58906], [107.90006, 21.5905], [107.86114, 21.65128], [107.80355, 21.66141], [107.66967, 21.60787], [107.56537, 21.61945], [107.54047, 21.5934], [107.49065, 21.59774], [107.49532, 21.62958], [107.47197, 21.6672], [107.41593, 21.64839], [107.38636, 21.59774], [107.35989, 21.60063], [107.35834, 21.6672], [107.29296, 21.74674], [107.24625, 21.7077], [107.20734, 21.71493], [107.10771, 21.79879], [107.02615, 21.81981], [107.00964, 21.85948], [107.06101, 21.88982], [107.05634, 21.92303], [106.99252, 21.95191], [106.97228, 21.92592], [106.92714, 21.93459], [106.9178, 21.97357], [106.81038, 21.97934], [106.74345, 22.00965], [106.72551, 21.97923], [106.69276, 21.96013], [106.68274, 21.99811], [106.70142, 22.02409], [106.6983, 22.15102], [106.67495, 22.1885], [106.69986, 22.22309], [106.6516, 22.33977], [106.55976, 22.34841], [106.57221, 22.37], [106.55665, 22.46498], [106.58395, 22.474], [106.61269, 22.60301], [106.65316, 22.5757], [106.71698, 22.58432], [106.72321, 22.63606], [106.76293, 22.73491], [106.82404, 22.7881], [106.83685, 22.8098], [106.81271, 22.8226], [106.78422, 22.81532], [106.71128, 22.85982], [106.71387, 22.88296], [106.6734, 22.89587], [106.6516, 22.86862], [106.60179, 22.92884], [106.55976, 22.92311], [106.51306, 22.94891], [106.49749, 22.91164], [106.34961, 22.86718], [106.27022, 22.87722], [106.19705, 22.98475], [106.00179, 22.99049], [105.99568, 22.94178], [105.90119, 22.94168], [105.8726, 22.92756], [105.72382, 23.06641], [105.57594, 23.075], [105.56037, 23.16806], [105.49966, 23.20669], [105.42805, 23.30824], [105.40782, 23.28107], [105.32376, 23.39684], [105.22569, 23.27249], [105.17276, 23.28679], [105.11672, 23.25247], [105.07002, 23.26248], [104.98712, 23.19176], [104.96532, 23.20463], [104.9486, 23.17235], [104.91435, 23.18666], [104.87992, 23.17141], [104.87382, 23.12854], [104.79478, 23.12934], [104.8334, 23.01484], [104.86765, 22.95178], [104.84942, 22.93631], [104.77114, 22.90017], [104.72755, 22.81984], [104.65283, 22.83419], [104.60457, 22.81841], [104.58122, 22.85571], [104.47225, 22.75813], [104.35593, 22.69353], [104.25683, 22.76534], [104.27084, 22.8457], [104.11384, 22.80363], [104.03734, 22.72945], [104.01088, 22.51823], [103.99247, 22.51958], [103.97384, 22.50634], [103.96783, 22.51173], [103.96352, 22.50584], [103.95191, 22.5134], [103.94513, 22.52553], [103.93286, 22.52703], [103.87904, 22.56683], [103.64506, 22.79979], [103.56255, 22.69499], [103.57812, 22.65764], [103.52675, 22.59155], [103.43646, 22.70648], [103.43179, 22.75816], [103.32282, 22.8127], [103.28079, 22.68063], [103.18895, 22.64471], [103.15782, 22.59873], [103.17961, 22.55705], [103.07843, 22.50097], [103.0722, 22.44775], [102.9321, 22.48659], [102.8636, 22.60735], [102.60675, 22.73376], [102.57095, 22.7036], [102.51802, 22.77969], [102.46665, 22.77108], [102.42618, 22.69212], [102.38415, 22.67919], [102.41061, 22.64184], [102.25339, 22.4607], [102.26428, 22.41321], [102.16621, 22.43336], [102.14099, 22.40092], [102.18712, 22.30403], [102.51734, 22.02676], [102.49092, 21.99002], [102.62301, 21.91447], [102.67145, 21.65894], [102.74189, 21.66713], [102.82115, 21.73667], [102.81894, 21.83888], [102.85637, 21.84501], [102.86077, 21.71213], [102.97965, 21.74076], [102.98846, 21.58936], [102.86297, 21.4255], [102.94223, 21.46034], [102.88939, 21.3107], [102.80794, 21.25736], [102.89825, 21.24707], [102.97745, 21.05821], [103.03469, 21.05821], [103.12055, 20.89994], [103.21497, 20.89832], [103.38032, 20.79501], [103.45737, 20.82382], [103.68633, 20.66324], [103.73478, 20.6669], [103.82282, 20.8732], [103.98024, 20.91531], [104.11121, 20.96779], [104.27412, 20.91433], [104.63957, 20.6653], [104.38199, 20.47155], [104.40621, 20.3849], [104.47886, 20.37459], [104.66158, 20.47774], [104.72102, 20.40554], [104.62195, 20.36633], [104.61315, 20.24452], [104.86852, 20.14121], [104.91695, 20.15567], [104.9874, 20.09573], [104.8465, 19.91783], [104.8355, 19.80395], [104.68359, 19.72729], [104.64837, 19.62365], [104.53169, 19.61743], [104.41281, 19.70035], [104.23229, 19.70242], [104.06498, 19.66926], [104.05617, 19.61743], [104.10832, 19.51575], [104.06058, 19.43484], [103.87125, 19.31854], [104.5361, 18.97747], [104.64617, 18.85668], [105.12829, 18.70453], [105.19654, 18.64196], [105.1327, 18.58355], [105.10408, 18.43533], [105.15942, 18.38691], [105.38366, 18.15315], [105.46292, 18.22008], [105.64784, 17.96687], [105.60381, 17.89356], [105.76612, 17.67147], [105.85744, 17.63221], [106.09019, 17.36399], [106.18991, 17.28227], [106.24444, 17.24714], [106.29287, 17.3018], [106.31929, 17.20509], [106.43597, 17.01362], [106.50862, 16.9673], [106.55045, 17.0031], [106.54824, 16.92729], [106.51963, 16.92097], [106.52183, 16.87884], [106.55265, 16.86831], [106.55485, 16.68704], [106.59013, 16.62259], [106.58267, 16.6012], [106.61477, 16.60713], [106.66052, 16.56892], [106.65832, 16.47816], [106.74418, 16.41904], [106.84104, 16.55415], [106.88727, 16.52671], [106.88067, 16.43594], [106.96638, 16.34938], [106.97385, 16.30204], [107.02597, 16.31132], [107.09091, 16.3092], [107.15035, 16.26271], [107.14595, 16.17816], [107.25822, 16.13587], [107.33968, 16.05549], [107.44975, 16.08511], [107.46296, 16.01106], [107.39471, 15.88829], [107.34188, 15.89464], [107.21419, 15.83747], [107.21859, 15.74638], [107.27143, 15.71459], [107.27583, 15.62769], [107.34408, 15.62345], [107.3815, 15.49832], [107.50699, 15.48771], [107.53341, 15.40496], [107.62367, 15.42193], [107.60605, 15.37524], [107.62587, 15.2266], [107.58844, 15.20111], [107.61926, 15.13949], [107.61486, 15.0566], [107.46516, 15.00982], [107.48277, 14.93751], [107.59285, 14.87795], [107.51579, 14.79282], [107.54361, 14.69092], [107.55371, 14.628], [107.52102, 14.59034], [107.52569, 14.54665], [107.48521, 14.40346], [107.44941, 14.41552], [107.39493, 14.32655], [107.40427, 14.24509], [107.33577, 14.11832], [107.37158, 14.07906], [107.35757, 14.02319], [107.38247, 13.99147], [107.44318, 13.99751], [107.46498, 13.91593], [107.45252, 13.78897], [107.53503, 13.73908], [107.61909, 13.52577], [107.62843, 13.3668], [107.49144, 13.01215], [107.49611, 12.88926], [107.55993, 12.7982], [107.5755, 12.52177], [107.55059, 12.36824], [107.4463, 12.29373], [107.42917, 12.24657], [107.34511, 12.33327], [107.15831, 12.27547], [106.99953, 12.08983], [106.92325, 12.06548], [106.79405, 12.0807], [106.70687, 11.96956], [106.4111, 11.97413], [106.4687, 11.86751], [106.44068, 11.86294], [106.44535, 11.8279], [106.41577, 11.76999], [106.45158, 11.68616], [106.44691, 11.66787], [106.37219, 11.69836], [106.30525, 11.67549], [106.26478, 11.72122], [106.18539, 11.75171], [106.13158, 11.73283], [106.06708, 11.77761], [106.02038, 11.77457], [106.00792, 11.7197], [105.95188, 11.63738], [105.88962, 11.67854], [105.8507, 11.66635], [105.80867, 11.60536], [105.81645, 11.56876], [105.87328, 11.55953], [105.88962, 11.43605], [105.86782, 11.28343], [106.10444, 11.07879], [106.1527, 11.10476], [106.1757, 11.07301], [106.20095, 10.97795], [106.14301, 10.98176], [106.18539, 10.79451], [106.06708, 10.8098], [105.94535, 10.9168], [105.93403, 10.83853], [105.84603, 10.85873], [105.86376, 10.89839], [105.77751, 11.03671], [105.50045, 10.94586], [105.42884, 10.96878], [105.34011, 10.86179], [105.11449, 10.96332], [105.08326, 10.95656], [105.02722, 10.89236], [105.09571, 10.72722], [104.95094, 10.64003], [104.87933, 10.52833], [104.59018, 10.53073], [104.49869, 10.4057], [104.47963, 10.43046], [104.43778, 10.42386], [103.99198, 10.48391], [102.47649, 9.66162], [104.81582, 8.03101], [109.55486, 8.10026], [111.60491, 13.57105], [108.00365, 17.98159], [108.10003, 21.47338]]]]
27409           }
27410         }, {
27411           type: "Feature",
27412           properties: {
27413             iso1A2: "VU",
27414             iso1A3: "VUT",
27415             iso1N3: "548",
27416             wikidata: "Q686",
27417             nameEn: "Vanuatu",
27418             groups: ["054", "009", "UN"],
27419             callingCodes: ["678"]
27420           },
27421           geometry: {
27422             type: "MultiPolygon",
27423             coordinates: [[[[156.73836, -14.50464], [174.245, -23.1974], [172.71443, -12.01327], [156.73836, -14.50464]]]]
27424           }
27425         }, {
27426           type: "Feature",
27427           properties: {
27428             iso1A2: "WF",
27429             iso1A3: "WLF",
27430             iso1N3: "876",
27431             wikidata: "Q35555",
27432             nameEn: "Wallis and Futuna",
27433             country: "FR",
27434             groups: ["Q1451600", "061", "009", "UN"],
27435             callingCodes: ["681"]
27436           },
27437           geometry: {
27438             type: "MultiPolygon",
27439             coordinates: [[[[-178.66551, -14.32452], [-176.76826, -14.95183], [-175.59809, -12.61507], [-178.66551, -14.32452]]]]
27440           }
27441         }, {
27442           type: "Feature",
27443           properties: {
27444             iso1A2: "WS",
27445             iso1A3: "WSM",
27446             iso1N3: "882",
27447             wikidata: "Q683",
27448             nameEn: "Samoa",
27449             groups: ["061", "009", "UN"],
27450             driveSide: "left",
27451             callingCodes: ["685"]
27452           },
27453           geometry: {
27454             type: "MultiPolygon",
27455             coordinates: [[[[-173.74402, -14.26669], [-170.99605, -15.1275], [-171.39864, -10.21587], [-173.74402, -14.26669]]]]
27456           }
27457         }, {
27458           type: "Feature",
27459           properties: {
27460             iso1A2: "XK",
27461             iso1A3: "XKX",
27462             wikidata: "Q1246",
27463             nameEn: "Kosovo",
27464             aliases: ["KV"],
27465             groups: ["039", "150"],
27466             isoStatus: "usrAssn",
27467             callingCodes: ["383"]
27468           },
27469           geometry: {
27470             type: "MultiPolygon",
27471             coordinates: [[[[21.39045, 42.74888], [21.44047, 42.87276], [21.36941, 42.87397], [21.32974, 42.90424], [21.2719, 42.8994], [21.23534, 42.95523], [21.23877, 43.00848], [21.2041, 43.02277], [21.16734, 42.99694], [21.14465, 43.11089], [21.08952, 43.13471], [21.05378, 43.10707], [21.00749, 43.13984], [20.96287, 43.12416], [20.83727, 43.17842], [20.88685, 43.21697], [20.82145, 43.26769], [20.73811, 43.25068], [20.68688, 43.21335], [20.59929, 43.20492], [20.69515, 43.09641], [20.64557, 43.00826], [20.59929, 43.01067], [20.48692, 42.93208], [20.53484, 42.8885], [20.43734, 42.83157], [20.40594, 42.84853], [20.35692, 42.8335], [20.27869, 42.81945], [20.2539, 42.76245], [20.04898, 42.77701], [20.02088, 42.74789], [20.02915, 42.71147], [20.0969, 42.65559], [20.07761, 42.55582], [20.17127, 42.50469], [20.21797, 42.41237], [20.24399, 42.32168], [20.34479, 42.32656], [20.3819, 42.3029], [20.48857, 42.25444], [20.56955, 42.12097], [20.55633, 42.08173], [20.59434, 42.03879], [20.63069, 41.94913], [20.57946, 41.91593], [20.59524, 41.8818], [20.68523, 41.85318], [20.76786, 41.91839], [20.75464, 42.05229], [21.11491, 42.20794], [21.16614, 42.19815], [21.22728, 42.08909], [21.31983, 42.10993], [21.29913, 42.13954], [21.30496, 42.1418], [21.38428, 42.24465], [21.43882, 42.23609], [21.43882, 42.2789], [21.50823, 42.27156], [21.52145, 42.24465], [21.58992, 42.25915], [21.56772, 42.30946], [21.5264, 42.33634], [21.53467, 42.36809], [21.57021, 42.3647], [21.59029, 42.38042], [21.62887, 42.37664], [21.64209, 42.41081], [21.62556, 42.45106], [21.7035, 42.51899], [21.70522, 42.54176], [21.7327, 42.55041], [21.75672, 42.62695], [21.79413, 42.65923], [21.75025, 42.70125], [21.6626, 42.67813], [21.58755, 42.70418], [21.59154, 42.72643], [21.47498, 42.74695], [21.39045, 42.74888]]]]
27472           }
27473         }, {
27474           type: "Feature",
27475           properties: {
27476             iso1A2: "YE",
27477             iso1A3: "YEM",
27478             iso1N3: "887",
27479             wikidata: "Q805",
27480             nameEn: "Yemen",
27481             groups: ["145", "142", "UN"],
27482             callingCodes: ["967"]
27483           },
27484           geometry: {
27485             type: "MultiPolygon",
27486             coordinates: [[[[57.49095, 8.14549], [52.81185, 17.28568], [52.74267, 17.29519], [52.78009, 17.35124], [52.00311, 19.00083], [49.04884, 18.59899], [48.19996, 18.20584], [47.58351, 17.50366], [47.48245, 17.10808], [47.00571, 16.94765], [46.76494, 17.29151], [46.31018, 17.20464], [44.50126, 17.47475], [43.70631, 17.35762], [43.43005, 17.56148], [43.29185, 17.53224], [43.22533, 17.38343], [43.32653, 17.31179], [43.20156, 17.25901], [43.17787, 17.14717], [43.23967, 17.03428], [43.18233, 17.02673], [43.1813, 16.98438], [43.19328, 16.94703], [43.1398, 16.90696], [43.18338, 16.84852], [43.22012, 16.83932], [43.22956, 16.80613], [43.24801, 16.80613], [43.26303, 16.79479], [43.25857, 16.75304], [43.21325, 16.74416], [43.22066, 16.65179], [43.15274, 16.67248], [43.11601, 16.53166], [42.97215, 16.51093], [42.94351, 16.49467], [42.94625, 16.39721], [42.76801, 16.40371], [42.15205, 16.40211], [40.99158, 15.81743], [43.29075, 12.79154], [43.32909, 12.59711], [43.90659, 12.3823], [51.12877, 12.56479], [57.49095, 8.14549]]]]
27487           }
27488         }, {
27489           type: "Feature",
27490           properties: {
27491             iso1A2: "YT",
27492             iso1A3: "MYT",
27493             iso1N3: "175",
27494             wikidata: "Q17063",
27495             nameEn: "Mayotte",
27496             country: "FR",
27497             groups: ["Q3320166", "EU", "014", "202", "002", "UN"],
27498             callingCodes: ["262"]
27499           },
27500           geometry: {
27501             type: "MultiPolygon",
27502             coordinates: [[[[43.28731, -13.97126], [45.54824, -13.22353], [45.4971, -11.75965], [43.28731, -13.97126]]]]
27503           }
27504         }, {
27505           type: "Feature",
27506           properties: {
27507             iso1A2: "ZA",
27508             iso1A3: "ZAF",
27509             iso1N3: "710",
27510             wikidata: "Q258",
27511             nameEn: "South Africa",
27512             groups: ["018", "202", "002", "UN"],
27513             driveSide: "left",
27514             callingCodes: ["27"]
27515           },
27516           geometry: {
27517             type: "MultiPolygon",
27518             coordinates: [[[[31.30611, -22.422], [31.16344, -22.32599], [31.08932, -22.34884], [30.86696, -22.28907], [30.6294, -22.32599], [30.48686, -22.31368], [30.38614, -22.34533], [30.28351, -22.35587], [30.2265, -22.2961], [30.13147, -22.30841], [29.92242, -22.19408], [29.76848, -22.14128], [29.64609, -22.12917], [29.37703, -22.19581], [29.21955, -22.17771], [29.18974, -22.18599], [29.15268, -22.21399], [29.10881, -22.21202], [29.0151, -22.22907], [28.91889, -22.44299], [28.63287, -22.55887], [28.34874, -22.5694], [28.04562, -22.8394], [28.04752, -22.90243], [27.93729, -22.96194], [27.93539, -23.04941], [27.74154, -23.2137], [27.6066, -23.21894], [27.52393, -23.37952], [27.33768, -23.40917], [26.99749, -23.65486], [26.84165, -24.24885], [26.51667, -24.47219], [26.46346, -24.60358], [26.39409, -24.63468], [25.8515, -24.75727], [25.84295, -24.78661], [25.88571, -24.87802], [25.72702, -25.25503], [25.69661, -25.29284], [25.6643, -25.4491], [25.58543, -25.6343], [25.33076, -25.76616], [25.12266, -25.75931], [25.01718, -25.72507], [24.8946, -25.80723], [24.67319, -25.81749], [24.44703, -25.73021], [24.36531, -25.773], [24.18287, -25.62916], [23.9244, -25.64286], [23.47588, -25.29971], [23.03497, -25.29971], [22.86012, -25.50572], [22.70808, -25.99186], [22.56365, -26.19668], [22.41921, -26.23078], [22.21206, -26.3773], [22.06192, -26.61882], [21.90703, -26.66808], [21.83291, -26.65959], [21.77114, -26.69015], [21.7854, -26.79199], [21.69322, -26.86152], [21.37869, -26.82083], [21.13353, -26.86661], [20.87031, -26.80047], [20.68596, -26.9039], [20.63275, -26.78181], [20.61754, -26.4692], [20.86081, -26.14892], [20.64795, -25.47827], [20.29826, -24.94869], [20.03678, -24.81004], [20.02809, -24.78725], [19.99817, -24.76768], [19.99882, -28.42622], [18.99885, -28.89165], [17.4579, -28.68718], [17.15405, -28.08573], [16.90446, -28.057], [16.59922, -28.53246], [16.46592, -28.57126], [16.45332, -28.63117], [12.51595, -32.27486], [38.88176, -48.03306], [34.51034, -26.91792], [32.35222, -26.86027], [32.29584, -26.852], [32.22302, -26.84136], [32.19409, -26.84032], [32.13315, -26.84345], [32.09664, -26.80721], [32.00893, -26.8096], [31.97463, -27.11057], [31.97592, -27.31675], [31.49834, -27.31549], [31.15027, -27.20151], [30.96088, -27.0245], [30.97757, -26.92706], [30.88826, -26.79622], [30.81101, -26.84722], [30.78927, -26.48271], [30.95819, -26.26303], [31.13073, -25.91558], [31.31237, -25.7431], [31.4175, -25.71886], [31.86881, -25.99973], [31.974, -25.95387], [31.92649, -25.84216], [32.00631, -25.65044], [31.97875, -25.46356], [32.01676, -25.38117], [32.03196, -25.10785], [31.9835, -24.29983], [31.90368, -24.18892], [31.87707, -23.95293], [31.77445, -23.90082], [31.70223, -23.72695], [31.67942, -23.60858], [31.56539, -23.47268], [31.55779, -23.176], [31.30611, -22.422]], [[29.33204, -29.45598], [29.28545, -29.58456], [29.12553, -29.76266], [29.16548, -29.91706], [28.9338, -30.05072], [28.80222, -30.10579], [28.68627, -30.12885], [28.399, -30.1592], [28.2319, -30.28476], [28.12073, -30.68072], [27.74814, -30.60635], [27.69467, -30.55862], [27.67819, -30.53437], [27.6521, -30.51707], [27.62137, -30.50509], [27.56781, -30.44562], [27.56901, -30.42504], [27.45452, -30.32239], [27.38108, -30.33456], [27.36649, -30.27246], [27.37293, -30.19401], [27.40778, -30.14577], [27.32555, -30.14785], [27.29603, -30.05473], [27.22719, -30.00718], [27.09489, -29.72796], [27.01016, -29.65439], [27.33464, -29.48161], [27.4358, -29.33465], [27.47254, -29.31968], [27.45125, -29.29708], [27.48679, -29.29349], [27.54258, -29.25575], [27.5158, -29.2261], [27.55974, -29.18954], [27.75458, -28.89839], [27.8907, -28.91612], [27.88933, -28.88156], [27.9392, -28.84864], [27.98675, -28.8787], [28.02503, -28.85991], [28.1317, -28.7293], [28.2348, -28.69471], [28.30518, -28.69531], [28.40612, -28.6215], [28.65091, -28.57025], [28.68043, -28.58744], [29.40524, -29.21246], [29.44883, -29.3772], [29.33204, -29.45598]]]]
27519           }
27520         }, {
27521           type: "Feature",
27522           properties: {
27523             iso1A2: "ZM",
27524             iso1A3: "ZMB",
27525             iso1N3: "894",
27526             wikidata: "Q953",
27527             nameEn: "Zambia",
27528             groups: ["014", "202", "002", "UN"],
27529             driveSide: "left",
27530             callingCodes: ["260"]
27531           },
27532           geometry: {
27533             type: "MultiPolygon",
27534             coordinates: [[[[32.95389, -9.40138], [32.76233, -9.31963], [32.75611, -9.28583], [32.53661, -9.24281], [32.49147, -9.14754], [32.43543, -9.11988], [32.25486, -9.13371], [32.16146, -9.05993], [32.08206, -9.04609], [31.98866, -9.07069], [31.94196, -9.02303], [31.94663, -8.93846], [31.81587, -8.88618], [31.71158, -8.91386], [31.57147, -8.81388], [31.57147, -8.70619], [31.37533, -8.60769], [31.00796, -8.58615], [30.79243, -8.27382], [28.88917, -8.4831], [28.9711, -8.66935], [28.38526, -9.23393], [28.36562, -9.30091], [28.52636, -9.35379], [28.51627, -9.44726], [28.56208, -9.49122], [28.68532, -9.78], [28.62795, -9.92942], [28.65032, -10.65133], [28.37241, -11.57848], [28.48357, -11.87532], [29.18592, -12.37921], [29.4992, -12.43843], [29.48404, -12.23604], [29.8139, -12.14898], [29.81551, -13.44683], [29.65078, -13.41844], [29.60531, -13.21685], [29.01918, -13.41353], [28.33199, -12.41375], [27.59932, -12.22123], [27.21025, -11.76157], [27.22541, -11.60323], [27.04351, -11.61312], [26.88687, -12.01868], [26.01777, -11.91488], [25.33058, -11.65767], [25.34069, -11.19707], [24.42612, -11.44975], [24.34528, -11.06816], [24.00027, -10.89356], [24.02603, -11.15368], [23.98804, -12.13149], [24.06672, -12.29058], [23.90937, -12.844], [24.03339, -12.99091], [21.97988, -13.00148], [22.00323, -16.18028], [22.17217, -16.50269], [23.20038, -17.47563], [23.47474, -17.62877], [24.23619, -17.47489], [24.32811, -17.49082], [24.38712, -17.46818], [24.5621, -17.52963], [24.70864, -17.49501], [25.00198, -17.58221], [25.26433, -17.79571], [25.51646, -17.86232], [25.6827, -17.81987], [25.85738, -17.91403], [25.85892, -17.97726], [26.08925, -17.98168], [26.0908, -17.93021], [26.21601, -17.88608], [26.55918, -17.99638], [26.68403, -18.07411], [26.74314, -18.0199], [26.89926, -17.98756], [27.14196, -17.81398], [27.30736, -17.60487], [27.61377, -17.34378], [27.62795, -17.24365], [27.83141, -16.96274], [28.73725, -16.5528], [28.76199, -16.51575], [28.81454, -16.48611], [28.8501, -16.04537], [28.9243, -15.93987], [29.01298, -15.93805], [29.21955, -15.76589], [29.4437, -15.68702], [29.8317, -15.6126], [30.35574, -15.6513], [30.41902, -15.62269], [30.22098, -14.99447], [33.24249, -14.00019], [33.16749, -13.93992], [33.07568, -13.98447], [33.02977, -14.05022], [32.99042, -13.95689], [32.88985, -13.82956], [32.79015, -13.80755], [32.76962, -13.77224], [32.84528, -13.71576], [32.7828, -13.64805], [32.68654, -13.64268], [32.66468, -13.60019], [32.68436, -13.55769], [32.73683, -13.57682], [32.84176, -13.52794], [32.86113, -13.47292], [33.0078, -13.19492], [32.98289, -13.12671], [33.02181, -12.88707], [32.96733, -12.88251], [32.94397, -12.76868], [33.05917, -12.59554], [33.18837, -12.61377], [33.28177, -12.54692], [33.37517, -12.54085], [33.54485, -12.35996], [33.47636, -12.32498], [33.3705, -12.34931], [33.25998, -12.14242], [33.33937, -11.91252], [33.32692, -11.59248], [33.24252, -11.59302], [33.23663, -11.40637], [33.29267, -11.43536], [33.29267, -11.3789], [33.39697, -11.15296], [33.25998, -10.88862], [33.28022, -10.84428], [33.47636, -10.78465], [33.70675, -10.56896], [33.54797, -10.36077], [33.53863, -10.20148], [33.31297, -10.05133], [33.37902, -9.9104], [33.36581, -9.81063], [33.31517, -9.82364], [33.2095, -9.61099], [33.12144, -9.58929], [33.10163, -9.66525], [33.05485, -9.61316], [33.00256, -9.63053], [33.00476, -9.5133], [32.95389, -9.40138]]]]
27535           }
27536         }, {
27537           type: "Feature",
27538           properties: {
27539             iso1A2: "ZW",
27540             iso1A3: "ZWE",
27541             iso1N3: "716",
27542             wikidata: "Q954",
27543             nameEn: "Zimbabwe",
27544             groups: ["014", "202", "002", "UN"],
27545             driveSide: "left",
27546             callingCodes: ["263"]
27547           },
27548           geometry: {
27549             type: "MultiPolygon",
27550             coordinates: [[[[30.41902, -15.62269], [30.35574, -15.6513], [29.8317, -15.6126], [29.4437, -15.68702], [29.21955, -15.76589], [29.01298, -15.93805], [28.9243, -15.93987], [28.8501, -16.04537], [28.81454, -16.48611], [28.76199, -16.51575], [28.73725, -16.5528], [27.83141, -16.96274], [27.62795, -17.24365], [27.61377, -17.34378], [27.30736, -17.60487], [27.14196, -17.81398], [26.89926, -17.98756], [26.74314, -18.0199], [26.68403, -18.07411], [26.55918, -17.99638], [26.21601, -17.88608], [26.0908, -17.93021], [26.08925, -17.98168], [25.85892, -17.97726], [25.85738, -17.91403], [25.6827, -17.81987], [25.51646, -17.86232], [25.26433, -17.79571], [25.23909, -17.90832], [25.31799, -18.07091], [25.39972, -18.12691], [25.53465, -18.39041], [25.68859, -18.56165], [25.79217, -18.6355], [25.82353, -18.82808], [25.94326, -18.90362], [25.99837, -19.02943], [25.96226, -19.08152], [26.17227, -19.53709], [26.72246, -19.92707], [27.21278, -20.08244], [27.29831, -20.28935], [27.28865, -20.49873], [27.69361, -20.48531], [27.72972, -20.51735], [27.69171, -21.08409], [27.91407, -21.31621], [28.01669, -21.57624], [28.29416, -21.59037], [28.49942, -21.66634], [28.58114, -21.63455], [29.07763, -21.81877], [29.04023, -21.85864], [29.02191, -21.90647], [29.02191, -21.95665], [29.04108, -22.00563], [29.08495, -22.04867], [29.14501, -22.07275], [29.1974, -22.07472], [29.24648, -22.05967], [29.3533, -22.18363], [29.37703, -22.19581], [29.64609, -22.12917], [29.76848, -22.14128], [29.92242, -22.19408], [30.13147, -22.30841], [30.2265, -22.2961], [30.28351, -22.35587], [30.38614, -22.34533], [30.48686, -22.31368], [30.6294, -22.32599], [30.86696, -22.28907], [31.08932, -22.34884], [31.16344, -22.32599], [31.30611, -22.422], [31.38336, -22.36919], [32.41234, -21.31246], [32.48236, -21.32873], [32.37115, -21.133], [32.51644, -20.91929], [32.48122, -20.63319], [32.55167, -20.56312], [32.66174, -20.56106], [32.85987, -20.27841], [32.85987, -20.16686], [32.93032, -20.03868], [33.01178, -20.02007], [33.06461, -19.77787], [32.95013, -19.67219], [32.84666, -19.68462], [32.84446, -19.48343], [32.78282, -19.47513], [32.77966, -19.36098], [32.85107, -19.29238], [32.87088, -19.09279], [32.84006, -19.0262], [32.72118, -19.02204], [32.69917, -18.94293], [32.73439, -18.92628], [32.70137, -18.84712], [32.82465, -18.77419], [32.9017, -18.7992], [32.95013, -18.69079], [32.88629, -18.58023], [32.88629, -18.51344], [33.02278, -18.4696], [33.03159, -18.35054], [32.94133, -17.99705], [33.0492, -17.60298], [32.98536, -17.55891], [32.96554, -17.48964], [33.0426, -17.3468], [33.00517, -17.30477], [32.96554, -17.11971], [32.84113, -16.92259], [32.91051, -16.89446], [32.97655, -16.70689], [32.78943, -16.70267], [32.69917, -16.66893], [32.71017, -16.59932], [32.42838, -16.4727], [32.28529, -16.43892], [32.02772, -16.43892], [31.91324, -16.41569], [31.90223, -16.34388], [31.67988, -16.19595], [31.42451, -16.15154], [31.30563, -16.01193], [31.13171, -15.98019], [30.97761, -16.05848], [30.91597, -15.99924], [30.42568, -15.9962], [30.41902, -15.62269]]]]
27551           }
27552         }];
27553         var borders_default = {
27554           type: type,
27555           features: features
27556         }; // src/country-coder.ts
27557
27558         var borders = borders_default;
27559         var whichPolygonGetter = {};
27560         var featuresByCode = {};
27561         var idFilterRegex = /(?=(?!^(and|the|of|el|la|de)$))(\b(and|the|of|el|la|de)\b)|[-_ .,'()&[\]/]/gi;
27562
27563         function canonicalID(id) {
27564           var s = id || "";
27565
27566           if (s.charAt(0) === ".") {
27567             return s.toUpperCase();
27568           } else {
27569             return s.replace(idFilterRegex, "").toUpperCase();
27570           }
27571         }
27572
27573         var levels = ["subterritory", "territory", "subcountryGroup", "country", "sharedLandform", "intermediateRegion", "subregion", "region", "subunion", "union", "unitedNations", "world"];
27574         loadDerivedDataAndCaches(borders);
27575
27576         function loadDerivedDataAndCaches(borders2) {
27577           var identifierProps = ["iso1A2", "iso1A3", "m49", "wikidata", "emojiFlag", "ccTLD", "nameEn"];
27578           var geometryFeatures = [];
27579
27580           for (var i in borders2.features) {
27581             var feature2 = borders2.features[i];
27582             feature2.properties.id = feature2.properties.iso1A2 || feature2.properties.m49 || feature2.properties.wikidata;
27583             loadM49(feature2);
27584             loadTLD(feature2);
27585             loadIsoStatus(feature2);
27586             loadLevel(feature2);
27587             loadGroups(feature2);
27588             loadFlag(feature2);
27589             cacheFeatureByIDs(feature2);
27590             if (feature2.geometry) geometryFeatures.push(feature2);
27591           }
27592
27593           for (var _i in borders2.features) {
27594             var _feature = borders2.features[_i];
27595             _feature.properties.groups = _feature.properties.groups.map(function (groupID) {
27596               return featuresByCode[groupID].properties.id;
27597             });
27598             loadMembersForGroupsOf(_feature);
27599           }
27600
27601           for (var _i2 in borders2.features) {
27602             var _feature2 = borders2.features[_i2];
27603             loadRoadSpeedUnit(_feature2);
27604             loadRoadHeightUnit(_feature2);
27605             loadDriveSide(_feature2);
27606             loadCallingCodes(_feature2);
27607             loadGroupGroups(_feature2);
27608           }
27609
27610           for (var _i3 in borders2.features) {
27611             var _feature3 = borders2.features[_i3];
27612
27613             _feature3.properties.groups.sort(function (groupID1, groupID2) {
27614               return levels.indexOf(featuresByCode[groupID1].properties.level) - levels.indexOf(featuresByCode[groupID2].properties.level);
27615             });
27616
27617             if (_feature3.properties.members) _feature3.properties.members.sort(function (id1, id2) {
27618               var diff = levels.indexOf(featuresByCode[id1].properties.level) - levels.indexOf(featuresByCode[id2].properties.level);
27619
27620               if (diff === 0) {
27621                 return borders2.features.indexOf(featuresByCode[id1]) - borders2.features.indexOf(featuresByCode[id2]);
27622               }
27623
27624               return diff;
27625             });
27626           }
27627
27628           var geometryOnlyCollection = {
27629             type: "FeatureCollection",
27630             features: geometryFeatures
27631           };
27632           whichPolygonGetter = whichPolygon_1(geometryOnlyCollection);
27633
27634           function loadGroups(feature2) {
27635             var props = feature2.properties;
27636
27637             if (!props.groups) {
27638               props.groups = [];
27639             }
27640
27641             if (feature2.geometry && props.country) {
27642               props.groups.push(props.country);
27643             }
27644
27645             if (props.m49 !== "001") {
27646               props.groups.push("001");
27647             }
27648           }
27649
27650           function loadM49(feature2) {
27651             var props = feature2.properties;
27652
27653             if (!props.m49 && props.iso1N3) {
27654               props.m49 = props.iso1N3;
27655             }
27656           }
27657
27658           function loadTLD(feature2) {
27659             var props = feature2.properties;
27660             if (props.level === "unitedNations") return;
27661
27662             if (!props.ccTLD && props.iso1A2) {
27663               props.ccTLD = "." + props.iso1A2.toLowerCase();
27664             }
27665           }
27666
27667           function loadIsoStatus(feature2) {
27668             var props = feature2.properties;
27669
27670             if (!props.isoStatus && props.iso1A2) {
27671               props.isoStatus = "official";
27672             }
27673           }
27674
27675           function loadLevel(feature2) {
27676             var props = feature2.properties;
27677             if (props.level) return;
27678
27679             if (!props.country) {
27680               props.level = "country";
27681             } else if (!props.iso1A2 || props.isoStatus === "official") {
27682               props.level = "territory";
27683             } else {
27684               props.level = "subterritory";
27685             }
27686           }
27687
27688           function loadGroupGroups(feature2) {
27689             var props = feature2.properties;
27690             if (feature2.geometry || !props.members) return;
27691             var featureLevelIndex = levels.indexOf(props.level);
27692             var sharedGroups = [];
27693
27694             var _loop = function _loop(_i4) {
27695               var memberID = props.members[_i4];
27696               var member = featuresByCode[memberID];
27697               var memberGroups = member.properties.groups.filter(function (groupID) {
27698                 return groupID !== feature2.properties.id && featureLevelIndex < levels.indexOf(featuresByCode[groupID].properties.level);
27699               });
27700
27701               if (_i4 === "0") {
27702                 sharedGroups = memberGroups;
27703               } else {
27704                 sharedGroups = sharedGroups.filter(function (groupID) {
27705                   return memberGroups.indexOf(groupID) !== -1;
27706                 });
27707               }
27708             };
27709
27710             for (var _i4 in props.members) {
27711               _loop(_i4);
27712             }
27713
27714             props.groups = props.groups.concat(sharedGroups.filter(function (groupID) {
27715               return props.groups.indexOf(groupID) === -1;
27716             }));
27717
27718             for (var j in sharedGroups) {
27719               var groupFeature = featuresByCode[sharedGroups[j]];
27720
27721               if (groupFeature.properties.members.indexOf(props.id) === -1) {
27722                 groupFeature.properties.members.push(props.id);
27723               }
27724             }
27725           }
27726
27727           function loadRoadSpeedUnit(feature2) {
27728             var props = feature2.properties;
27729
27730             if (feature2.geometry) {
27731               if (!props.roadSpeedUnit) props.roadSpeedUnit = "km/h";
27732             } else if (props.members) {
27733               var vals = Array.from(new Set(props.members.map(function (id) {
27734                 var member = featuresByCode[id];
27735                 if (member.geometry) return member.properties.roadSpeedUnit || "km/h";
27736               }).filter(Boolean)));
27737               if (vals.length === 1) props.roadSpeedUnit = vals[0];
27738             }
27739           }
27740
27741           function loadRoadHeightUnit(feature2) {
27742             var props = feature2.properties;
27743
27744             if (feature2.geometry) {
27745               if (!props.roadHeightUnit) props.roadHeightUnit = "m";
27746             } else if (props.members) {
27747               var vals = Array.from(new Set(props.members.map(function (id) {
27748                 var member = featuresByCode[id];
27749                 if (member.geometry) return member.properties.roadHeightUnit || "m";
27750               }).filter(Boolean)));
27751               if (vals.length === 1) props.roadHeightUnit = vals[0];
27752             }
27753           }
27754
27755           function loadDriveSide(feature2) {
27756             var props = feature2.properties;
27757
27758             if (feature2.geometry) {
27759               if (!props.driveSide) props.driveSide = "right";
27760             } else if (props.members) {
27761               var vals = Array.from(new Set(props.members.map(function (id) {
27762                 var member = featuresByCode[id];
27763                 if (member.geometry) return member.properties.driveSide || "right";
27764               }).filter(Boolean)));
27765               if (vals.length === 1) props.driveSide = vals[0];
27766             }
27767           }
27768
27769           function loadCallingCodes(feature2) {
27770             var props = feature2.properties;
27771
27772             if (!feature2.geometry && props.members) {
27773               props.callingCodes = Array.from(new Set(props.members.reduce(function (array, id) {
27774                 var member = featuresByCode[id];
27775                 if (member.geometry && member.properties.callingCodes) return array.concat(member.properties.callingCodes);
27776                 return array;
27777               }, [])));
27778             }
27779           }
27780
27781           function loadFlag(feature2) {
27782             if (!feature2.properties.iso1A2) return;
27783             var flag = feature2.properties.iso1A2.replace(/./g, function (_char) {
27784               return String.fromCodePoint(_char.charCodeAt(0) + 127397);
27785             });
27786             feature2.properties.emojiFlag = flag;
27787           }
27788
27789           function loadMembersForGroupsOf(feature2) {
27790             for (var j in feature2.properties.groups) {
27791               var groupID = feature2.properties.groups[j];
27792               var groupFeature = featuresByCode[groupID];
27793               if (!groupFeature.properties.members) groupFeature.properties.members = [];
27794               groupFeature.properties.members.push(feature2.properties.id);
27795             }
27796           }
27797
27798           function cacheFeatureByIDs(feature2) {
27799             var ids = [];
27800
27801             for (var k in identifierProps) {
27802               var prop = identifierProps[k];
27803               var id = feature2.properties[prop];
27804               if (id) ids.push(id);
27805             }
27806
27807             if (feature2.properties.aliases) {
27808               for (var j in feature2.properties.aliases) {
27809                 ids.push(feature2.properties.aliases[j]);
27810               }
27811             }
27812
27813             for (var _i5 in ids) {
27814               var _id = canonicalID(ids[_i5]);
27815
27816               featuresByCode[_id] = feature2;
27817             }
27818           }
27819         }
27820
27821         function locArray(loc) {
27822           if (Array.isArray(loc)) {
27823             return loc;
27824           } else if (loc.coordinates) {
27825             return loc.coordinates;
27826           }
27827
27828           return loc.geometry.coordinates;
27829         }
27830
27831         function smallestFeature(loc) {
27832           var query = locArray(loc);
27833           var featureProperties = whichPolygonGetter(query);
27834           if (!featureProperties) return null;
27835           return featuresByCode[featureProperties.id];
27836         }
27837
27838         function countryFeature(loc) {
27839           var feature2 = smallestFeature(loc);
27840           if (!feature2) return null;
27841           var countryCode = feature2.properties.country || feature2.properties.iso1A2;
27842           return featuresByCode[countryCode] || null;
27843         }
27844
27845         var defaultOpts = {
27846           level: void 0,
27847           maxLevel: void 0,
27848           withProp: void 0
27849         };
27850
27851         function featureForLoc(loc, opts) {
27852           var targetLevel = opts.level || "country";
27853           var maxLevel = opts.maxLevel || "world";
27854           var withProp = opts.withProp;
27855           var targetLevelIndex = levels.indexOf(targetLevel);
27856           if (targetLevelIndex === -1) return null;
27857           var maxLevelIndex = levels.indexOf(maxLevel);
27858           if (maxLevelIndex === -1) return null;
27859           if (maxLevelIndex < targetLevelIndex) return null;
27860
27861           if (targetLevel === "country") {
27862             var fastFeature = countryFeature(loc);
27863
27864             if (fastFeature) {
27865               if (!withProp || fastFeature.properties[withProp]) {
27866                 return fastFeature;
27867               }
27868             }
27869           }
27870
27871           var features2 = featuresContaining(loc);
27872
27873           for (var i in features2) {
27874             var feature2 = features2[i];
27875             var levelIndex = levels.indexOf(feature2.properties.level);
27876
27877             if (feature2.properties.level === targetLevel || levelIndex > targetLevelIndex && levelIndex <= maxLevelIndex) {
27878               if (!withProp || feature2.properties[withProp]) {
27879                 return feature2;
27880               }
27881             }
27882           }
27883
27884           return null;
27885         }
27886
27887         function featureForID(id) {
27888           var stringID;
27889
27890           if (typeof id === "number") {
27891             stringID = id.toString();
27892
27893             if (stringID.length === 1) {
27894               stringID = "00" + stringID;
27895             } else if (stringID.length === 2) {
27896               stringID = "0" + stringID;
27897             }
27898           } else {
27899             stringID = canonicalID(id);
27900           }
27901
27902           return featuresByCode[stringID] || null;
27903         }
27904
27905         function smallestFeaturesForBbox(bbox) {
27906           return whichPolygonGetter.bbox(bbox).map(function (props) {
27907             return featuresByCode[props.id];
27908           });
27909         }
27910
27911         function smallestOrMatchingFeature(query) {
27912           if (_typeof(query) === "object") {
27913             return smallestFeature(query);
27914           }
27915
27916           return featureForID(query);
27917         }
27918
27919         function feature$1(query) {
27920           var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultOpts;
27921
27922           if (_typeof(query) === "object") {
27923             return featureForLoc(query, opts);
27924           }
27925
27926           return featureForID(query);
27927         }
27928
27929         function iso1A2Code(query) {
27930           var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultOpts;
27931           opts.withProp = "iso1A2";
27932           var match = feature$1(query, opts);
27933           if (!match) return null;
27934           return match.properties.iso1A2 || null;
27935         }
27936
27937         function featuresContaining(query, strict) {
27938           var matchingFeatures;
27939
27940           if (Array.isArray(query) && query.length === 4) {
27941             matchingFeatures = smallestFeaturesForBbox(query);
27942           } else {
27943             var smallestOrMatching = smallestOrMatchingFeature(query);
27944             matchingFeatures = smallestOrMatching ? [smallestOrMatching] : [];
27945           }
27946
27947           if (!matchingFeatures.length) return [];
27948           var returnFeatures;
27949
27950           if (!strict || _typeof(query) === "object") {
27951             returnFeatures = matchingFeatures.slice();
27952           } else {
27953             returnFeatures = [];
27954           }
27955
27956           for (var j in matchingFeatures) {
27957             var properties = matchingFeatures[j].properties;
27958
27959             for (var i in properties.groups) {
27960               var groupID = properties.groups[i];
27961               var groupFeature = featuresByCode[groupID];
27962
27963               if (returnFeatures.indexOf(groupFeature) === -1) {
27964                 returnFeatures.push(groupFeature);
27965               }
27966             }
27967           }
27968
27969           return returnFeatures;
27970         }
27971
27972         function featuresIn(id, strict) {
27973           var feature2 = featureForID(id);
27974           if (!feature2) return [];
27975           var features2 = [];
27976
27977           if (!strict) {
27978             features2.push(feature2);
27979           }
27980
27981           var properties = feature2.properties;
27982
27983           if (properties.members) {
27984             for (var i in properties.members) {
27985               var memberID = properties.members[i];
27986               features2.push(featuresByCode[memberID]);
27987             }
27988           }
27989
27990           return features2;
27991         }
27992
27993         function aggregateFeature(id) {
27994           var features2 = featuresIn(id, false);
27995           if (features2.length === 0) return null;
27996           var aggregateCoordinates = [];
27997
27998           for (var i in features2) {
27999             var feature2 = features2[i];
28000
28001             if (feature2.geometry && feature2.geometry.type === "MultiPolygon" && feature2.geometry.coordinates) {
28002               aggregateCoordinates = aggregateCoordinates.concat(feature2.geometry.coordinates);
28003             }
28004           }
28005
28006           return {
28007             type: "Feature",
28008             properties: features2[0].properties,
28009             geometry: {
28010               type: "MultiPolygon",
28011               coordinates: aggregateCoordinates
28012             }
28013           };
28014         }
28015
28016         function roadSpeedUnit(query) {
28017           var feature2 = smallestOrMatchingFeature(query);
28018           return feature2 && feature2.properties.roadSpeedUnit || null;
28019         }
28020
28021         function roadHeightUnit(query) {
28022           var feature2 = smallestOrMatchingFeature(query);
28023           return feature2 && feature2.properties.roadHeightUnit || null;
28024         }
28025
28026         var geojsonArea = {};
28027
28028         var wgs84$1 = {};
28029
28030         wgs84$1.RADIUS = 6378137;
28031         wgs84$1.FLATTENING = 1 / 298.257223563;
28032         wgs84$1.POLAR_RADIUS = 6356752.3142;
28033
28034         var wgs84 = wgs84$1;
28035         geojsonArea.geometry = geometry;
28036         geojsonArea.ring = ringArea;
28037
28038         function geometry(_) {
28039           var area = 0,
28040               i;
28041
28042           switch (_.type) {
28043             case 'Polygon':
28044               return polygonArea(_.coordinates);
28045
28046             case 'MultiPolygon':
28047               for (i = 0; i < _.coordinates.length; i++) {
28048                 area += polygonArea(_.coordinates[i]);
28049               }
28050
28051               return area;
28052
28053             case 'Point':
28054             case 'MultiPoint':
28055             case 'LineString':
28056             case 'MultiLineString':
28057               return 0;
28058
28059             case 'GeometryCollection':
28060               for (i = 0; i < _.geometries.length; i++) {
28061                 area += geometry(_.geometries[i]);
28062               }
28063
28064               return area;
28065           }
28066         }
28067
28068         function polygonArea(coords) {
28069           var area = 0;
28070
28071           if (coords && coords.length > 0) {
28072             area += Math.abs(ringArea(coords[0]));
28073
28074             for (var i = 1; i < coords.length; i++) {
28075               area -= Math.abs(ringArea(coords[i]));
28076             }
28077           }
28078
28079           return area;
28080         }
28081         /**
28082          * Calculate the approximate area of the polygon were it projected onto
28083          *     the earth.  Note that this area will be positive if ring is oriented
28084          *     clockwise, otherwise it will be negative.
28085          *
28086          * Reference:
28087          * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
28088          *     Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
28089          *     Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
28090          *
28091          * Returns:
28092          * {float} The approximate signed geodesic area of the polygon in square
28093          *     meters.
28094          */
28095
28096
28097         function ringArea(coords) {
28098           var p1,
28099               p2,
28100               p3,
28101               lowerIndex,
28102               middleIndex,
28103               upperIndex,
28104               i,
28105               area = 0,
28106               coordsLength = coords.length;
28107
28108           if (coordsLength > 2) {
28109             for (i = 0; i < coordsLength; i++) {
28110               if (i === coordsLength - 2) {
28111                 // i = N-2
28112                 lowerIndex = coordsLength - 2;
28113                 middleIndex = coordsLength - 1;
28114                 upperIndex = 0;
28115               } else if (i === coordsLength - 1) {
28116                 // i = N-1
28117                 lowerIndex = coordsLength - 1;
28118                 middleIndex = 0;
28119                 upperIndex = 1;
28120               } else {
28121                 // i = 0 to N-3
28122                 lowerIndex = i;
28123                 middleIndex = i + 1;
28124                 upperIndex = i + 2;
28125               }
28126
28127               p1 = coords[lowerIndex];
28128               p2 = coords[middleIndex];
28129               p3 = coords[upperIndex];
28130               area += (rad(p3[0]) - rad(p1[0])) * Math.sin(rad(p2[1]));
28131             }
28132
28133             area = area * wgs84.RADIUS * wgs84.RADIUS / 2;
28134           }
28135
28136           return area;
28137         }
28138
28139         function rad(_) {
28140           return _ * Math.PI / 180;
28141         }
28142
28143         var inputValidation = {};
28144
28145         var $$n = _export;
28146         var $includes = arrayIncludes.includes;
28147         var addToUnscopables$2 = addToUnscopables$6;
28148
28149         // `Array.prototype.includes` method
28150         // https://tc39.es/ecma262/#sec-array.prototype.includes
28151         $$n({ target: 'Array', proto: true }, {
28152           includes: function includes(el /* , fromIndex = 0 */) {
28153             return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
28154           }
28155         });
28156
28157         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
28158         addToUnscopables$2('includes');
28159
28160         var validateCenter$1 = {};
28161
28162         validateCenter$1.validateCenter = function validateCenter(center) {
28163           var validCenterLengths = [2, 3];
28164
28165           if (!Array.isArray(center) || !validCenterLengths.includes(center.length)) {
28166             throw new Error("ERROR! Center has to be an array of length two or three");
28167           }
28168
28169           var _center = _slicedToArray(center, 2),
28170               lng = _center[0],
28171               lat = _center[1];
28172
28173           if (typeof lng !== "number" || typeof lat !== "number") {
28174             throw new Error("ERROR! Longitude and Latitude has to be numbers but where ".concat(_typeof(lng), " and ").concat(_typeof(lat)));
28175           }
28176
28177           if (lng > 180 || lng < -180) {
28178             throw new Error("ERROR! Longitude has to be between -180 and 180 but was ".concat(lng));
28179           }
28180
28181           if (lat > 90 || lat < -90) {
28182             throw new Error("ERROR! Latitude has to be between -90 and 90 but was ".concat(lat));
28183           }
28184         };
28185
28186         var validateRadius$1 = {};
28187
28188         validateRadius$1.validateRadius = function validateRadius(radius) {
28189           if (typeof radius !== "number") {
28190             throw new Error("ERROR! Radius has to be a positive number but was: ".concat(_typeof(radius)));
28191           }
28192
28193           if (radius <= 0) {
28194             throw new Error("ERROR! Radius has to be a positive number but was: ".concat(radius));
28195           }
28196         };
28197
28198         var validateNumberOfEdges$1 = {};
28199
28200         validateNumberOfEdges$1.validateNumberOfEdges = function validateNumberOfEdges(numberOfEdges) {
28201           if (typeof numberOfEdges !== "number") {
28202             var ARGUMENT_TYPE = Array.isArray(numberOfEdges) ? "array" : _typeof(numberOfEdges);
28203             throw new Error("ERROR! Number of edges has to be a number but was: ".concat(ARGUMENT_TYPE));
28204           }
28205
28206           if (numberOfEdges < 3) {
28207             throw new Error("ERROR! Number of edges has to be at least 3 but was: ".concat(numberOfEdges));
28208           }
28209         };
28210
28211         var validateEarthRadius$1 = {};
28212
28213         validateEarthRadius$1.validateEarthRadius = function validateEarthRadius(earthRadius) {
28214           if (typeof earthRadius !== "number") {
28215             var ARGUMENT_TYPE = Array.isArray(earthRadius) ? "array" : _typeof(earthRadius);
28216             throw new Error("ERROR! Earth radius has to be a number but was: ".concat(ARGUMENT_TYPE));
28217           }
28218
28219           if (earthRadius <= 0) {
28220             throw new Error("ERROR! Earth radius has to be a positive number but was: ".concat(earthRadius));
28221           }
28222         };
28223
28224         var validateBearing$1 = {};
28225
28226         validateBearing$1.validateBearing = function validateBearing(bearing) {
28227           if (typeof bearing !== "number") {
28228             var ARGUMENT_TYPE = Array.isArray(bearing) ? "array" : _typeof(bearing);
28229             throw new Error("ERROR! Bearing has to be a number but was: ".concat(ARGUMENT_TYPE));
28230           }
28231         };
28232
28233         var validateCenter = validateCenter$1.validateCenter;
28234         var validateRadius = validateRadius$1.validateRadius;
28235         var validateNumberOfEdges = validateNumberOfEdges$1.validateNumberOfEdges;
28236         var validateEarthRadius = validateEarthRadius$1.validateEarthRadius;
28237         var validateBearing = validateBearing$1.validateBearing;
28238
28239         function validateInput$1(_ref) {
28240           var center = _ref.center,
28241               radius = _ref.radius,
28242               numberOfEdges = _ref.numberOfEdges,
28243               earthRadius = _ref.earthRadius,
28244               bearing = _ref.bearing;
28245           validateCenter(center);
28246           validateRadius(radius);
28247           validateNumberOfEdges(numberOfEdges);
28248           validateEarthRadius(earthRadius);
28249           validateBearing(bearing);
28250         }
28251
28252         inputValidation.validateCenter = validateCenter;
28253         inputValidation.validateRadius = validateRadius;
28254         inputValidation.validateNumberOfEdges = validateNumberOfEdges;
28255         inputValidation.validateEarthRadius = validateEarthRadius;
28256         inputValidation.validateBearing = validateBearing;
28257         inputValidation.validateInput = validateInput$1;
28258
28259         var validateInput = inputValidation.validateInput;
28260         var defaultEarthRadius = 6378137; // equatorial Earth radius
28261
28262         function toRadians(angleInDegrees) {
28263           return angleInDegrees * Math.PI / 180;
28264         }
28265
28266         function toDegrees(angleInRadians) {
28267           return angleInRadians * 180 / Math.PI;
28268         }
28269
28270         function offset(c1, distance, earthRadius, bearing) {
28271           var lat1 = toRadians(c1[1]);
28272           var lon1 = toRadians(c1[0]);
28273           var dByR = distance / earthRadius;
28274           var lat = Math.asin(Math.sin(lat1) * Math.cos(dByR) + Math.cos(lat1) * Math.sin(dByR) * Math.cos(bearing));
28275           var lon = lon1 + Math.atan2(Math.sin(bearing) * Math.sin(dByR) * Math.cos(lat1), Math.cos(dByR) - Math.sin(lat1) * Math.sin(lat));
28276           return [toDegrees(lon), toDegrees(lat)];
28277         }
28278
28279         var circleToPolygon = function circleToPolygon(center, radius, options) {
28280           var n = getNumberOfEdges(options);
28281           var earthRadius = getEarthRadius(options);
28282           var bearing = getBearing(options);
28283           var direction = getDirection(options); // validateInput() throws error on invalid input and do nothing on valid input
28284
28285           validateInput({
28286             center: center,
28287             radius: radius,
28288             numberOfEdges: n,
28289             earthRadius: earthRadius,
28290             bearing: bearing
28291           });
28292           var start = toRadians(bearing);
28293           var coordinates = [];
28294
28295           for (var i = 0; i < n; ++i) {
28296             coordinates.push(offset(center, radius, earthRadius, start + direction * 2 * Math.PI * -i / n));
28297           }
28298
28299           coordinates.push(coordinates[0]);
28300           return {
28301             type: "Polygon",
28302             coordinates: [coordinates]
28303           };
28304         };
28305
28306         function getNumberOfEdges(options) {
28307           if (isUndefinedOrNull(options)) {
28308             return 32;
28309           } else if (isObjectNotArray(options)) {
28310             var numberOfEdges = options.numberOfEdges;
28311             return numberOfEdges === undefined ? 32 : numberOfEdges;
28312           }
28313
28314           return options;
28315         }
28316
28317         function getEarthRadius(options) {
28318           if (isUndefinedOrNull(options)) {
28319             return defaultEarthRadius;
28320           } else if (isObjectNotArray(options)) {
28321             var earthRadius = options.earthRadius;
28322             return earthRadius === undefined ? defaultEarthRadius : earthRadius;
28323           }
28324
28325           return defaultEarthRadius;
28326         }
28327
28328         function getDirection(options) {
28329           if (isObjectNotArray(options) && options.rightHandRule) {
28330             return -1;
28331           }
28332
28333           return 1;
28334         }
28335
28336         function getBearing(options) {
28337           if (isUndefinedOrNull(options)) {
28338             return 0;
28339           } else if (isObjectNotArray(options)) {
28340             var bearing = options.bearing;
28341             return bearing === undefined ? 0 : bearing;
28342           }
28343
28344           return 0;
28345         }
28346
28347         function isObjectNotArray(argument) {
28348           return argument !== null && _typeof(argument) === "object" && !Array.isArray(argument);
28349         }
28350
28351         function isUndefinedOrNull(argument) {
28352           return argument === null || argument === undefined;
28353         }
28354
28355         var $$m = _export;
28356
28357         // `Number.EPSILON` constant
28358         // https://tc39.es/ecma262/#sec-number.epsilon
28359         $$m({ target: 'Number', stat: true }, {
28360           EPSILON: Math.pow(2, -52)
28361         });
28362
28363         var uncurryThis$8 = functionUncurryThis;
28364         var requireObjectCoercible$4 = requireObjectCoercible$e;
28365         var toString$5 = toString$k;
28366
28367         var quot = /"/g;
28368         var replace$2 = uncurryThis$8(''.replace);
28369
28370         // `CreateHTML` abstract operation
28371         // https://tc39.es/ecma262/#sec-createhtml
28372         var createHtml = function (string, tag, attribute, value) {
28373           var S = toString$5(requireObjectCoercible$4(string));
28374           var p1 = '<' + tag;
28375           if (attribute !== '') p1 += ' ' + attribute + '="' + replace$2(toString$5(value), quot, '&quot;') + '"';
28376           return p1 + '>' + S + '</' + tag + '>';
28377         };
28378
28379         var fails$6 = fails$V;
28380
28381         // check the existence of a method, lowercase
28382         // of a tag and escaping quotes in arguments
28383         var stringHtmlForced = function (METHOD_NAME) {
28384           return fails$6(function () {
28385             var test = ''[METHOD_NAME]('"');
28386             return test !== test.toLowerCase() || test.split('"').length > 3;
28387           });
28388         };
28389
28390         var $$l = _export;
28391         var createHTML = createHtml;
28392         var forcedStringHTMLMethod = stringHtmlForced;
28393
28394         // `String.prototype.link` method
28395         // https://tc39.es/ecma262/#sec-string.prototype.link
28396         $$l({ target: 'String', proto: true, forced: forcedStringHTMLMethod('link') }, {
28397           link: function link(url) {
28398             return createHTML(this, 'a', 'href', url);
28399           }
28400         });
28401
28402         /**
28403          * splaytree v3.1.0
28404          * Fast Splay tree for Node and browser
28405          *
28406          * @author Alexander Milevski <info@w8r.name>
28407          * @license MIT
28408          * @preserve
28409          */
28410         var Node =
28411         /** @class */
28412         function () {
28413           function Node(key, data) {
28414             this.next = null;
28415             this.key = key;
28416             this.data = data;
28417             this.left = null;
28418             this.right = null;
28419           }
28420
28421           return Node;
28422         }();
28423         /* follows "An implementation of top-down splaying"
28424          * by D. Sleator <sleator@cs.cmu.edu> March 1992
28425          */
28426
28427
28428         function DEFAULT_COMPARE(a, b) {
28429           return a > b ? 1 : a < b ? -1 : 0;
28430         }
28431         /**
28432          * Simple top down splay, not requiring i to be in the tree t.
28433          */
28434
28435
28436         function splay(i, t, comparator) {
28437           var N = new Node(null, null);
28438           var l = N;
28439           var r = N;
28440
28441           while (true) {
28442             var cmp = comparator(i, t.key); //if (i < t.key) {
28443
28444             if (cmp < 0) {
28445               if (t.left === null) break; //if (i < t.left.key) {
28446
28447               if (comparator(i, t.left.key) < 0) {
28448                 var y = t.left;
28449                 /* rotate right */
28450
28451                 t.left = y.right;
28452                 y.right = t;
28453                 t = y;
28454                 if (t.left === null) break;
28455               }
28456
28457               r.left = t;
28458               /* link right */
28459
28460               r = t;
28461               t = t.left; //} else if (i > t.key) {
28462             } else if (cmp > 0) {
28463               if (t.right === null) break; //if (i > t.right.key) {
28464
28465               if (comparator(i, t.right.key) > 0) {
28466                 var y = t.right;
28467                 /* rotate left */
28468
28469                 t.right = y.left;
28470                 y.left = t;
28471                 t = y;
28472                 if (t.right === null) break;
28473               }
28474
28475               l.right = t;
28476               /* link left */
28477
28478               l = t;
28479               t = t.right;
28480             } else break;
28481           }
28482           /* assemble */
28483
28484
28485           l.right = t.left;
28486           r.left = t.right;
28487           t.left = N.right;
28488           t.right = N.left;
28489           return t;
28490         }
28491
28492         function insert(i, data, t, comparator) {
28493           var node = new Node(i, data);
28494
28495           if (t === null) {
28496             node.left = node.right = null;
28497             return node;
28498           }
28499
28500           t = splay(i, t, comparator);
28501           var cmp = comparator(i, t.key);
28502
28503           if (cmp < 0) {
28504             node.left = t.left;
28505             node.right = t;
28506             t.left = null;
28507           } else if (cmp >= 0) {
28508             node.right = t.right;
28509             node.left = t;
28510             t.right = null;
28511           }
28512
28513           return node;
28514         }
28515
28516         function split$2(key, v, comparator) {
28517           var left = null;
28518           var right = null;
28519
28520           if (v) {
28521             v = splay(key, v, comparator);
28522             var cmp = comparator(v.key, key);
28523
28524             if (cmp === 0) {
28525               left = v.left;
28526               right = v.right;
28527             } else if (cmp < 0) {
28528               right = v.right;
28529               v.right = null;
28530               left = v;
28531             } else {
28532               left = v.left;
28533               v.left = null;
28534               right = v;
28535             }
28536           }
28537
28538           return {
28539             left: left,
28540             right: right
28541           };
28542         }
28543
28544         function merge$3(left, right, comparator) {
28545           if (right === null) return left;
28546           if (left === null) return right;
28547           right = splay(left.key, right, comparator);
28548           right.left = left;
28549           return right;
28550         }
28551         /**
28552          * Prints level of the tree
28553          */
28554
28555
28556         function printRow(root, prefix, isTail, out, printNode) {
28557           if (root) {
28558             out("" + prefix + (isTail ? '└── ' : '├── ') + printNode(root) + "\n");
28559             var indent = prefix + (isTail ? '    ' : '│   ');
28560             if (root.left) printRow(root.left, indent, false, out, printNode);
28561             if (root.right) printRow(root.right, indent, true, out, printNode);
28562           }
28563         }
28564
28565         var Tree =
28566         /** @class */
28567         function () {
28568           function Tree(comparator) {
28569             if (comparator === void 0) {
28570               comparator = DEFAULT_COMPARE;
28571             }
28572
28573             this._root = null;
28574             this._size = 0;
28575             this._comparator = comparator;
28576           }
28577           /**
28578            * Inserts a key, allows duplicates
28579            */
28580
28581
28582           Tree.prototype.insert = function (key, data) {
28583             this._size++;
28584             return this._root = insert(key, data, this._root, this._comparator);
28585           };
28586           /**
28587            * Adds a key, if it is not present in the tree
28588            */
28589
28590
28591           Tree.prototype.add = function (key, data) {
28592             var node = new Node(key, data);
28593
28594             if (this._root === null) {
28595               node.left = node.right = null;
28596               this._size++;
28597               this._root = node;
28598             }
28599
28600             var comparator = this._comparator;
28601             var t = splay(key, this._root, comparator);
28602             var cmp = comparator(key, t.key);
28603             if (cmp === 0) this._root = t;else {
28604               if (cmp < 0) {
28605                 node.left = t.left;
28606                 node.right = t;
28607                 t.left = null;
28608               } else if (cmp > 0) {
28609                 node.right = t.right;
28610                 node.left = t;
28611                 t.right = null;
28612               }
28613
28614               this._size++;
28615               this._root = node;
28616             }
28617             return this._root;
28618           };
28619           /**
28620            * @param  {Key} key
28621            * @return {Node|null}
28622            */
28623
28624
28625           Tree.prototype.remove = function (key) {
28626             this._root = this._remove(key, this._root, this._comparator);
28627           };
28628           /**
28629            * Deletes i from the tree if it's there
28630            */
28631
28632
28633           Tree.prototype._remove = function (i, t, comparator) {
28634             var x;
28635             if (t === null) return null;
28636             t = splay(i, t, comparator);
28637             var cmp = comparator(i, t.key);
28638
28639             if (cmp === 0) {
28640               /* found it */
28641               if (t.left === null) {
28642                 x = t.right;
28643               } else {
28644                 x = splay(i, t.left, comparator);
28645                 x.right = t.right;
28646               }
28647
28648               this._size--;
28649               return x;
28650             }
28651
28652             return t;
28653             /* It wasn't there */
28654           };
28655           /**
28656            * Removes and returns the node with smallest key
28657            */
28658
28659
28660           Tree.prototype.pop = function () {
28661             var node = this._root;
28662
28663             if (node) {
28664               while (node.left) {
28665                 node = node.left;
28666               }
28667
28668               this._root = splay(node.key, this._root, this._comparator);
28669               this._root = this._remove(node.key, this._root, this._comparator);
28670               return {
28671                 key: node.key,
28672                 data: node.data
28673               };
28674             }
28675
28676             return null;
28677           };
28678           /**
28679            * Find without splaying
28680            */
28681
28682
28683           Tree.prototype.findStatic = function (key) {
28684             var current = this._root;
28685             var compare = this._comparator;
28686
28687             while (current) {
28688               var cmp = compare(key, current.key);
28689               if (cmp === 0) return current;else if (cmp < 0) current = current.left;else current = current.right;
28690             }
28691
28692             return null;
28693           };
28694
28695           Tree.prototype.find = function (key) {
28696             if (this._root) {
28697               this._root = splay(key, this._root, this._comparator);
28698               if (this._comparator(key, this._root.key) !== 0) return null;
28699             }
28700
28701             return this._root;
28702           };
28703
28704           Tree.prototype.contains = function (key) {
28705             var current = this._root;
28706             var compare = this._comparator;
28707
28708             while (current) {
28709               var cmp = compare(key, current.key);
28710               if (cmp === 0) return true;else if (cmp < 0) current = current.left;else current = current.right;
28711             }
28712
28713             return false;
28714           };
28715
28716           Tree.prototype.forEach = function (visitor, ctx) {
28717             var current = this._root;
28718             var Q = [];
28719             /* Initialize stack s */
28720
28721             var done = false;
28722
28723             while (!done) {
28724               if (current !== null) {
28725                 Q.push(current);
28726                 current = current.left;
28727               } else {
28728                 if (Q.length !== 0) {
28729                   current = Q.pop();
28730                   visitor.call(ctx, current);
28731                   current = current.right;
28732                 } else done = true;
28733               }
28734             }
28735
28736             return this;
28737           };
28738           /**
28739            * Walk key range from `low` to `high`. Stops if `fn` returns a value.
28740            */
28741
28742
28743           Tree.prototype.range = function (low, high, fn, ctx) {
28744             var Q = [];
28745             var compare = this._comparator;
28746             var node = this._root;
28747             var cmp;
28748
28749             while (Q.length !== 0 || node) {
28750               if (node) {
28751                 Q.push(node);
28752                 node = node.left;
28753               } else {
28754                 node = Q.pop();
28755                 cmp = compare(node.key, high);
28756
28757                 if (cmp > 0) {
28758                   break;
28759                 } else if (compare(node.key, low) >= 0) {
28760                   if (fn.call(ctx, node)) return this; // stop if smth is returned
28761                 }
28762
28763                 node = node.right;
28764               }
28765             }
28766
28767             return this;
28768           };
28769           /**
28770            * Returns array of keys
28771            */
28772
28773
28774           Tree.prototype.keys = function () {
28775             var keys = [];
28776             this.forEach(function (_a) {
28777               var key = _a.key;
28778               return keys.push(key);
28779             });
28780             return keys;
28781           };
28782           /**
28783            * Returns array of all the data in the nodes
28784            */
28785
28786
28787           Tree.prototype.values = function () {
28788             var values = [];
28789             this.forEach(function (_a) {
28790               var data = _a.data;
28791               return values.push(data);
28792             });
28793             return values;
28794           };
28795
28796           Tree.prototype.min = function () {
28797             if (this._root) return this.minNode(this._root).key;
28798             return null;
28799           };
28800
28801           Tree.prototype.max = function () {
28802             if (this._root) return this.maxNode(this._root).key;
28803             return null;
28804           };
28805
28806           Tree.prototype.minNode = function (t) {
28807             if (t === void 0) {
28808               t = this._root;
28809             }
28810
28811             if (t) while (t.left) {
28812               t = t.left;
28813             }
28814             return t;
28815           };
28816
28817           Tree.prototype.maxNode = function (t) {
28818             if (t === void 0) {
28819               t = this._root;
28820             }
28821
28822             if (t) while (t.right) {
28823               t = t.right;
28824             }
28825             return t;
28826           };
28827           /**
28828            * Returns node at given index
28829            */
28830
28831
28832           Tree.prototype.at = function (index) {
28833             var current = this._root;
28834             var done = false;
28835             var i = 0;
28836             var Q = [];
28837
28838             while (!done) {
28839               if (current) {
28840                 Q.push(current);
28841                 current = current.left;
28842               } else {
28843                 if (Q.length > 0) {
28844                   current = Q.pop();
28845                   if (i === index) return current;
28846                   i++;
28847                   current = current.right;
28848                 } else done = true;
28849               }
28850             }
28851
28852             return null;
28853           };
28854
28855           Tree.prototype.next = function (d) {
28856             var root = this._root;
28857             var successor = null;
28858
28859             if (d.right) {
28860               successor = d.right;
28861
28862               while (successor.left) {
28863                 successor = successor.left;
28864               }
28865
28866               return successor;
28867             }
28868
28869             var comparator = this._comparator;
28870
28871             while (root) {
28872               var cmp = comparator(d.key, root.key);
28873               if (cmp === 0) break;else if (cmp < 0) {
28874                 successor = root;
28875                 root = root.left;
28876               } else root = root.right;
28877             }
28878
28879             return successor;
28880           };
28881
28882           Tree.prototype.prev = function (d) {
28883             var root = this._root;
28884             var predecessor = null;
28885
28886             if (d.left !== null) {
28887               predecessor = d.left;
28888
28889               while (predecessor.right) {
28890                 predecessor = predecessor.right;
28891               }
28892
28893               return predecessor;
28894             }
28895
28896             var comparator = this._comparator;
28897
28898             while (root) {
28899               var cmp = comparator(d.key, root.key);
28900               if (cmp === 0) break;else if (cmp < 0) root = root.left;else {
28901                 predecessor = root;
28902                 root = root.right;
28903               }
28904             }
28905
28906             return predecessor;
28907           };
28908
28909           Tree.prototype.clear = function () {
28910             this._root = null;
28911             this._size = 0;
28912             return this;
28913           };
28914
28915           Tree.prototype.toList = function () {
28916             return toList(this._root);
28917           };
28918           /**
28919            * Bulk-load items. Both array have to be same size
28920            */
28921
28922
28923           Tree.prototype.load = function (keys, values, presort) {
28924             if (values === void 0) {
28925               values = [];
28926             }
28927
28928             if (presort === void 0) {
28929               presort = false;
28930             }
28931
28932             var size = keys.length;
28933             var comparator = this._comparator; // sort if needed
28934
28935             if (presort) sort(keys, values, 0, size - 1, comparator);
28936
28937             if (this._root === null) {
28938               // empty tree
28939               this._root = loadRecursive(keys, values, 0, size);
28940               this._size = size;
28941             } else {
28942               // that re-builds the whole tree from two in-order traversals
28943               var mergedList = mergeLists(this.toList(), createList(keys, values), comparator);
28944               size = this._size + size;
28945               this._root = sortedListToBST({
28946                 head: mergedList
28947               }, 0, size);
28948             }
28949
28950             return this;
28951           };
28952
28953           Tree.prototype.isEmpty = function () {
28954             return this._root === null;
28955           };
28956
28957           Object.defineProperty(Tree.prototype, "size", {
28958             get: function get() {
28959               return this._size;
28960             },
28961             enumerable: true,
28962             configurable: true
28963           });
28964           Object.defineProperty(Tree.prototype, "root", {
28965             get: function get() {
28966               return this._root;
28967             },
28968             enumerable: true,
28969             configurable: true
28970           });
28971
28972           Tree.prototype.toString = function (printNode) {
28973             if (printNode === void 0) {
28974               printNode = function printNode(n) {
28975                 return String(n.key);
28976               };
28977             }
28978
28979             var out = [];
28980             printRow(this._root, '', true, function (v) {
28981               return out.push(v);
28982             }, printNode);
28983             return out.join('');
28984           };
28985
28986           Tree.prototype.update = function (key, newKey, newData) {
28987             var comparator = this._comparator;
28988
28989             var _a = split$2(key, this._root, comparator),
28990                 left = _a.left,
28991                 right = _a.right;
28992
28993             if (comparator(key, newKey) < 0) {
28994               right = insert(newKey, newData, right, comparator);
28995             } else {
28996               left = insert(newKey, newData, left, comparator);
28997             }
28998
28999             this._root = merge$3(left, right, comparator);
29000           };
29001
29002           Tree.prototype.split = function (key) {
29003             return split$2(key, this._root, this._comparator);
29004           };
29005
29006           return Tree;
29007         }();
29008
29009         function loadRecursive(keys, values, start, end) {
29010           var size = end - start;
29011
29012           if (size > 0) {
29013             var middle = start + Math.floor(size / 2);
29014             var key = keys[middle];
29015             var data = values[middle];
29016             var node = new Node(key, data);
29017             node.left = loadRecursive(keys, values, start, middle);
29018             node.right = loadRecursive(keys, values, middle + 1, end);
29019             return node;
29020           }
29021
29022           return null;
29023         }
29024
29025         function createList(keys, values) {
29026           var head = new Node(null, null);
29027           var p = head;
29028
29029           for (var i = 0; i < keys.length; i++) {
29030             p = p.next = new Node(keys[i], values[i]);
29031           }
29032
29033           p.next = null;
29034           return head.next;
29035         }
29036
29037         function toList(root) {
29038           var current = root;
29039           var Q = [];
29040           var done = false;
29041           var head = new Node(null, null);
29042           var p = head;
29043
29044           while (!done) {
29045             if (current) {
29046               Q.push(current);
29047               current = current.left;
29048             } else {
29049               if (Q.length > 0) {
29050                 current = p = p.next = Q.pop();
29051                 current = current.right;
29052               } else done = true;
29053             }
29054           }
29055
29056           p.next = null; // that'll work even if the tree was empty
29057
29058           return head.next;
29059         }
29060
29061         function sortedListToBST(list, start, end) {
29062           var size = end - start;
29063
29064           if (size > 0) {
29065             var middle = start + Math.floor(size / 2);
29066             var left = sortedListToBST(list, start, middle);
29067             var root = list.head;
29068             root.left = left;
29069             list.head = list.head.next;
29070             root.right = sortedListToBST(list, middle + 1, end);
29071             return root;
29072           }
29073
29074           return null;
29075         }
29076
29077         function mergeLists(l1, l2, compare) {
29078           var head = new Node(null, null); // dummy
29079
29080           var p = head;
29081           var p1 = l1;
29082           var p2 = l2;
29083
29084           while (p1 !== null && p2 !== null) {
29085             if (compare(p1.key, p2.key) < 0) {
29086               p.next = p1;
29087               p1 = p1.next;
29088             } else {
29089               p.next = p2;
29090               p2 = p2.next;
29091             }
29092
29093             p = p.next;
29094           }
29095
29096           if (p1 !== null) {
29097             p.next = p1;
29098           } else if (p2 !== null) {
29099             p.next = p2;
29100           }
29101
29102           return head.next;
29103         }
29104
29105         function sort(keys, values, left, right, compare) {
29106           if (left >= right) return;
29107           var pivot = keys[left + right >> 1];
29108           var i = left - 1;
29109           var j = right + 1;
29110
29111           while (true) {
29112             do {
29113               i++;
29114             } while (compare(keys[i], pivot) < 0);
29115
29116             do {
29117               j--;
29118             } while (compare(keys[j], pivot) > 0);
29119
29120             if (i >= j) break;
29121             var tmp = keys[i];
29122             keys[i] = keys[j];
29123             keys[j] = tmp;
29124             tmp = values[i];
29125             values[i] = values[j];
29126             values[j] = tmp;
29127           }
29128
29129           sort(keys, values, left, j, compare);
29130           sort(keys, values, j + 1, right, compare);
29131         }
29132
29133         function _classCallCheck(instance, Constructor) {
29134           if (!(instance instanceof Constructor)) {
29135             throw new TypeError("Cannot call a class as a function");
29136           }
29137         }
29138
29139         function _defineProperties(target, props) {
29140           for (var i = 0; i < props.length; i++) {
29141             var descriptor = props[i];
29142             descriptor.enumerable = descriptor.enumerable || false;
29143             descriptor.configurable = true;
29144             if ("value" in descriptor) descriptor.writable = true;
29145             Object.defineProperty(target, descriptor.key, descriptor);
29146           }
29147         }
29148
29149         function _createClass(Constructor, protoProps, staticProps) {
29150           if (protoProps) _defineProperties(Constructor.prototype, protoProps);
29151           if (staticProps) _defineProperties(Constructor, staticProps);
29152           return Constructor;
29153         }
29154         /**
29155          * A bounding box has the format:
29156          *
29157          *  { ll: { x: xmin, y: ymin }, ur: { x: xmax, y: ymax } }
29158          *
29159          */
29160
29161
29162         var isInBbox = function isInBbox(bbox, point) {
29163           return bbox.ll.x <= point.x && point.x <= bbox.ur.x && bbox.ll.y <= point.y && point.y <= bbox.ur.y;
29164         };
29165         /* Returns either null, or a bbox (aka an ordered pair of points)
29166          * If there is only one point of overlap, a bbox with identical points
29167          * will be returned */
29168
29169
29170         var getBboxOverlap = function getBboxOverlap(b1, b2) {
29171           // check if the bboxes overlap at all
29172           if (b2.ur.x < b1.ll.x || b1.ur.x < b2.ll.x || b2.ur.y < b1.ll.y || b1.ur.y < b2.ll.y) return null; // find the middle two X values
29173
29174           var lowerX = b1.ll.x < b2.ll.x ? b2.ll.x : b1.ll.x;
29175           var upperX = b1.ur.x < b2.ur.x ? b1.ur.x : b2.ur.x; // find the middle two Y values
29176
29177           var lowerY = b1.ll.y < b2.ll.y ? b2.ll.y : b1.ll.y;
29178           var upperY = b1.ur.y < b2.ur.y ? b1.ur.y : b2.ur.y; // put those middle values together to get the overlap
29179
29180           return {
29181             ll: {
29182               x: lowerX,
29183               y: lowerY
29184             },
29185             ur: {
29186               x: upperX,
29187               y: upperY
29188             }
29189           };
29190         };
29191         /* Javascript doesn't do integer math. Everything is
29192          * floating point with percision Number.EPSILON.
29193          *
29194          * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON
29195          */
29196
29197
29198         var epsilon = Number.EPSILON; // IE Polyfill
29199
29200         if (epsilon === undefined) epsilon = Math.pow(2, -52);
29201         var EPSILON_SQ = epsilon * epsilon;
29202         /* FLP comparator */
29203
29204         var cmp = function cmp(a, b) {
29205           // check if they're both 0
29206           if (-epsilon < a && a < epsilon) {
29207             if (-epsilon < b && b < epsilon) {
29208               return 0;
29209             }
29210           } // check if they're flp equal
29211
29212
29213           var ab = a - b;
29214
29215           if (ab * ab < EPSILON_SQ * a * b) {
29216             return 0;
29217           } // normal comparison
29218
29219
29220           return a < b ? -1 : 1;
29221         };
29222         /**
29223          * This class rounds incoming values sufficiently so that
29224          * floating points problems are, for the most part, avoided.
29225          *
29226          * Incoming points are have their x & y values tested against
29227          * all previously seen x & y values. If either is 'too close'
29228          * to a previously seen value, it's value is 'snapped' to the
29229          * previously seen value.
29230          *
29231          * All points should be rounded by this class before being
29232          * stored in any data structures in the rest of this algorithm.
29233          */
29234
29235
29236         var PtRounder = /*#__PURE__*/function () {
29237           function PtRounder() {
29238             _classCallCheck(this, PtRounder);
29239
29240             this.reset();
29241           }
29242
29243           _createClass(PtRounder, [{
29244             key: "reset",
29245             value: function reset() {
29246               this.xRounder = new CoordRounder();
29247               this.yRounder = new CoordRounder();
29248             }
29249           }, {
29250             key: "round",
29251             value: function round(x, y) {
29252               return {
29253                 x: this.xRounder.round(x),
29254                 y: this.yRounder.round(y)
29255               };
29256             }
29257           }]);
29258
29259           return PtRounder;
29260         }();
29261
29262         var CoordRounder = /*#__PURE__*/function () {
29263           function CoordRounder() {
29264             _classCallCheck(this, CoordRounder);
29265
29266             this.tree = new Tree(); // preseed with 0 so we don't end up with values < Number.EPSILON
29267
29268             this.round(0);
29269           } // Note: this can rounds input values backwards or forwards.
29270           //       You might ask, why not restrict this to just rounding
29271           //       forwards? Wouldn't that allow left endpoints to always
29272           //       remain left endpoints during splitting (never change to
29273           //       right). No - it wouldn't, because we snap intersections
29274           //       to endpoints (to establish independence from the segment
29275           //       angle for t-intersections).
29276
29277
29278           _createClass(CoordRounder, [{
29279             key: "round",
29280             value: function round(coord) {
29281               var node = this.tree.add(coord);
29282               var prevNode = this.tree.prev(node);
29283
29284               if (prevNode !== null && cmp(node.key, prevNode.key) === 0) {
29285                 this.tree.remove(coord);
29286                 return prevNode.key;
29287               }
29288
29289               var nextNode = this.tree.next(node);
29290
29291               if (nextNode !== null && cmp(node.key, nextNode.key) === 0) {
29292                 this.tree.remove(coord);
29293                 return nextNode.key;
29294               }
29295
29296               return coord;
29297             }
29298           }]);
29299
29300           return CoordRounder;
29301         }(); // singleton available by import
29302
29303
29304         var rounder = new PtRounder();
29305         /* Cross Product of two vectors with first point at origin */
29306
29307         var crossProduct = function crossProduct(a, b) {
29308           return a.x * b.y - a.y * b.x;
29309         };
29310         /* Dot Product of two vectors with first point at origin */
29311
29312
29313         var dotProduct = function dotProduct(a, b) {
29314           return a.x * b.x + a.y * b.y;
29315         };
29316         /* Comparator for two vectors with same starting point */
29317
29318
29319         var compareVectorAngles = function compareVectorAngles(basePt, endPt1, endPt2) {
29320           var v1 = {
29321             x: endPt1.x - basePt.x,
29322             y: endPt1.y - basePt.y
29323           };
29324           var v2 = {
29325             x: endPt2.x - basePt.x,
29326             y: endPt2.y - basePt.y
29327           };
29328           var kross = crossProduct(v1, v2);
29329           return cmp(kross, 0);
29330         };
29331
29332         var length = function length(v) {
29333           return Math.sqrt(dotProduct(v, v));
29334         };
29335         /* Get the sine of the angle from pShared -> pAngle to pShaed -> pBase */
29336
29337
29338         var sineOfAngle = function sineOfAngle(pShared, pBase, pAngle) {
29339           var vBase = {
29340             x: pBase.x - pShared.x,
29341             y: pBase.y - pShared.y
29342           };
29343           var vAngle = {
29344             x: pAngle.x - pShared.x,
29345             y: pAngle.y - pShared.y
29346           };
29347           return crossProduct(vAngle, vBase) / length(vAngle) / length(vBase);
29348         };
29349         /* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */
29350
29351
29352         var cosineOfAngle = function cosineOfAngle(pShared, pBase, pAngle) {
29353           var vBase = {
29354             x: pBase.x - pShared.x,
29355             y: pBase.y - pShared.y
29356           };
29357           var vAngle = {
29358             x: pAngle.x - pShared.x,
29359             y: pAngle.y - pShared.y
29360           };
29361           return dotProduct(vAngle, vBase) / length(vAngle) / length(vBase);
29362         };
29363         /* Get the x coordinate where the given line (defined by a point and vector)
29364          * crosses the horizontal line with the given y coordiante.
29365          * In the case of parrallel lines (including overlapping ones) returns null. */
29366
29367
29368         var horizontalIntersection = function horizontalIntersection(pt, v, y) {
29369           if (v.y === 0) return null;
29370           return {
29371             x: pt.x + v.x / v.y * (y - pt.y),
29372             y: y
29373           };
29374         };
29375         /* Get the y coordinate where the given line (defined by a point and vector)
29376          * crosses the vertical line with the given x coordiante.
29377          * In the case of parrallel lines (including overlapping ones) returns null. */
29378
29379
29380         var verticalIntersection = function verticalIntersection(pt, v, x) {
29381           if (v.x === 0) return null;
29382           return {
29383             x: x,
29384             y: pt.y + v.y / v.x * (x - pt.x)
29385           };
29386         };
29387         /* Get the intersection of two lines, each defined by a base point and a vector.
29388          * In the case of parrallel lines (including overlapping ones) returns null. */
29389
29390
29391         var intersection = function intersection(pt1, v1, pt2, v2) {
29392           // take some shortcuts for vertical and horizontal lines
29393           // this also ensures we don't calculate an intersection and then discover
29394           // it's actually outside the bounding box of the line
29395           if (v1.x === 0) return verticalIntersection(pt2, v2, pt1.x);
29396           if (v2.x === 0) return verticalIntersection(pt1, v1, pt2.x);
29397           if (v1.y === 0) return horizontalIntersection(pt2, v2, pt1.y);
29398           if (v2.y === 0) return horizontalIntersection(pt1, v1, pt2.y); // General case for non-overlapping segments.
29399           // This algorithm is based on Schneider and Eberly.
29400           // http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf - pg 244
29401
29402           var kross = crossProduct(v1, v2);
29403           if (kross == 0) return null;
29404           var ve = {
29405             x: pt2.x - pt1.x,
29406             y: pt2.y - pt1.y
29407           };
29408           var d1 = crossProduct(ve, v1) / kross;
29409           var d2 = crossProduct(ve, v2) / kross; // take the average of the two calculations to minimize rounding error
29410
29411           var x1 = pt1.x + d2 * v1.x,
29412               x2 = pt2.x + d1 * v2.x;
29413           var y1 = pt1.y + d2 * v1.y,
29414               y2 = pt2.y + d1 * v2.y;
29415           var x = (x1 + x2) / 2;
29416           var y = (y1 + y2) / 2;
29417           return {
29418             x: x,
29419             y: y
29420           };
29421         };
29422
29423         var SweepEvent = /*#__PURE__*/function () {
29424           _createClass(SweepEvent, null, [{
29425             key: "compare",
29426             // for ordering sweep events in the sweep event queue
29427             value: function compare(a, b) {
29428               // favor event with a point that the sweep line hits first
29429               var ptCmp = SweepEvent.comparePoints(a.point, b.point);
29430               if (ptCmp !== 0) return ptCmp; // the points are the same, so link them if needed
29431
29432               if (a.point !== b.point) a.link(b); // favor right events over left
29433
29434               if (a.isLeft !== b.isLeft) return a.isLeft ? 1 : -1; // we have two matching left or right endpoints
29435               // ordering of this case is the same as for their segments
29436
29437               return Segment.compare(a.segment, b.segment);
29438             } // for ordering points in sweep line order
29439
29440           }, {
29441             key: "comparePoints",
29442             value: function comparePoints(aPt, bPt) {
29443               if (aPt.x < bPt.x) return -1;
29444               if (aPt.x > bPt.x) return 1;
29445               if (aPt.y < bPt.y) return -1;
29446               if (aPt.y > bPt.y) return 1;
29447               return 0;
29448             } // Warning: 'point' input will be modified and re-used (for performance)
29449
29450           }]);
29451
29452           function SweepEvent(point, isLeft) {
29453             _classCallCheck(this, SweepEvent);
29454
29455             if (point.events === undefined) point.events = [this];else point.events.push(this);
29456             this.point = point;
29457             this.isLeft = isLeft; // this.segment, this.otherSE set by factory
29458           }
29459
29460           _createClass(SweepEvent, [{
29461             key: "link",
29462             value: function link(other) {
29463               if (other.point === this.point) {
29464                 throw new Error('Tried to link already linked events');
29465               }
29466
29467               var otherEvents = other.point.events;
29468
29469               for (var i = 0, iMax = otherEvents.length; i < iMax; i++) {
29470                 var evt = otherEvents[i];
29471                 this.point.events.push(evt);
29472                 evt.point = this.point;
29473               }
29474
29475               this.checkForConsuming();
29476             }
29477             /* Do a pass over our linked events and check to see if any pair
29478              * of segments match, and should be consumed. */
29479
29480           }, {
29481             key: "checkForConsuming",
29482             value: function checkForConsuming() {
29483               // FIXME: The loops in this method run O(n^2) => no good.
29484               //        Maintain little ordered sweep event trees?
29485               //        Can we maintaining an ordering that avoids the need
29486               //        for the re-sorting with getLeftmostComparator in geom-out?
29487               // Compare each pair of events to see if other events also match
29488               var numEvents = this.point.events.length;
29489
29490               for (var i = 0; i < numEvents; i++) {
29491                 var evt1 = this.point.events[i];
29492                 if (evt1.segment.consumedBy !== undefined) continue;
29493
29494                 for (var j = i + 1; j < numEvents; j++) {
29495                   var evt2 = this.point.events[j];
29496                   if (evt2.consumedBy !== undefined) continue;
29497                   if (evt1.otherSE.point.events !== evt2.otherSE.point.events) continue;
29498                   evt1.segment.consume(evt2.segment);
29499                 }
29500               }
29501             }
29502           }, {
29503             key: "getAvailableLinkedEvents",
29504             value: function getAvailableLinkedEvents() {
29505               // point.events is always of length 2 or greater
29506               var events = [];
29507
29508               for (var i = 0, iMax = this.point.events.length; i < iMax; i++) {
29509                 var evt = this.point.events[i];
29510
29511                 if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) {
29512                   events.push(evt);
29513                 }
29514               }
29515
29516               return events;
29517             }
29518             /**
29519              * Returns a comparator function for sorting linked events that will
29520              * favor the event that will give us the smallest left-side angle.
29521              * All ring construction starts as low as possible heading to the right,
29522              * so by always turning left as sharp as possible we'll get polygons
29523              * without uncessary loops & holes.
29524              *
29525              * The comparator function has a compute cache such that it avoids
29526              * re-computing already-computed values.
29527              */
29528
29529           }, {
29530             key: "getLeftmostComparator",
29531             value: function getLeftmostComparator(baseEvent) {
29532               var _this = this;
29533
29534               var cache = new Map();
29535
29536               var fillCache = function fillCache(linkedEvent) {
29537                 var nextEvent = linkedEvent.otherSE;
29538                 cache.set(linkedEvent, {
29539                   sine: sineOfAngle(_this.point, baseEvent.point, nextEvent.point),
29540                   cosine: cosineOfAngle(_this.point, baseEvent.point, nextEvent.point)
29541                 });
29542               };
29543
29544               return function (a, b) {
29545                 if (!cache.has(a)) fillCache(a);
29546                 if (!cache.has(b)) fillCache(b);
29547
29548                 var _cache$get = cache.get(a),
29549                     asine = _cache$get.sine,
29550                     acosine = _cache$get.cosine;
29551
29552                 var _cache$get2 = cache.get(b),
29553                     bsine = _cache$get2.sine,
29554                     bcosine = _cache$get2.cosine; // both on or above x-axis
29555
29556
29557                 if (asine >= 0 && bsine >= 0) {
29558                   if (acosine < bcosine) return 1;
29559                   if (acosine > bcosine) return -1;
29560                   return 0;
29561                 } // both below x-axis
29562
29563
29564                 if (asine < 0 && bsine < 0) {
29565                   if (acosine < bcosine) return -1;
29566                   if (acosine > bcosine) return 1;
29567                   return 0;
29568                 } // one above x-axis, one below
29569
29570
29571                 if (bsine < asine) return -1;
29572                 if (bsine > asine) return 1;
29573                 return 0;
29574               };
29575             }
29576           }]);
29577
29578           return SweepEvent;
29579         }(); // segments and sweep events when all else is identical
29580
29581
29582         var segmentId = 0;
29583
29584         var Segment = /*#__PURE__*/function () {
29585           _createClass(Segment, null, [{
29586             key: "compare",
29587
29588             /* This compare() function is for ordering segments in the sweep
29589              * line tree, and does so according to the following criteria:
29590              *
29591              * Consider the vertical line that lies an infinestimal step to the
29592              * right of the right-more of the two left endpoints of the input
29593              * segments. Imagine slowly moving a point up from negative infinity
29594              * in the increasing y direction. Which of the two segments will that
29595              * point intersect first? That segment comes 'before' the other one.
29596              *
29597              * If neither segment would be intersected by such a line, (if one
29598              * or more of the segments are vertical) then the line to be considered
29599              * is directly on the right-more of the two left inputs.
29600              */
29601             value: function compare(a, b) {
29602               var alx = a.leftSE.point.x;
29603               var blx = b.leftSE.point.x;
29604               var arx = a.rightSE.point.x;
29605               var brx = b.rightSE.point.x; // check if they're even in the same vertical plane
29606
29607               if (brx < alx) return 1;
29608               if (arx < blx) return -1;
29609               var aly = a.leftSE.point.y;
29610               var bly = b.leftSE.point.y;
29611               var ary = a.rightSE.point.y;
29612               var bry = b.rightSE.point.y; // is left endpoint of segment B the right-more?
29613
29614               if (alx < blx) {
29615                 // are the two segments in the same horizontal plane?
29616                 if (bly < aly && bly < ary) return 1;
29617                 if (bly > aly && bly > ary) return -1; // is the B left endpoint colinear to segment A?
29618
29619                 var aCmpBLeft = a.comparePoint(b.leftSE.point);
29620                 if (aCmpBLeft < 0) return 1;
29621                 if (aCmpBLeft > 0) return -1; // is the A right endpoint colinear to segment B ?
29622
29623                 var bCmpARight = b.comparePoint(a.rightSE.point);
29624                 if (bCmpARight !== 0) return bCmpARight; // colinear segments, consider the one with left-more
29625                 // left endpoint to be first (arbitrary?)
29626
29627                 return -1;
29628               } // is left endpoint of segment A the right-more?
29629
29630
29631               if (alx > blx) {
29632                 if (aly < bly && aly < bry) return -1;
29633                 if (aly > bly && aly > bry) return 1; // is the A left endpoint colinear to segment B?
29634
29635                 var bCmpALeft = b.comparePoint(a.leftSE.point);
29636                 if (bCmpALeft !== 0) return bCmpALeft; // is the B right endpoint colinear to segment A?
29637
29638                 var aCmpBRight = a.comparePoint(b.rightSE.point);
29639                 if (aCmpBRight < 0) return 1;
29640                 if (aCmpBRight > 0) return -1; // colinear segments, consider the one with left-more
29641                 // left endpoint to be first (arbitrary?)
29642
29643                 return 1;
29644               } // if we get here, the two left endpoints are in the same
29645               // vertical plane, ie alx === blx
29646               // consider the lower left-endpoint to come first
29647
29648
29649               if (aly < bly) return -1;
29650               if (aly > bly) return 1; // left endpoints are identical
29651               // check for colinearity by using the left-more right endpoint
29652               // is the A right endpoint more left-more?
29653
29654               if (arx < brx) {
29655                 var _bCmpARight = b.comparePoint(a.rightSE.point);
29656
29657                 if (_bCmpARight !== 0) return _bCmpARight;
29658               } // is the B right endpoint more left-more?
29659
29660
29661               if (arx > brx) {
29662                 var _aCmpBRight = a.comparePoint(b.rightSE.point);
29663
29664                 if (_aCmpBRight < 0) return 1;
29665                 if (_aCmpBRight > 0) return -1;
29666               }
29667
29668               if (arx !== brx) {
29669                 // are these two [almost] vertical segments with opposite orientation?
29670                 // if so, the one with the lower right endpoint comes first
29671                 var ay = ary - aly;
29672                 var ax = arx - alx;
29673                 var by = bry - bly;
29674                 var bx = brx - blx;
29675                 if (ay > ax && by < bx) return 1;
29676                 if (ay < ax && by > bx) return -1;
29677               } // we have colinear segments with matching orientation
29678               // consider the one with more left-more right endpoint to be first
29679
29680
29681               if (arx > brx) return 1;
29682               if (arx < brx) return -1; // if we get here, two two right endpoints are in the same
29683               // vertical plane, ie arx === brx
29684               // consider the lower right-endpoint to come first
29685
29686               if (ary < bry) return -1;
29687               if (ary > bry) return 1; // right endpoints identical as well, so the segments are idential
29688               // fall back on creation order as consistent tie-breaker
29689
29690               if (a.id < b.id) return -1;
29691               if (a.id > b.id) return 1; // identical segment, ie a === b
29692
29693               return 0;
29694             }
29695             /* Warning: a reference to ringWindings input will be stored,
29696              *  and possibly will be later modified */
29697
29698           }]);
29699
29700           function Segment(leftSE, rightSE, rings, windings) {
29701             _classCallCheck(this, Segment);
29702
29703             this.id = ++segmentId;
29704             this.leftSE = leftSE;
29705             leftSE.segment = this;
29706             leftSE.otherSE = rightSE;
29707             this.rightSE = rightSE;
29708             rightSE.segment = this;
29709             rightSE.otherSE = leftSE;
29710             this.rings = rings;
29711             this.windings = windings; // left unset for performance, set later in algorithm
29712             // this.ringOut, this.consumedBy, this.prev
29713           }
29714
29715           _createClass(Segment, [{
29716             key: "replaceRightSE",
29717
29718             /* When a segment is split, the rightSE is replaced with a new sweep event */
29719             value: function replaceRightSE(newRightSE) {
29720               this.rightSE = newRightSE;
29721               this.rightSE.segment = this;
29722               this.rightSE.otherSE = this.leftSE;
29723               this.leftSE.otherSE = this.rightSE;
29724             }
29725           }, {
29726             key: "bbox",
29727             value: function bbox() {
29728               var y1 = this.leftSE.point.y;
29729               var y2 = this.rightSE.point.y;
29730               return {
29731                 ll: {
29732                   x: this.leftSE.point.x,
29733                   y: y1 < y2 ? y1 : y2
29734                 },
29735                 ur: {
29736                   x: this.rightSE.point.x,
29737                   y: y1 > y2 ? y1 : y2
29738                 }
29739               };
29740             }
29741             /* A vector from the left point to the right */
29742
29743           }, {
29744             key: "vector",
29745             value: function vector() {
29746               return {
29747                 x: this.rightSE.point.x - this.leftSE.point.x,
29748                 y: this.rightSE.point.y - this.leftSE.point.y
29749               };
29750             }
29751           }, {
29752             key: "isAnEndpoint",
29753             value: function isAnEndpoint(pt) {
29754               return pt.x === this.leftSE.point.x && pt.y === this.leftSE.point.y || pt.x === this.rightSE.point.x && pt.y === this.rightSE.point.y;
29755             }
29756             /* Compare this segment with a point.
29757              *
29758              * A point P is considered to be colinear to a segment if there
29759              * exists a distance D such that if we travel along the segment
29760              * from one * endpoint towards the other a distance D, we find
29761              * ourselves at point P.
29762              *
29763              * Return value indicates:
29764              *
29765              *   1: point lies above the segment (to the left of vertical)
29766              *   0: point is colinear to segment
29767              *  -1: point lies below the segment (to the right of vertical)
29768              */
29769
29770           }, {
29771             key: "comparePoint",
29772             value: function comparePoint(point) {
29773               if (this.isAnEndpoint(point)) return 0;
29774               var lPt = this.leftSE.point;
29775               var rPt = this.rightSE.point;
29776               var v = this.vector(); // Exactly vertical segments.
29777
29778               if (lPt.x === rPt.x) {
29779                 if (point.x === lPt.x) return 0;
29780                 return point.x < lPt.x ? 1 : -1;
29781               } // Nearly vertical segments with an intersection.
29782               // Check to see where a point on the line with matching Y coordinate is.
29783
29784
29785               var yDist = (point.y - lPt.y) / v.y;
29786               var xFromYDist = lPt.x + yDist * v.x;
29787               if (point.x === xFromYDist) return 0; // General case.
29788               // Check to see where a point on the line with matching X coordinate is.
29789
29790               var xDist = (point.x - lPt.x) / v.x;
29791               var yFromXDist = lPt.y + xDist * v.y;
29792               if (point.y === yFromXDist) return 0;
29793               return point.y < yFromXDist ? -1 : 1;
29794             }
29795             /**
29796              * Given another segment, returns the first non-trivial intersection
29797              * between the two segments (in terms of sweep line ordering), if it exists.
29798              *
29799              * A 'non-trivial' intersection is one that will cause one or both of the
29800              * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection:
29801              *
29802              *   * endpoint of segA with endpoint of segB --> trivial
29803              *   * endpoint of segA with point along segB --> non-trivial
29804              *   * endpoint of segB with point along segA --> non-trivial
29805              *   * point along segA with point along segB --> non-trivial
29806              *
29807              * If no non-trivial intersection exists, return null
29808              * Else, return null.
29809              */
29810
29811           }, {
29812             key: "getIntersection",
29813             value: function getIntersection(other) {
29814               // If bboxes don't overlap, there can't be any intersections
29815               var tBbox = this.bbox();
29816               var oBbox = other.bbox();
29817               var bboxOverlap = getBboxOverlap(tBbox, oBbox);
29818               if (bboxOverlap === null) return null; // We first check to see if the endpoints can be considered intersections.
29819               // This will 'snap' intersections to endpoints if possible, and will
29820               // handle cases of colinearity.
29821
29822               var tlp = this.leftSE.point;
29823               var trp = this.rightSE.point;
29824               var olp = other.leftSE.point;
29825               var orp = other.rightSE.point; // does each endpoint touch the other segment?
29826               // note that we restrict the 'touching' definition to only allow segments
29827               // to touch endpoints that lie forward from where we are in the sweep line pass
29828
29829               var touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0;
29830               var touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0;
29831               var touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0;
29832               var touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0; // do left endpoints match?
29833
29834               if (touchesThisLSE && touchesOtherLSE) {
29835                 // these two cases are for colinear segments with matching left
29836                 // endpoints, and one segment being longer than the other
29837                 if (touchesThisRSE && !touchesOtherRSE) return trp;
29838                 if (!touchesThisRSE && touchesOtherRSE) return orp; // either the two segments match exactly (two trival intersections)
29839                 // or just on their left endpoint (one trivial intersection
29840
29841                 return null;
29842               } // does this left endpoint matches (other doesn't)
29843
29844
29845               if (touchesThisLSE) {
29846                 // check for segments that just intersect on opposing endpoints
29847                 if (touchesOtherRSE) {
29848                   if (tlp.x === orp.x && tlp.y === orp.y) return null;
29849                 } // t-intersection on left endpoint
29850
29851
29852                 return tlp;
29853               } // does other left endpoint matches (this doesn't)
29854
29855
29856               if (touchesOtherLSE) {
29857                 // check for segments that just intersect on opposing endpoints
29858                 if (touchesThisRSE) {
29859                   if (trp.x === olp.x && trp.y === olp.y) return null;
29860                 } // t-intersection on left endpoint
29861
29862
29863                 return olp;
29864               } // trivial intersection on right endpoints
29865
29866
29867               if (touchesThisRSE && touchesOtherRSE) return null; // t-intersections on just one right endpoint
29868
29869               if (touchesThisRSE) return trp;
29870               if (touchesOtherRSE) return orp; // None of our endpoints intersect. Look for a general intersection between
29871               // infinite lines laid over the segments
29872
29873               var pt = intersection(tlp, this.vector(), olp, other.vector()); // are the segments parrallel? Note that if they were colinear with overlap,
29874               // they would have an endpoint intersection and that case was already handled above
29875
29876               if (pt === null) return null; // is the intersection found between the lines not on the segments?
29877
29878               if (!isInBbox(bboxOverlap, pt)) return null; // round the the computed point if needed
29879
29880               return rounder.round(pt.x, pt.y);
29881             }
29882             /**
29883              * Split the given segment into multiple segments on the given points.
29884              *  * Each existing segment will retain its leftSE and a new rightSE will be
29885              *    generated for it.
29886              *  * A new segment will be generated which will adopt the original segment's
29887              *    rightSE, and a new leftSE will be generated for it.
29888              *  * If there are more than two points given to split on, new segments
29889              *    in the middle will be generated with new leftSE and rightSE's.
29890              *  * An array of the newly generated SweepEvents will be returned.
29891              *
29892              * Warning: input array of points is modified
29893              */
29894
29895           }, {
29896             key: "split",
29897             value: function split(point) {
29898               var newEvents = [];
29899               var alreadyLinked = point.events !== undefined;
29900               var newLeftSE = new SweepEvent(point, true);
29901               var newRightSE = new SweepEvent(point, false);
29902               var oldRightSE = this.rightSE;
29903               this.replaceRightSE(newRightSE);
29904               newEvents.push(newRightSE);
29905               newEvents.push(newLeftSE);
29906               var newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice()); // when splitting a nearly vertical downward-facing segment,
29907               // sometimes one of the resulting new segments is vertical, in which
29908               // case its left and right events may need to be swapped
29909
29910               if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) {
29911                 newSeg.swapEvents();
29912               }
29913
29914               if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) {
29915                 this.swapEvents();
29916               } // in the point we just used to create new sweep events with was already
29917               // linked to other events, we need to check if either of the affected
29918               // segments should be consumed
29919
29920
29921               if (alreadyLinked) {
29922                 newLeftSE.checkForConsuming();
29923                 newRightSE.checkForConsuming();
29924               }
29925
29926               return newEvents;
29927             }
29928             /* Swap which event is left and right */
29929
29930           }, {
29931             key: "swapEvents",
29932             value: function swapEvents() {
29933               var tmpEvt = this.rightSE;
29934               this.rightSE = this.leftSE;
29935               this.leftSE = tmpEvt;
29936               this.leftSE.isLeft = true;
29937               this.rightSE.isLeft = false;
29938
29939               for (var i = 0, iMax = this.windings.length; i < iMax; i++) {
29940                 this.windings[i] *= -1;
29941               }
29942             }
29943             /* Consume another segment. We take their rings under our wing
29944              * and mark them as consumed. Use for perfectly overlapping segments */
29945
29946           }, {
29947             key: "consume",
29948             value: function consume(other) {
29949               var consumer = this;
29950               var consumee = other;
29951
29952               while (consumer.consumedBy) {
29953                 consumer = consumer.consumedBy;
29954               }
29955
29956               while (consumee.consumedBy) {
29957                 consumee = consumee.consumedBy;
29958               }
29959
29960               var cmp = Segment.compare(consumer, consumee);
29961               if (cmp === 0) return; // already consumed
29962               // the winner of the consumption is the earlier segment
29963               // according to sweep line ordering
29964
29965               if (cmp > 0) {
29966                 var tmp = consumer;
29967                 consumer = consumee;
29968                 consumee = tmp;
29969               } // make sure a segment doesn't consume it's prev
29970
29971
29972               if (consumer.prev === consumee) {
29973                 var _tmp = consumer;
29974                 consumer = consumee;
29975                 consumee = _tmp;
29976               }
29977
29978               for (var i = 0, iMax = consumee.rings.length; i < iMax; i++) {
29979                 var ring = consumee.rings[i];
29980                 var winding = consumee.windings[i];
29981                 var index = consumer.rings.indexOf(ring);
29982
29983                 if (index === -1) {
29984                   consumer.rings.push(ring);
29985                   consumer.windings.push(winding);
29986                 } else consumer.windings[index] += winding;
29987               }
29988
29989               consumee.rings = null;
29990               consumee.windings = null;
29991               consumee.consumedBy = consumer; // mark sweep events consumed as to maintain ordering in sweep event queue
29992
29993               consumee.leftSE.consumedBy = consumer.leftSE;
29994               consumee.rightSE.consumedBy = consumer.rightSE;
29995             }
29996             /* The first segment previous segment chain that is in the result */
29997
29998           }, {
29999             key: "prevInResult",
30000             value: function prevInResult() {
30001               if (this._prevInResult !== undefined) return this._prevInResult;
30002               if (!this.prev) this._prevInResult = null;else if (this.prev.isInResult()) this._prevInResult = this.prev;else this._prevInResult = this.prev.prevInResult();
30003               return this._prevInResult;
30004             }
30005           }, {
30006             key: "beforeState",
30007             value: function beforeState() {
30008               if (this._beforeState !== undefined) return this._beforeState;
30009               if (!this.prev) this._beforeState = {
30010                 rings: [],
30011                 windings: [],
30012                 multiPolys: []
30013               };else {
30014                 var seg = this.prev.consumedBy || this.prev;
30015                 this._beforeState = seg.afterState();
30016               }
30017               return this._beforeState;
30018             }
30019           }, {
30020             key: "afterState",
30021             value: function afterState() {
30022               if (this._afterState !== undefined) return this._afterState;
30023               var beforeState = this.beforeState();
30024               this._afterState = {
30025                 rings: beforeState.rings.slice(0),
30026                 windings: beforeState.windings.slice(0),
30027                 multiPolys: []
30028               };
30029               var ringsAfter = this._afterState.rings;
30030               var windingsAfter = this._afterState.windings;
30031               var mpsAfter = this._afterState.multiPolys; // calculate ringsAfter, windingsAfter
30032
30033               for (var i = 0, iMax = this.rings.length; i < iMax; i++) {
30034                 var ring = this.rings[i];
30035                 var winding = this.windings[i];
30036                 var index = ringsAfter.indexOf(ring);
30037
30038                 if (index === -1) {
30039                   ringsAfter.push(ring);
30040                   windingsAfter.push(winding);
30041                 } else windingsAfter[index] += winding;
30042               } // calcualte polysAfter
30043
30044
30045               var polysAfter = [];
30046               var polysExclude = [];
30047
30048               for (var _i = 0, _iMax = ringsAfter.length; _i < _iMax; _i++) {
30049                 if (windingsAfter[_i] === 0) continue; // non-zero rule
30050
30051                 var _ring = ringsAfter[_i];
30052                 var poly = _ring.poly;
30053                 if (polysExclude.indexOf(poly) !== -1) continue;
30054                 if (_ring.isExterior) polysAfter.push(poly);else {
30055                   if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly);
30056
30057                   var _index = polysAfter.indexOf(_ring.poly);
30058
30059                   if (_index !== -1) polysAfter.splice(_index, 1);
30060                 }
30061               } // calculate multiPolysAfter
30062
30063
30064               for (var _i2 = 0, _iMax2 = polysAfter.length; _i2 < _iMax2; _i2++) {
30065                 var mp = polysAfter[_i2].multiPoly;
30066                 if (mpsAfter.indexOf(mp) === -1) mpsAfter.push(mp);
30067               }
30068
30069               return this._afterState;
30070             }
30071             /* Is this segment part of the final result? */
30072
30073           }, {
30074             key: "isInResult",
30075             value: function isInResult() {
30076               // if we've been consumed, we're not in the result
30077               if (this.consumedBy) return false;
30078               if (this._isInResult !== undefined) return this._isInResult;
30079               var mpsBefore = this.beforeState().multiPolys;
30080               var mpsAfter = this.afterState().multiPolys;
30081
30082               switch (operation.type) {
30083                 case 'union':
30084                   {
30085                     // UNION - included iff:
30086                     //  * On one side of us there is 0 poly interiors AND
30087                     //  * On the other side there is 1 or more.
30088                     var noBefores = mpsBefore.length === 0;
30089                     var noAfters = mpsAfter.length === 0;
30090                     this._isInResult = noBefores !== noAfters;
30091                     break;
30092                   }
30093
30094                 case 'intersection':
30095                   {
30096                     // INTERSECTION - included iff:
30097                     //  * on one side of us all multipolys are rep. with poly interiors AND
30098                     //  * on the other side of us, not all multipolys are repsented
30099                     //    with poly interiors
30100                     var least;
30101                     var most;
30102
30103                     if (mpsBefore.length < mpsAfter.length) {
30104                       least = mpsBefore.length;
30105                       most = mpsAfter.length;
30106                     } else {
30107                       least = mpsAfter.length;
30108                       most = mpsBefore.length;
30109                     }
30110
30111                     this._isInResult = most === operation.numMultiPolys && least < most;
30112                     break;
30113                   }
30114
30115                 case 'xor':
30116                   {
30117                     // XOR - included iff:
30118                     //  * the difference between the number of multipolys represented
30119                     //    with poly interiors on our two sides is an odd number
30120                     var diff = Math.abs(mpsBefore.length - mpsAfter.length);
30121                     this._isInResult = diff % 2 === 1;
30122                     break;
30123                   }
30124
30125                 case 'difference':
30126                   {
30127                     // DIFFERENCE included iff:
30128                     //  * on exactly one side, we have just the subject
30129                     var isJustSubject = function isJustSubject(mps) {
30130                       return mps.length === 1 && mps[0].isSubject;
30131                     };
30132
30133                     this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter);
30134                     break;
30135                   }
30136
30137                 default:
30138                   throw new Error("Unrecognized operation type found ".concat(operation.type));
30139               }
30140
30141               return this._isInResult;
30142             }
30143           }], [{
30144             key: "fromRing",
30145             value: function fromRing(pt1, pt2, ring) {
30146               var leftPt, rightPt, winding; // ordering the two points according to sweep line ordering
30147
30148               var cmpPts = SweepEvent.comparePoints(pt1, pt2);
30149
30150               if (cmpPts < 0) {
30151                 leftPt = pt1;
30152                 rightPt = pt2;
30153                 winding = 1;
30154               } else if (cmpPts > 0) {
30155                 leftPt = pt2;
30156                 rightPt = pt1;
30157                 winding = -1;
30158               } else throw new Error("Tried to create degenerate segment at [".concat(pt1.x, ", ").concat(pt1.y, "]"));
30159
30160               var leftSE = new SweepEvent(leftPt, true);
30161               var rightSE = new SweepEvent(rightPt, false);
30162               return new Segment(leftSE, rightSE, [ring], [winding]);
30163             }
30164           }]);
30165
30166           return Segment;
30167         }();
30168
30169         var RingIn = /*#__PURE__*/function () {
30170           function RingIn(geomRing, poly, isExterior) {
30171             _classCallCheck(this, RingIn);
30172
30173             if (!Array.isArray(geomRing) || geomRing.length === 0) {
30174               throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30175             }
30176
30177             this.poly = poly;
30178             this.isExterior = isExterior;
30179             this.segments = [];
30180
30181             if (typeof geomRing[0][0] !== 'number' || typeof geomRing[0][1] !== 'number') {
30182               throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30183             }
30184
30185             var firstPoint = rounder.round(geomRing[0][0], geomRing[0][1]);
30186             this.bbox = {
30187               ll: {
30188                 x: firstPoint.x,
30189                 y: firstPoint.y
30190               },
30191               ur: {
30192                 x: firstPoint.x,
30193                 y: firstPoint.y
30194               }
30195             };
30196             var prevPoint = firstPoint;
30197
30198             for (var i = 1, iMax = geomRing.length; i < iMax; i++) {
30199               if (typeof geomRing[i][0] !== 'number' || typeof geomRing[i][1] !== 'number') {
30200                 throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30201               }
30202
30203               var point = rounder.round(geomRing[i][0], geomRing[i][1]); // skip repeated points
30204
30205               if (point.x === prevPoint.x && point.y === prevPoint.y) continue;
30206               this.segments.push(Segment.fromRing(prevPoint, point, this));
30207               if (point.x < this.bbox.ll.x) this.bbox.ll.x = point.x;
30208               if (point.y < this.bbox.ll.y) this.bbox.ll.y = point.y;
30209               if (point.x > this.bbox.ur.x) this.bbox.ur.x = point.x;
30210               if (point.y > this.bbox.ur.y) this.bbox.ur.y = point.y;
30211               prevPoint = point;
30212             } // add segment from last to first if last is not the same as first
30213
30214
30215             if (firstPoint.x !== prevPoint.x || firstPoint.y !== prevPoint.y) {
30216               this.segments.push(Segment.fromRing(prevPoint, firstPoint, this));
30217             }
30218           }
30219
30220           _createClass(RingIn, [{
30221             key: "getSweepEvents",
30222             value: function getSweepEvents() {
30223               var sweepEvents = [];
30224
30225               for (var i = 0, iMax = this.segments.length; i < iMax; i++) {
30226                 var segment = this.segments[i];
30227                 sweepEvents.push(segment.leftSE);
30228                 sweepEvents.push(segment.rightSE);
30229               }
30230
30231               return sweepEvents;
30232             }
30233           }]);
30234
30235           return RingIn;
30236         }();
30237
30238         var PolyIn = /*#__PURE__*/function () {
30239           function PolyIn(geomPoly, multiPoly) {
30240             _classCallCheck(this, PolyIn);
30241
30242             if (!Array.isArray(geomPoly)) {
30243               throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30244             }
30245
30246             this.exteriorRing = new RingIn(geomPoly[0], this, true); // copy by value
30247
30248             this.bbox = {
30249               ll: {
30250                 x: this.exteriorRing.bbox.ll.x,
30251                 y: this.exteriorRing.bbox.ll.y
30252               },
30253               ur: {
30254                 x: this.exteriorRing.bbox.ur.x,
30255                 y: this.exteriorRing.bbox.ur.y
30256               }
30257             };
30258             this.interiorRings = [];
30259
30260             for (var i = 1, iMax = geomPoly.length; i < iMax; i++) {
30261               var ring = new RingIn(geomPoly[i], this, false);
30262               if (ring.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = ring.bbox.ll.x;
30263               if (ring.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = ring.bbox.ll.y;
30264               if (ring.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = ring.bbox.ur.x;
30265               if (ring.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = ring.bbox.ur.y;
30266               this.interiorRings.push(ring);
30267             }
30268
30269             this.multiPoly = multiPoly;
30270           }
30271
30272           _createClass(PolyIn, [{
30273             key: "getSweepEvents",
30274             value: function getSweepEvents() {
30275               var sweepEvents = this.exteriorRing.getSweepEvents();
30276
30277               for (var i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
30278                 var ringSweepEvents = this.interiorRings[i].getSweepEvents();
30279
30280                 for (var j = 0, jMax = ringSweepEvents.length; j < jMax; j++) {
30281                   sweepEvents.push(ringSweepEvents[j]);
30282                 }
30283               }
30284
30285               return sweepEvents;
30286             }
30287           }]);
30288
30289           return PolyIn;
30290         }();
30291
30292         var MultiPolyIn = /*#__PURE__*/function () {
30293           function MultiPolyIn(geom, isSubject) {
30294             _classCallCheck(this, MultiPolyIn);
30295
30296             if (!Array.isArray(geom)) {
30297               throw new Error('Input geometry is not a valid Polygon or MultiPolygon');
30298             }
30299
30300             try {
30301               // if the input looks like a polygon, convert it to a multipolygon
30302               if (typeof geom[0][0][0] === 'number') geom = [geom];
30303             } catch (ex) {// The input is either malformed or has empty arrays.
30304               // In either case, it will be handled later on.
30305             }
30306
30307             this.polys = [];
30308             this.bbox = {
30309               ll: {
30310                 x: Number.POSITIVE_INFINITY,
30311                 y: Number.POSITIVE_INFINITY
30312               },
30313               ur: {
30314                 x: Number.NEGATIVE_INFINITY,
30315                 y: Number.NEGATIVE_INFINITY
30316               }
30317             };
30318
30319             for (var i = 0, iMax = geom.length; i < iMax; i++) {
30320               var poly = new PolyIn(geom[i], this);
30321               if (poly.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = poly.bbox.ll.x;
30322               if (poly.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = poly.bbox.ll.y;
30323               if (poly.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = poly.bbox.ur.x;
30324               if (poly.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = poly.bbox.ur.y;
30325               this.polys.push(poly);
30326             }
30327
30328             this.isSubject = isSubject;
30329           }
30330
30331           _createClass(MultiPolyIn, [{
30332             key: "getSweepEvents",
30333             value: function getSweepEvents() {
30334               var sweepEvents = [];
30335
30336               for (var i = 0, iMax = this.polys.length; i < iMax; i++) {
30337                 var polySweepEvents = this.polys[i].getSweepEvents();
30338
30339                 for (var j = 0, jMax = polySweepEvents.length; j < jMax; j++) {
30340                   sweepEvents.push(polySweepEvents[j]);
30341                 }
30342               }
30343
30344               return sweepEvents;
30345             }
30346           }]);
30347
30348           return MultiPolyIn;
30349         }();
30350
30351         var RingOut = /*#__PURE__*/function () {
30352           _createClass(RingOut, null, [{
30353             key: "factory",
30354
30355             /* Given the segments from the sweep line pass, compute & return a series
30356              * of closed rings from all the segments marked to be part of the result */
30357             value: function factory(allSegments) {
30358               var ringsOut = [];
30359
30360               for (var i = 0, iMax = allSegments.length; i < iMax; i++) {
30361                 var segment = allSegments[i];
30362                 if (!segment.isInResult() || segment.ringOut) continue;
30363                 var prevEvent = null;
30364                 var event = segment.leftSE;
30365                 var nextEvent = segment.rightSE;
30366                 var events = [event];
30367                 var startingPoint = event.point;
30368                 var intersectionLEs = [];
30369                 /* Walk the chain of linked events to form a closed ring */
30370
30371                 while (true) {
30372                   prevEvent = event;
30373                   event = nextEvent;
30374                   events.push(event);
30375                   /* Is the ring complete? */
30376
30377                   if (event.point === startingPoint) break;
30378
30379                   while (true) {
30380                     var availableLEs = event.getAvailableLinkedEvents();
30381                     /* Did we hit a dead end? This shouldn't happen. Indicates some earlier
30382                      * part of the algorithm malfunctioned... please file a bug report. */
30383
30384                     if (availableLEs.length === 0) {
30385                       var firstPt = events[0].point;
30386                       var lastPt = events[events.length - 1].point;
30387                       throw new Error("Unable to complete output ring starting at [".concat(firstPt.x, ",") + " ".concat(firstPt.y, "]. Last matching segment found ends at") + " [".concat(lastPt.x, ", ").concat(lastPt.y, "]."));
30388                     }
30389                     /* Only one way to go, so cotinue on the path */
30390
30391
30392                     if (availableLEs.length === 1) {
30393                       nextEvent = availableLEs[0].otherSE;
30394                       break;
30395                     }
30396                     /* We must have an intersection. Check for a completed loop */
30397
30398
30399                     var indexLE = null;
30400
30401                     for (var j = 0, jMax = intersectionLEs.length; j < jMax; j++) {
30402                       if (intersectionLEs[j].point === event.point) {
30403                         indexLE = j;
30404                         break;
30405                       }
30406                     }
30407                     /* Found a completed loop. Cut that off and make a ring */
30408
30409
30410                     if (indexLE !== null) {
30411                       var intersectionLE = intersectionLEs.splice(indexLE)[0];
30412                       var ringEvents = events.splice(intersectionLE.index);
30413                       ringEvents.unshift(ringEvents[0].otherSE);
30414                       ringsOut.push(new RingOut(ringEvents.reverse()));
30415                       continue;
30416                     }
30417                     /* register the intersection */
30418
30419
30420                     intersectionLEs.push({
30421                       index: events.length,
30422                       point: event.point
30423                     });
30424                     /* Choose the left-most option to continue the walk */
30425
30426                     var comparator = event.getLeftmostComparator(prevEvent);
30427                     nextEvent = availableLEs.sort(comparator)[0].otherSE;
30428                     break;
30429                   }
30430                 }
30431
30432                 ringsOut.push(new RingOut(events));
30433               }
30434
30435               return ringsOut;
30436             }
30437           }]);
30438
30439           function RingOut(events) {
30440             _classCallCheck(this, RingOut);
30441
30442             this.events = events;
30443
30444             for (var i = 0, iMax = events.length; i < iMax; i++) {
30445               events[i].segment.ringOut = this;
30446             }
30447
30448             this.poly = null;
30449           }
30450
30451           _createClass(RingOut, [{
30452             key: "getGeom",
30453             value: function getGeom() {
30454               // Remove superfluous points (ie extra points along a straight line),
30455               var prevPt = this.events[0].point;
30456               var points = [prevPt];
30457
30458               for (var i = 1, iMax = this.events.length - 1; i < iMax; i++) {
30459                 var _pt = this.events[i].point;
30460                 var _nextPt = this.events[i + 1].point;
30461                 if (compareVectorAngles(_pt, prevPt, _nextPt) === 0) continue;
30462                 points.push(_pt);
30463                 prevPt = _pt;
30464               } // ring was all (within rounding error of angle calc) colinear points
30465
30466
30467               if (points.length === 1) return null; // check if the starting point is necessary
30468
30469               var pt = points[0];
30470               var nextPt = points[1];
30471               if (compareVectorAngles(pt, prevPt, nextPt) === 0) points.shift();
30472               points.push(points[0]);
30473               var step = this.isExteriorRing() ? 1 : -1;
30474               var iStart = this.isExteriorRing() ? 0 : points.length - 1;
30475               var iEnd = this.isExteriorRing() ? points.length : -1;
30476               var orderedPoints = [];
30477
30478               for (var _i = iStart; _i != iEnd; _i += step) {
30479                 orderedPoints.push([points[_i].x, points[_i].y]);
30480               }
30481
30482               return orderedPoints;
30483             }
30484           }, {
30485             key: "isExteriorRing",
30486             value: function isExteriorRing() {
30487               if (this._isExteriorRing === undefined) {
30488                 var enclosing = this.enclosingRing();
30489                 this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true;
30490               }
30491
30492               return this._isExteriorRing;
30493             }
30494           }, {
30495             key: "enclosingRing",
30496             value: function enclosingRing() {
30497               if (this._enclosingRing === undefined) {
30498                 this._enclosingRing = this._calcEnclosingRing();
30499               }
30500
30501               return this._enclosingRing;
30502             }
30503             /* Returns the ring that encloses this one, if any */
30504
30505           }, {
30506             key: "_calcEnclosingRing",
30507             value: function _calcEnclosingRing() {
30508               // start with the ealier sweep line event so that the prevSeg
30509               // chain doesn't lead us inside of a loop of ours
30510               var leftMostEvt = this.events[0];
30511
30512               for (var i = 1, iMax = this.events.length; i < iMax; i++) {
30513                 var evt = this.events[i];
30514                 if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt;
30515               }
30516
30517               var prevSeg = leftMostEvt.segment.prevInResult();
30518               var prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
30519
30520               while (true) {
30521                 // no segment found, thus no ring can enclose us
30522                 if (!prevSeg) return null; // no segments below prev segment found, thus the ring of the prev
30523                 // segment must loop back around and enclose us
30524
30525                 if (!prevPrevSeg) return prevSeg.ringOut; // if the two segments are of different rings, the ring of the prev
30526                 // segment must either loop around us or the ring of the prev prev
30527                 // seg, which would make us and the ring of the prev peers
30528
30529                 if (prevPrevSeg.ringOut !== prevSeg.ringOut) {
30530                   if (prevPrevSeg.ringOut.enclosingRing() !== prevSeg.ringOut) {
30531                     return prevSeg.ringOut;
30532                   } else return prevSeg.ringOut.enclosingRing();
30533                 } // two segments are from the same ring, so this was a penisula
30534                 // of that ring. iterate downward, keep searching
30535
30536
30537                 prevSeg = prevPrevSeg.prevInResult();
30538                 prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null;
30539               }
30540             }
30541           }]);
30542
30543           return RingOut;
30544         }();
30545
30546         var PolyOut = /*#__PURE__*/function () {
30547           function PolyOut(exteriorRing) {
30548             _classCallCheck(this, PolyOut);
30549
30550             this.exteriorRing = exteriorRing;
30551             exteriorRing.poly = this;
30552             this.interiorRings = [];
30553           }
30554
30555           _createClass(PolyOut, [{
30556             key: "addInterior",
30557             value: function addInterior(ring) {
30558               this.interiorRings.push(ring);
30559               ring.poly = this;
30560             }
30561           }, {
30562             key: "getGeom",
30563             value: function getGeom() {
30564               var geom = [this.exteriorRing.getGeom()]; // exterior ring was all (within rounding error of angle calc) colinear points
30565
30566               if (geom[0] === null) return null;
30567
30568               for (var i = 0, iMax = this.interiorRings.length; i < iMax; i++) {
30569                 var ringGeom = this.interiorRings[i].getGeom(); // interior ring was all (within rounding error of angle calc) colinear points
30570
30571                 if (ringGeom === null) continue;
30572                 geom.push(ringGeom);
30573               }
30574
30575               return geom;
30576             }
30577           }]);
30578
30579           return PolyOut;
30580         }();
30581
30582         var MultiPolyOut = /*#__PURE__*/function () {
30583           function MultiPolyOut(rings) {
30584             _classCallCheck(this, MultiPolyOut);
30585
30586             this.rings = rings;
30587             this.polys = this._composePolys(rings);
30588           }
30589
30590           _createClass(MultiPolyOut, [{
30591             key: "getGeom",
30592             value: function getGeom() {
30593               var geom = [];
30594
30595               for (var i = 0, iMax = this.polys.length; i < iMax; i++) {
30596                 var polyGeom = this.polys[i].getGeom(); // exterior ring was all (within rounding error of angle calc) colinear points
30597
30598                 if (polyGeom === null) continue;
30599                 geom.push(polyGeom);
30600               }
30601
30602               return geom;
30603             }
30604           }, {
30605             key: "_composePolys",
30606             value: function _composePolys(rings) {
30607               var polys = [];
30608
30609               for (var i = 0, iMax = rings.length; i < iMax; i++) {
30610                 var ring = rings[i];
30611                 if (ring.poly) continue;
30612                 if (ring.isExteriorRing()) polys.push(new PolyOut(ring));else {
30613                   var enclosingRing = ring.enclosingRing();
30614                   if (!enclosingRing.poly) polys.push(new PolyOut(enclosingRing));
30615                   enclosingRing.poly.addInterior(ring);
30616                 }
30617               }
30618
30619               return polys;
30620             }
30621           }]);
30622
30623           return MultiPolyOut;
30624         }();
30625         /**
30626          * NOTE:  We must be careful not to change any segments while
30627          *        they are in the SplayTree. AFAIK, there's no way to tell
30628          *        the tree to rebalance itself - thus before splitting
30629          *        a segment that's in the tree, we remove it from the tree,
30630          *        do the split, then re-insert it. (Even though splitting a
30631          *        segment *shouldn't* change its correct position in the
30632          *        sweep line tree, the reality is because of rounding errors,
30633          *        it sometimes does.)
30634          */
30635
30636
30637         var SweepLine = /*#__PURE__*/function () {
30638           function SweepLine(queue) {
30639             var comparator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Segment.compare;
30640
30641             _classCallCheck(this, SweepLine);
30642
30643             this.queue = queue;
30644             this.tree = new Tree(comparator);
30645             this.segments = [];
30646           }
30647
30648           _createClass(SweepLine, [{
30649             key: "process",
30650             value: function process(event) {
30651               var segment = event.segment;
30652               var newEvents = []; // if we've already been consumed by another segment,
30653               // clean up our body parts and get out
30654
30655               if (event.consumedBy) {
30656                 if (event.isLeft) this.queue.remove(event.otherSE);else this.tree.remove(segment);
30657                 return newEvents;
30658               }
30659
30660               var node = event.isLeft ? this.tree.insert(segment) : this.tree.find(segment);
30661               if (!node) throw new Error("Unable to find segment #".concat(segment.id, " ") + "[".concat(segment.leftSE.point.x, ", ").concat(segment.leftSE.point.y, "] -> ") + "[".concat(segment.rightSE.point.x, ", ").concat(segment.rightSE.point.y, "] ") + 'in SweepLine tree. Please submit a bug report.');
30662               var prevNode = node;
30663               var nextNode = node;
30664               var prevSeg = undefined;
30665               var nextSeg = undefined; // skip consumed segments still in tree
30666
30667               while (prevSeg === undefined) {
30668                 prevNode = this.tree.prev(prevNode);
30669                 if (prevNode === null) prevSeg = null;else if (prevNode.key.consumedBy === undefined) prevSeg = prevNode.key;
30670               } // skip consumed segments still in tree
30671
30672
30673               while (nextSeg === undefined) {
30674                 nextNode = this.tree.next(nextNode);
30675                 if (nextNode === null) nextSeg = null;else if (nextNode.key.consumedBy === undefined) nextSeg = nextNode.key;
30676               }
30677
30678               if (event.isLeft) {
30679                 // Check for intersections against the previous segment in the sweep line
30680                 var prevMySplitter = null;
30681
30682                 if (prevSeg) {
30683                   var prevInter = prevSeg.getIntersection(segment);
30684
30685                   if (prevInter !== null) {
30686                     if (!segment.isAnEndpoint(prevInter)) prevMySplitter = prevInter;
30687
30688                     if (!prevSeg.isAnEndpoint(prevInter)) {
30689                       var newEventsFromSplit = this._splitSafely(prevSeg, prevInter);
30690
30691                       for (var i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) {
30692                         newEvents.push(newEventsFromSplit[i]);
30693                       }
30694                     }
30695                   }
30696                 } // Check for intersections against the next segment in the sweep line
30697
30698
30699                 var nextMySplitter = null;
30700
30701                 if (nextSeg) {
30702                   var nextInter = nextSeg.getIntersection(segment);
30703
30704                   if (nextInter !== null) {
30705                     if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter;
30706
30707                     if (!nextSeg.isAnEndpoint(nextInter)) {
30708                       var _newEventsFromSplit = this._splitSafely(nextSeg, nextInter);
30709
30710                       for (var _i = 0, _iMax = _newEventsFromSplit.length; _i < _iMax; _i++) {
30711                         newEvents.push(_newEventsFromSplit[_i]);
30712                       }
30713                     }
30714                   }
30715                 } // For simplicity, even if we find more than one intersection we only
30716                 // spilt on the 'earliest' (sweep-line style) of the intersections.
30717                 // The other intersection will be handled in a future process().
30718
30719
30720                 if (prevMySplitter !== null || nextMySplitter !== null) {
30721                   var mySplitter = null;
30722                   if (prevMySplitter === null) mySplitter = nextMySplitter;else if (nextMySplitter === null) mySplitter = prevMySplitter;else {
30723                     var cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter);
30724                     mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter;
30725                   } // Rounding errors can cause changes in ordering,
30726                   // so remove afected segments and right sweep events before splitting
30727
30728                   this.queue.remove(segment.rightSE);
30729                   newEvents.push(segment.rightSE);
30730
30731                   var _newEventsFromSplit2 = segment.split(mySplitter);
30732
30733                   for (var _i2 = 0, _iMax2 = _newEventsFromSplit2.length; _i2 < _iMax2; _i2++) {
30734                     newEvents.push(_newEventsFromSplit2[_i2]);
30735                   }
30736                 }
30737
30738                 if (newEvents.length > 0) {
30739                   // We found some intersections, so re-do the current event to
30740                   // make sure sweep line ordering is totally consistent for later
30741                   // use with the segment 'prev' pointers
30742                   this.tree.remove(segment);
30743                   newEvents.push(event);
30744                 } else {
30745                   // done with left event
30746                   this.segments.push(segment);
30747                   segment.prev = prevSeg;
30748                 }
30749               } else {
30750                 // event.isRight
30751                 // since we're about to be removed from the sweep line, check for
30752                 // intersections between our previous and next segments
30753                 if (prevSeg && nextSeg) {
30754                   var inter = prevSeg.getIntersection(nextSeg);
30755
30756                   if (inter !== null) {
30757                     if (!prevSeg.isAnEndpoint(inter)) {
30758                       var _newEventsFromSplit3 = this._splitSafely(prevSeg, inter);
30759
30760                       for (var _i3 = 0, _iMax3 = _newEventsFromSplit3.length; _i3 < _iMax3; _i3++) {
30761                         newEvents.push(_newEventsFromSplit3[_i3]);
30762                       }
30763                     }
30764
30765                     if (!nextSeg.isAnEndpoint(inter)) {
30766                       var _newEventsFromSplit4 = this._splitSafely(nextSeg, inter);
30767
30768                       for (var _i4 = 0, _iMax4 = _newEventsFromSplit4.length; _i4 < _iMax4; _i4++) {
30769                         newEvents.push(_newEventsFromSplit4[_i4]);
30770                       }
30771                     }
30772                   }
30773                 }
30774
30775                 this.tree.remove(segment);
30776               }
30777
30778               return newEvents;
30779             }
30780             /* Safely split a segment that is currently in the datastructures
30781              * IE - a segment other than the one that is currently being processed. */
30782
30783           }, {
30784             key: "_splitSafely",
30785             value: function _splitSafely(seg, pt) {
30786               // Rounding errors can cause changes in ordering,
30787               // so remove afected segments and right sweep events before splitting
30788               // removeNode() doesn't work, so have re-find the seg
30789               // https://github.com/w8r/splay-tree/pull/5
30790               this.tree.remove(seg);
30791               var rightSE = seg.rightSE;
30792               this.queue.remove(rightSE);
30793               var newEvents = seg.split(pt);
30794               newEvents.push(rightSE); // splitting can trigger consumption
30795
30796               if (seg.consumedBy === undefined) this.tree.insert(seg);
30797               return newEvents;
30798             }
30799           }]);
30800
30801           return SweepLine;
30802         }();
30803
30804         var POLYGON_CLIPPING_MAX_QUEUE_SIZE = typeof process !== 'undefined' && process.env.POLYGON_CLIPPING_MAX_QUEUE_SIZE || 1000000;
30805         var POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS = typeof process !== 'undefined' && process.env.POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS || 1000000;
30806
30807         var Operation = /*#__PURE__*/function () {
30808           function Operation() {
30809             _classCallCheck(this, Operation);
30810           }
30811
30812           _createClass(Operation, [{
30813             key: "run",
30814             value: function run(type, geom, moreGeoms) {
30815               operation.type = type;
30816               rounder.reset();
30817               /* Convert inputs to MultiPoly objects */
30818
30819               var multipolys = [new MultiPolyIn(geom, true)];
30820
30821               for (var i = 0, iMax = moreGeoms.length; i < iMax; i++) {
30822                 multipolys.push(new MultiPolyIn(moreGeoms[i], false));
30823               }
30824
30825               operation.numMultiPolys = multipolys.length;
30826               /* BBox optimization for difference operation
30827                * If the bbox of a multipolygon that's part of the clipping doesn't
30828                * intersect the bbox of the subject at all, we can just drop that
30829                * multiploygon. */
30830
30831               if (operation.type === 'difference') {
30832                 // in place removal
30833                 var subject = multipolys[0];
30834                 var _i = 1;
30835
30836                 while (_i < multipolys.length) {
30837                   if (getBboxOverlap(multipolys[_i].bbox, subject.bbox) !== null) _i++;else multipolys.splice(_i, 1);
30838                 }
30839               }
30840               /* BBox optimization for intersection operation
30841                * If we can find any pair of multipolygons whose bbox does not overlap,
30842                * then the result will be empty. */
30843
30844
30845               if (operation.type === 'intersection') {
30846                 // TODO: this is O(n^2) in number of polygons. By sorting the bboxes,
30847                 //       it could be optimized to O(n * ln(n))
30848                 for (var _i2 = 0, _iMax = multipolys.length; _i2 < _iMax; _i2++) {
30849                   var mpA = multipolys[_i2];
30850
30851                   for (var j = _i2 + 1, jMax = multipolys.length; j < jMax; j++) {
30852                     if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null) return [];
30853                   }
30854                 }
30855               }
30856               /* Put segment endpoints in a priority queue */
30857
30858
30859               var queue = new Tree(SweepEvent.compare);
30860
30861               for (var _i3 = 0, _iMax2 = multipolys.length; _i3 < _iMax2; _i3++) {
30862                 var sweepEvents = multipolys[_i3].getSweepEvents();
30863
30864                 for (var _j = 0, _jMax = sweepEvents.length; _j < _jMax; _j++) {
30865                   queue.insert(sweepEvents[_j]);
30866
30867                   if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {
30868                     // prevents an infinite loop, an otherwise common manifestation of bugs
30869                     throw new Error('Infinite loop when putting segment endpoints in a priority queue ' + '(queue size too big). Please file a bug report.');
30870                   }
30871                 }
30872               }
30873               /* Pass the sweep line over those endpoints */
30874
30875
30876               var sweepLine = new SweepLine(queue);
30877               var prevQueueSize = queue.size;
30878               var node = queue.pop();
30879
30880               while (node) {
30881                 var evt = node.key;
30882
30883                 if (queue.size === prevQueueSize) {
30884                   // prevents an infinite loop, an otherwise common manifestation of bugs
30885                   var seg = evt.segment;
30886                   throw new Error("Unable to pop() ".concat(evt.isLeft ? 'left' : 'right', " SweepEvent ") + "[".concat(evt.point.x, ", ").concat(evt.point.y, "] from segment #").concat(seg.id, " ") + "[".concat(seg.leftSE.point.x, ", ").concat(seg.leftSE.point.y, "] -> ") + "[".concat(seg.rightSE.point.x, ", ").concat(seg.rightSE.point.y, "] from queue. ") + 'Please file a bug report.');
30887                 }
30888
30889                 if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) {
30890                   // prevents an infinite loop, an otherwise common manifestation of bugs
30891                   throw new Error('Infinite loop when passing sweep line over endpoints ' + '(queue size too big). Please file a bug report.');
30892                 }
30893
30894                 if (sweepLine.segments.length > POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS) {
30895                   // prevents an infinite loop, an otherwise common manifestation of bugs
30896                   throw new Error('Infinite loop when passing sweep line over endpoints ' + '(too many sweep line segments). Please file a bug report.');
30897                 }
30898
30899                 var newEvents = sweepLine.process(evt);
30900
30901                 for (var _i4 = 0, _iMax3 = newEvents.length; _i4 < _iMax3; _i4++) {
30902                   var _evt = newEvents[_i4];
30903                   if (_evt.consumedBy === undefined) queue.insert(_evt);
30904                 }
30905
30906                 prevQueueSize = queue.size;
30907                 node = queue.pop();
30908               } // free some memory we don't need anymore
30909
30910
30911               rounder.reset();
30912               /* Collect and compile segments we're keeping into a multipolygon */
30913
30914               var ringsOut = RingOut.factory(sweepLine.segments);
30915               var result = new MultiPolyOut(ringsOut);
30916               return result.getGeom();
30917             }
30918           }]);
30919
30920           return Operation;
30921         }(); // singleton available by import
30922
30923
30924         var operation = new Operation();
30925
30926         var union = function union(geom) {
30927           for (var _len = arguments.length, moreGeoms = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
30928             moreGeoms[_key - 1] = arguments[_key];
30929           }
30930
30931           return operation.run('union', geom, moreGeoms);
30932         };
30933
30934         var intersection$1 = function intersection(geom) {
30935           for (var _len2 = arguments.length, moreGeoms = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
30936             moreGeoms[_key2 - 1] = arguments[_key2];
30937           }
30938
30939           return operation.run('intersection', geom, moreGeoms);
30940         };
30941
30942         var xor = function xor(geom) {
30943           for (var _len3 = arguments.length, moreGeoms = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
30944             moreGeoms[_key3 - 1] = arguments[_key3];
30945           }
30946
30947           return operation.run('xor', geom, moreGeoms);
30948         };
30949
30950         var difference = function difference(subjectGeom) {
30951           for (var _len4 = arguments.length, clippingGeoms = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {
30952             clippingGeoms[_key4 - 1] = arguments[_key4];
30953           }
30954
30955           return operation.run('difference', subjectGeom, clippingGeoms);
30956         };
30957
30958         var index = {
30959           union: union,
30960           intersection: intersection$1,
30961           xor: xor,
30962           difference: difference
30963         };
30964
30965         var geojsonPrecision = {exports: {}};
30966
30967         (function () {
30968           function parse(t, coordinatePrecision, extrasPrecision) {
30969             function point(p) {
30970               return p.map(function (e, index) {
30971                 if (index < 2) {
30972                   return 1 * e.toFixed(coordinatePrecision);
30973                 } else {
30974                   return 1 * e.toFixed(extrasPrecision);
30975                 }
30976               });
30977             }
30978
30979             function multi(l) {
30980               return l.map(point);
30981             }
30982
30983             function poly(p) {
30984               return p.map(multi);
30985             }
30986
30987             function multiPoly(m) {
30988               return m.map(poly);
30989             }
30990
30991             function geometry(obj) {
30992               if (!obj) {
30993                 return {};
30994               }
30995
30996               switch (obj.type) {
30997                 case "Point":
30998                   obj.coordinates = point(obj.coordinates);
30999                   return obj;
31000
31001                 case "LineString":
31002                 case "MultiPoint":
31003                   obj.coordinates = multi(obj.coordinates);
31004                   return obj;
31005
31006                 case "Polygon":
31007                 case "MultiLineString":
31008                   obj.coordinates = poly(obj.coordinates);
31009                   return obj;
31010
31011                 case "MultiPolygon":
31012                   obj.coordinates = multiPoly(obj.coordinates);
31013                   return obj;
31014
31015                 case "GeometryCollection":
31016                   obj.geometries = obj.geometries.map(geometry);
31017                   return obj;
31018
31019                 default:
31020                   return {};
31021               }
31022             }
31023
31024             function feature(obj) {
31025               obj.geometry = geometry(obj.geometry);
31026               return obj;
31027             }
31028
31029             function featureCollection(f) {
31030               f.features = f.features.map(feature);
31031               return f;
31032             }
31033
31034             function geometryCollection(g) {
31035               g.geometries = g.geometries.map(geometry);
31036               return g;
31037             }
31038
31039             if (!t) {
31040               return t;
31041             }
31042
31043             switch (t.type) {
31044               case "Feature":
31045                 return feature(t);
31046
31047               case "GeometryCollection":
31048                 return geometryCollection(t);
31049
31050               case "FeatureCollection":
31051                 return featureCollection(t);
31052
31053               case "Point":
31054               case "LineString":
31055               case "Polygon":
31056               case "MultiPoint":
31057               case "MultiPolygon":
31058               case "MultiLineString":
31059                 return geometry(t);
31060
31061               default:
31062                 return t;
31063             }
31064           }
31065
31066           geojsonPrecision.exports = parse;
31067           geojsonPrecision.exports.parse = parse;
31068         })();
31069
31070         var precision = geojsonPrecision.exports;
31071
31072         var $$k = _export;
31073         var fails$5 = fails$V;
31074         var toObject$1 = toObject$i;
31075         var toPrimitive = toPrimitive$3;
31076
31077         var FORCED$5 = fails$5(function () {
31078           return new Date(NaN).toJSON() !== null
31079             || Date.prototype.toJSON.call({ toISOString: function () { return 1; } }) !== 1;
31080         });
31081
31082         // `Date.prototype.toJSON` method
31083         // https://tc39.es/ecma262/#sec-date.prototype.tojson
31084         $$k({ target: 'Date', proto: true, forced: FORCED$5 }, {
31085           // eslint-disable-next-line no-unused-vars -- required for `.length`
31086           toJSON: function toJSON(key) {
31087             var O = toObject$1(this);
31088             var pv = toPrimitive(O, 'number');
31089             return typeof pv == 'number' && !isFinite(pv) ? null : O.toISOString();
31090           }
31091         });
31092
31093         var $$j = _export;
31094         var call = functionCall;
31095
31096         // `URL.prototype.toJSON` method
31097         // https://url.spec.whatwg.org/#dom-url-tojson
31098         $$j({ target: 'URL', proto: true, enumerable: true }, {
31099           toJSON: function toJSON() {
31100             return call(URL.prototype.toString, this);
31101           }
31102         });
31103
31104         function isObject$3(obj) {
31105           return _typeof(obj) === 'object' && obj !== null;
31106         }
31107
31108         function forEach(obj, cb) {
31109           if (Array.isArray(obj)) {
31110             obj.forEach(cb);
31111           } else if (isObject$3(obj)) {
31112             Object.keys(obj).forEach(function (key) {
31113               var val = obj[key];
31114               cb(val, key);
31115             });
31116           }
31117         }
31118
31119         function getTreeDepth(obj) {
31120           var depth = 0;
31121
31122           if (Array.isArray(obj) || isObject$3(obj)) {
31123             forEach(obj, function (val) {
31124               if (Array.isArray(val) || isObject$3(val)) {
31125                 var tmpDepth = getTreeDepth(val);
31126
31127                 if (tmpDepth > depth) {
31128                   depth = tmpDepth;
31129                 }
31130               }
31131             });
31132             return depth + 1;
31133           }
31134
31135           return depth;
31136         }
31137
31138         function stringify(obj, options) {
31139           options = options || {};
31140           var indent = JSON.stringify([1], null, get(options, 'indent', 2)).slice(2, -3);
31141           var addMargin = get(options, 'margins', false);
31142           var addArrayMargin = get(options, 'arrayMargins', false);
31143           var addObjectMargin = get(options, 'objectMargins', false);
31144           var maxLength = indent === '' ? Infinity : get(options, 'maxLength', 80);
31145           var maxNesting = get(options, 'maxNesting', Infinity);
31146           return function _stringify(obj, currentIndent, reserved) {
31147             if (obj && typeof obj.toJSON === 'function') {
31148               obj = obj.toJSON();
31149             }
31150
31151             var string = JSON.stringify(obj);
31152
31153             if (string === undefined) {
31154               return string;
31155             }
31156
31157             var length = maxLength - currentIndent.length - reserved;
31158             var treeDepth = getTreeDepth(obj);
31159
31160             if (treeDepth <= maxNesting && string.length <= length) {
31161               var prettified = prettify(string, {
31162                 addMargin: addMargin,
31163                 addArrayMargin: addArrayMargin,
31164                 addObjectMargin: addObjectMargin
31165               });
31166
31167               if (prettified.length <= length) {
31168                 return prettified;
31169               }
31170             }
31171
31172             if (isObject$3(obj)) {
31173               var nextIndent = currentIndent + indent;
31174               var items = [];
31175               var delimiters;
31176
31177               var comma = function comma(array, index) {
31178                 return index === array.length - 1 ? 0 : 1;
31179               };
31180
31181               if (Array.isArray(obj)) {
31182                 for (var index = 0; index < obj.length; index++) {
31183                   items.push(_stringify(obj[index], nextIndent, comma(obj, index)) || 'null');
31184                 }
31185
31186                 delimiters = '[]';
31187               } else {
31188                 Object.keys(obj).forEach(function (key, index, array) {
31189                   var keyPart = JSON.stringify(key) + ': ';
31190
31191                   var value = _stringify(obj[key], nextIndent, keyPart.length + comma(array, index));
31192
31193                   if (value !== undefined) {
31194                     items.push(keyPart + value);
31195                   }
31196                 });
31197                 delimiters = '{}';
31198               }
31199
31200               if (items.length > 0) {
31201                 return [delimiters[0], indent + items.join(',\n' + nextIndent), delimiters[1]].join('\n' + currentIndent);
31202               }
31203             }
31204
31205             return string;
31206           }(obj, '', 0);
31207         } // Note: This regex matches even invalid JSON strings, but since we’re
31208         // working on the output of `JSON.stringify` we know that only valid strings
31209         // are present (unless the user supplied a weird `options.indent` but in
31210         // that case we don’t care since the output would be invalid anyway).
31211
31212
31213         var stringOrChar = /("(?:[^\\"]|\\.)*")|[:,\][}{]/g;
31214
31215         function prettify(string, options) {
31216           options = options || {};
31217           var tokens = {
31218             '{': '{',
31219             '}': '}',
31220             '[': '[',
31221             ']': ']',
31222             ',': ', ',
31223             ':': ': '
31224           };
31225
31226           if (options.addMargin || options.addObjectMargin) {
31227             tokens['{'] = '{ ';
31228             tokens['}'] = ' }';
31229           }
31230
31231           if (options.addMargin || options.addArrayMargin) {
31232             tokens['['] = '[ ';
31233             tokens[']'] = ' ]';
31234           }
31235
31236           return string.replace(stringOrChar, function (match, string) {
31237             return string ? match : tokens[match];
31238           });
31239         }
31240
31241         function get(options, name, defaultValue) {
31242           return name in options ? options[name] : defaultValue;
31243         }
31244
31245         var jsonStringifyPrettyCompact = stringify;
31246
31247         var _default = /*#__PURE__*/function () {
31248           // constructor
31249           //
31250           // `fc`  Optional FeatureCollection of known features
31251           //
31252           // Optionally pass a GeoJSON FeatureCollection of known features which we can refer to later.
31253           // Each feature must have a filename-like `id`, for example: `something.geojson`
31254           //
31255           // {
31256           //   "type": "FeatureCollection"
31257           //   "features": [
31258           //     {
31259           //       "type": "Feature",
31260           //       "id": "philly_metro.geojson",
31261           //       "properties": { … },
31262           //       "geometry": { … }
31263           //     }
31264           //   ]
31265           // }
31266           function _default(fc) {
31267             var _this = this;
31268
31269             _classCallCheck$1(this, _default);
31270
31271             // The _cache retains resolved features, so if you ask for the same thing multiple times
31272             // we don't repeat the expensive resolving/clipping operations.
31273             //
31274             // Each feature has a stable identifier that is used as the cache key.
31275             // The identifiers look like:
31276             // - for point locations, the stringified point:          e.g. '[8.67039,49.41882]'
31277             // - for geojson locations, the geojson id:               e.g. 'de-hamburg.geojson'
31278             // - for countrycoder locations, feature.id property:     e.g. 'Q2'  (countrycoder uses Wikidata identifiers)
31279             // - for aggregated locationSets, +[include]-[exclude]:   e.g '+[Q2]-[Q18,Q27611]'
31280             this._cache = {}; // When strict mode = true, throw on invalid locations or locationSets.
31281             // When strict mode = false, return `null` for invalid locations or locationSets.
31282
31283             this._strict = true; // process input FeatureCollection
31284
31285             if (fc && fc.type === 'FeatureCollection' && Array.isArray(fc.features)) {
31286               fc.features.forEach(function (feature) {
31287                 feature.properties = feature.properties || {};
31288                 var props = feature.properties; // Get `id` from either `id` or `properties`
31289
31290                 var id = feature.id || props.id;
31291                 if (!id || !/^\S+\.geojson$/i.test(id)) return; // Ensure `id` exists and is lowercase
31292
31293                 id = id.toLowerCase();
31294                 feature.id = id;
31295                 props.id = id; // Ensure `area` property exists
31296
31297                 if (!props.area) {
31298                   var area = geojsonArea.geometry(feature.geometry) / 1e6; // m² to km²
31299
31300                   props.area = Number(area.toFixed(2));
31301                 }
31302
31303                 _this._cache[id] = feature;
31304               });
31305             } // Replace CountryCoder world geometry to be a polygon covering the world.
31306
31307
31308             var world = _cloneDeep(feature$1('Q2'));
31309
31310             world.geometry = {
31311               type: 'Polygon',
31312               coordinates: [[[-180, -90], [180, -90], [180, 90], [-180, 90], [-180, -90]]]
31313             };
31314             world.id = 'Q2';
31315             world.properties.id = 'Q2';
31316             world.properties.area = geojsonArea.geometry(world.geometry) / 1e6; // m² to km²
31317
31318             this._cache.Q2 = world;
31319           } // validateLocation
31320           // `location`  The location to validate
31321           //
31322           // Pass a `location` value to validate
31323           //
31324           // Returns a result like:
31325           //   {
31326           //     type:     'point', 'geojson', or 'countrycoder'
31327           //     location:  the queried location
31328           //     id:        the stable identifier for the feature
31329           //   }
31330           // or `null` if the location is invalid
31331           //
31332
31333
31334           _createClass$1(_default, [{
31335             key: "validateLocation",
31336             value: function validateLocation(location) {
31337               if (Array.isArray(location) && (location.length === 2 || location.length === 3)) {
31338                 // [lon, lat] or [lon, lat, radius] point?
31339                 var lon = location[0];
31340                 var lat = location[1];
31341                 var radius = location[2];
31342
31343                 if (Number.isFinite(lon) && lon >= -180 && lon <= 180 && Number.isFinite(lat) && lat >= -90 && lat <= 90 && (location.length === 2 || Number.isFinite(radius) && radius > 0)) {
31344                   var id = '[' + location.toString() + ']';
31345                   return {
31346                     type: 'point',
31347                     location: location,
31348                     id: id
31349                   };
31350                 }
31351               } else if (typeof location === 'string' && /^\S+\.geojson$/i.test(location)) {
31352                 // a .geojson filename?
31353                 var _id = location.toLowerCase();
31354
31355                 if (this._cache[_id]) {
31356                   return {
31357                     type: 'geojson',
31358                     location: location,
31359                     id: _id
31360                   };
31361                 }
31362               } else if (typeof location === 'string' || typeof location === 'number') {
31363                 // a country-coder value?
31364                 var feature = feature$1(location);
31365
31366                 if (feature) {
31367                   // Use wikidata QID as the identifier, since that seems to be the one
31368                   // property that everything in CountryCoder is guaranteed to have.
31369                   var _id2 = feature.properties.wikidata;
31370                   return {
31371                     type: 'countrycoder',
31372                     location: location,
31373                     id: _id2
31374                   };
31375                 }
31376               }
31377
31378               if (this._strict) {
31379                 throw new Error("validateLocation:  Invalid location: \"".concat(location, "\"."));
31380               } else {
31381                 return null;
31382               }
31383             } // resolveLocation
31384             // `location`  The location to resolve
31385             //
31386             // Pass a `location` value to resolve
31387             //
31388             // Returns a result like:
31389             //   {
31390             //     type:      'point', 'geojson', or 'countrycoder'
31391             //     location:  the queried location
31392             //     id:        a stable identifier for the feature
31393             //     feature:   the resolved GeoJSON feature
31394             //   }
31395             //  or `null` if the location is invalid
31396             //
31397
31398           }, {
31399             key: "resolveLocation",
31400             value: function resolveLocation(location) {
31401               var valid = this.validateLocation(location);
31402               if (!valid) return null;
31403               var id = valid.id; // Return a result from cache if we can
31404
31405               if (this._cache[id]) {
31406                 return Object.assign(valid, {
31407                   feature: this._cache[id]
31408                 });
31409               } // A [lon,lat] coordinate pair?
31410
31411
31412               if (valid.type === 'point') {
31413                 var lon = location[0];
31414                 var lat = location[1];
31415                 var radius = location[2] || 25; // km
31416
31417                 var EDGES = 10;
31418                 var PRECISION = 3;
31419                 var area = Math.PI * radius * radius;
31420                 var feature = this._cache[id] = precision({
31421                   type: 'Feature',
31422                   id: id,
31423                   properties: {
31424                     id: id,
31425                     area: Number(area.toFixed(2))
31426                   },
31427                   geometry: circleToPolygon([lon, lat], radius * 1000, EDGES) // km to m
31428
31429                 }, PRECISION);
31430                 return Object.assign(valid, {
31431                   feature: feature
31432                 }); // A .geojson filename?
31433               } else if (valid.type === 'geojson') ; else if (valid.type === 'countrycoder') {
31434                 var _feature = _cloneDeep(feature$1(id));
31435
31436                 var props = _feature.properties; // -> This block of code is weird and requires some explanation. <-
31437                 // CountryCoder includes higher level features which are made up of members.
31438                 // These features don't have their own geometry, but CountryCoder provides an
31439                 //   `aggregateFeature` method to combine these members into a MultiPolygon.
31440                 // In the past, Turf/JSTS/martinez could not handle the aggregated features,
31441                 //   so we'd iteratively union them all together.  (this was slow)
31442                 // But now mfogel/polygon-clipping handles these MultiPolygons like a boss.
31443                 // This approach also has the benefit of removing all the internal boaders and
31444                 //   simplifying the regional polygons a lot.
31445
31446                 if (Array.isArray(props.members)) {
31447                   var aggregate = aggregateFeature(id);
31448                   aggregate.geometry.coordinates = _clip([aggregate], 'UNION').geometry.coordinates;
31449                   _feature.geometry = aggregate.geometry;
31450                 } // Ensure `area` property exists
31451
31452
31453                 if (!props.area) {
31454                   var _area = geojsonArea.geometry(_feature.geometry) / 1e6; // m² to km²
31455
31456
31457                   props.area = Number(_area.toFixed(2));
31458                 } // Ensure `id` property exists
31459
31460
31461                 _feature.id = id;
31462                 props.id = id;
31463                 this._cache[id] = _feature;
31464                 return Object.assign(valid, {
31465                   feature: _feature
31466                 });
31467               }
31468
31469               if (this._strict) {
31470                 throw new Error("resolveLocation:  Couldn't resolve location \"".concat(location, "\"."));
31471               } else {
31472                 return null;
31473               }
31474             } // validateLocationSet
31475             // `locationSet`  the locationSet to validate
31476             //
31477             // Pass a locationSet Object to validate like:
31478             //   {
31479             //     include: [ Array of locations ],
31480             //     exclude: [ Array of locations ]
31481             //   }
31482             //
31483             // Returns a result like:
31484             //   {
31485             //     type:         'locationset'
31486             //     locationSet:  the queried locationSet
31487             //     id:           the stable identifier for the feature
31488             //   }
31489             // or `null` if the locationSet is invalid
31490             //
31491
31492           }, {
31493             key: "validateLocationSet",
31494             value: function validateLocationSet(locationSet) {
31495               locationSet = locationSet || {};
31496               var validator = this.validateLocation.bind(this);
31497               var include = (locationSet.include || []).map(validator).filter(Boolean);
31498               var exclude = (locationSet.exclude || []).map(validator).filter(Boolean);
31499
31500               if (!include.length) {
31501                 if (this._strict) {
31502                   throw new Error("validateLocationSet:  LocationSet includes nothing.");
31503                 } else {
31504                   // non-strict mode, replace an empty locationSet with one that includes "the world"
31505                   locationSet.include = ['Q2'];
31506                   include = [{
31507                     type: 'countrycoder',
31508                     location: 'Q2',
31509                     id: 'Q2'
31510                   }];
31511                 }
31512               } // Generate stable identifier
31513
31514
31515               include.sort(_sortLocations);
31516               var id = '+[' + include.map(function (d) {
31517                 return d.id;
31518               }).join(',') + ']';
31519
31520               if (exclude.length) {
31521                 exclude.sort(_sortLocations);
31522                 id += '-[' + exclude.map(function (d) {
31523                   return d.id;
31524                 }).join(',') + ']';
31525               }
31526
31527               return {
31528                 type: 'locationset',
31529                 locationSet: locationSet,
31530                 id: id
31531               };
31532             } // resolveLocationSet
31533             // `locationSet`  the locationSet to resolve
31534             //
31535             // Pass a locationSet Object to validate like:
31536             //   {
31537             //     include: [ Array of locations ],
31538             //     exclude: [ Array of locations ]
31539             //   }
31540             //
31541             // Returns a result like:
31542             //   {
31543             //     type:         'locationset'
31544             //     locationSet:  the queried locationSet
31545             //     id:           the stable identifier for the feature
31546             //     feature:      the resolved GeoJSON feature
31547             //   }
31548             // or `null` if the locationSet is invalid
31549             //
31550
31551           }, {
31552             key: "resolveLocationSet",
31553             value: function resolveLocationSet(locationSet) {
31554               locationSet = locationSet || {};
31555               var valid = this.validateLocationSet(locationSet);
31556               if (!valid) return null;
31557               var id = valid.id; // Return a result from cache if we can
31558
31559               if (this._cache[id]) {
31560                 return Object.assign(valid, {
31561                   feature: this._cache[id]
31562                 });
31563               }
31564
31565               var resolver = this.resolveLocation.bind(this);
31566               var includes = (locationSet.include || []).map(resolver).filter(Boolean);
31567               var excludes = (locationSet.exclude || []).map(resolver).filter(Boolean); // Return quickly if it's a single included location..
31568
31569               if (includes.length === 1 && excludes.length === 0) {
31570                 return Object.assign(valid, {
31571                   feature: includes[0].feature
31572                 });
31573               } // Calculate unions
31574
31575
31576               var includeGeoJSON = _clip(includes.map(function (d) {
31577                 return d.feature;
31578               }), 'UNION');
31579
31580               var excludeGeoJSON = _clip(excludes.map(function (d) {
31581                 return d.feature;
31582               }), 'UNION'); // Calculate difference, update `area` and return result
31583
31584
31585               var resultGeoJSON = excludeGeoJSON ? _clip([includeGeoJSON, excludeGeoJSON], 'DIFFERENCE') : includeGeoJSON;
31586               var area = geojsonArea.geometry(resultGeoJSON.geometry) / 1e6; // m² to km²
31587
31588               resultGeoJSON.id = id;
31589               resultGeoJSON.properties = {
31590                 id: id,
31591                 area: Number(area.toFixed(2))
31592               };
31593               this._cache[id] = resultGeoJSON;
31594               return Object.assign(valid, {
31595                 feature: resultGeoJSON
31596               });
31597             } // strict
31598             //
31599
31600           }, {
31601             key: "strict",
31602             value: function strict(val) {
31603               if (val === undefined) {
31604                 // get
31605                 return this._strict;
31606               } else {
31607                 // set
31608                 this._strict = val;
31609                 return this;
31610               }
31611             } // cache
31612             // convenience method to access the internal cache
31613
31614           }, {
31615             key: "cache",
31616             value: function cache() {
31617               return this._cache;
31618             } // stringify
31619             // convenience method to prettyStringify the given object
31620
31621           }, {
31622             key: "stringify",
31623             value: function stringify(obj, options) {
31624               return jsonStringifyPrettyCompact(obj, options);
31625             }
31626           }]);
31627
31628           return _default;
31629         }(); // Wrap the mfogel/polygon-clipping library and return a GeoJSON feature.
31630
31631         function _clip(features, which) {
31632           if (!Array.isArray(features) || !features.length) return null;
31633           var fn = {
31634             UNION: index.union,
31635             DIFFERENCE: index.difference
31636           }[which];
31637           var args = features.map(function (feature) {
31638             return feature.geometry.coordinates;
31639           });
31640           var coords = fn.apply(null, args);
31641           return {
31642             type: 'Feature',
31643             properties: {},
31644             geometry: {
31645               type: whichType(coords),
31646               coordinates: coords
31647             }
31648           }; // is this a Polygon or a MultiPolygon?
31649
31650           function whichType(coords) {
31651             var a = Array.isArray(coords);
31652             var b = a && Array.isArray(coords[0]);
31653             var c = b && Array.isArray(coords[0][0]);
31654             var d = c && Array.isArray(coords[0][0][0]);
31655             return d ? 'MultiPolygon' : 'Polygon';
31656           }
31657         }
31658
31659         function _cloneDeep(obj) {
31660           return JSON.parse(JSON.stringify(obj));
31661         } // Sorting the location lists is ok because they end up unioned together.
31662         // This sorting makes it possible to generate a deterministic id.
31663
31664
31665         function _sortLocations(a, b) {
31666           var rank = {
31667             countrycoder: 1,
31668             geojson: 2,
31669             point: 3
31670           };
31671           var aRank = rank[a.type];
31672           var bRank = rank[b.type];
31673           return aRank > bRank ? 1 : aRank < bRank ? -1 : a.id.localeCompare(b.id);
31674         }
31675
31676         var $$i = _export;
31677
31678         // `Number.MAX_SAFE_INTEGER` constant
31679         // https://tc39.es/ecma262/#sec-number.max_safe_integer
31680         $$i({ target: 'Number', stat: true }, {
31681           MAX_SAFE_INTEGER: 0x1FFFFFFFFFFFFF
31682         });
31683
31684         var aesJs = {exports: {}};
31685
31686         (function (module, exports) {
31687           (function (root) {
31688
31689             function checkInt(value) {
31690               return parseInt(value) === value;
31691             }
31692
31693             function checkInts(arrayish) {
31694               if (!checkInt(arrayish.length)) {
31695                 return false;
31696               }
31697
31698               for (var i = 0; i < arrayish.length; i++) {
31699                 if (!checkInt(arrayish[i]) || arrayish[i] < 0 || arrayish[i] > 255) {
31700                   return false;
31701                 }
31702               }
31703
31704               return true;
31705             }
31706
31707             function coerceArray(arg, copy) {
31708               // ArrayBuffer view
31709               if (arg.buffer && arg.name === 'Uint8Array') {
31710                 if (copy) {
31711                   if (arg.slice) {
31712                     arg = arg.slice();
31713                   } else {
31714                     arg = Array.prototype.slice.call(arg);
31715                   }
31716                 }
31717
31718                 return arg;
31719               } // It's an array; check it is a valid representation of a byte
31720
31721
31722               if (Array.isArray(arg)) {
31723                 if (!checkInts(arg)) {
31724                   throw new Error('Array contains invalid value: ' + arg);
31725                 }
31726
31727                 return new Uint8Array(arg);
31728               } // Something else, but behaves like an array (maybe a Buffer? Arguments?)
31729
31730
31731               if (checkInt(arg.length) && checkInts(arg)) {
31732                 return new Uint8Array(arg);
31733               }
31734
31735               throw new Error('unsupported array-like object');
31736             }
31737
31738             function createArray(length) {
31739               return new Uint8Array(length);
31740             }
31741
31742             function copyArray(sourceArray, targetArray, targetStart, sourceStart, sourceEnd) {
31743               if (sourceStart != null || sourceEnd != null) {
31744                 if (sourceArray.slice) {
31745                   sourceArray = sourceArray.slice(sourceStart, sourceEnd);
31746                 } else {
31747                   sourceArray = Array.prototype.slice.call(sourceArray, sourceStart, sourceEnd);
31748                 }
31749               }
31750
31751               targetArray.set(sourceArray, targetStart);
31752             }
31753
31754             var convertUtf8 = function () {
31755               function toBytes(text) {
31756                 var result = [],
31757                     i = 0;
31758                 text = encodeURI(text);
31759
31760                 while (i < text.length) {
31761                   var c = text.charCodeAt(i++); // if it is a % sign, encode the following 2 bytes as a hex value
31762
31763                   if (c === 37) {
31764                     result.push(parseInt(text.substr(i, 2), 16));
31765                     i += 2; // otherwise, just the actual byte
31766                   } else {
31767                     result.push(c);
31768                   }
31769                 }
31770
31771                 return coerceArray(result);
31772               }
31773
31774               function fromBytes(bytes) {
31775                 var result = [],
31776                     i = 0;
31777
31778                 while (i < bytes.length) {
31779                   var c = bytes[i];
31780
31781                   if (c < 128) {
31782                     result.push(String.fromCharCode(c));
31783                     i++;
31784                   } else if (c > 191 && c < 224) {
31785                     result.push(String.fromCharCode((c & 0x1f) << 6 | bytes[i + 1] & 0x3f));
31786                     i += 2;
31787                   } else {
31788                     result.push(String.fromCharCode((c & 0x0f) << 12 | (bytes[i + 1] & 0x3f) << 6 | bytes[i + 2] & 0x3f));
31789                     i += 3;
31790                   }
31791                 }
31792
31793                 return result.join('');
31794               }
31795
31796               return {
31797                 toBytes: toBytes,
31798                 fromBytes: fromBytes
31799               };
31800             }();
31801
31802             var convertHex = function () {
31803               function toBytes(text) {
31804                 var result = [];
31805
31806                 for (var i = 0; i < text.length; i += 2) {
31807                   result.push(parseInt(text.substr(i, 2), 16));
31808                 }
31809
31810                 return result;
31811               } // http://ixti.net/development/javascript/2011/11/11/base64-encodedecode-of-utf8-in-browser-with-js.html
31812
31813
31814               var Hex = '0123456789abcdef';
31815
31816               function fromBytes(bytes) {
31817                 var result = [];
31818
31819                 for (var i = 0; i < bytes.length; i++) {
31820                   var v = bytes[i];
31821                   result.push(Hex[(v & 0xf0) >> 4] + Hex[v & 0x0f]);
31822                 }
31823
31824                 return result.join('');
31825               }
31826
31827               return {
31828                 toBytes: toBytes,
31829                 fromBytes: fromBytes
31830               };
31831             }(); // Number of rounds by keysize
31832
31833
31834             var numberOfRounds = {
31835               16: 10,
31836               24: 12,
31837               32: 14
31838             }; // Round constant words
31839
31840             var rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91]; // S-box and Inverse S-box (S is for Substitution)
31841
31842             var S = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16];
31843             var Si = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]; // Transformations for encryption
31844
31845             var T1 = [0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a];
31846             var T2 = [0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616];
31847             var T3 = [0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16];
31848             var T4 = [0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c]; // Transformations for decryption
31849
31850             var T5 = [0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742];
31851             var T6 = [0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857];
31852             var T7 = [0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8];
31853             var T8 = [0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0]; // Transformations for decryption key expansion
31854
31855             var U1 = [0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3];
31856             var U2 = [0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697];
31857             var U3 = [0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46];
31858             var U4 = [0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d];
31859
31860             function convertToInt32(bytes) {
31861               var result = [];
31862
31863               for (var i = 0; i < bytes.length; i += 4) {
31864                 result.push(bytes[i] << 24 | bytes[i + 1] << 16 | bytes[i + 2] << 8 | bytes[i + 3]);
31865               }
31866
31867               return result;
31868             }
31869
31870             var AES = function AES(key) {
31871               if (!(this instanceof AES)) {
31872                 throw Error('AES must be instanitated with `new`');
31873               }
31874
31875               Object.defineProperty(this, 'key', {
31876                 value: coerceArray(key, true)
31877               });
31878
31879               this._prepare();
31880             };
31881
31882             AES.prototype._prepare = function () {
31883               var rounds = numberOfRounds[this.key.length];
31884
31885               if (rounds == null) {
31886                 throw new Error('invalid key size (must be 16, 24 or 32 bytes)');
31887               } // encryption round keys
31888
31889
31890               this._Ke = []; // decryption round keys
31891
31892               this._Kd = [];
31893
31894               for (var i = 0; i <= rounds; i++) {
31895                 this._Ke.push([0, 0, 0, 0]);
31896
31897                 this._Kd.push([0, 0, 0, 0]);
31898               }
31899
31900               var roundKeyCount = (rounds + 1) * 4;
31901               var KC = this.key.length / 4; // convert the key into ints
31902
31903               var tk = convertToInt32(this.key); // copy values into round key arrays
31904
31905               var index;
31906
31907               for (var i = 0; i < KC; i++) {
31908                 index = i >> 2;
31909                 this._Ke[index][i % 4] = tk[i];
31910                 this._Kd[rounds - index][i % 4] = tk[i];
31911               } // key expansion (fips-197 section 5.2)
31912
31913
31914               var rconpointer = 0;
31915               var t = KC,
31916                   tt;
31917
31918               while (t < roundKeyCount) {
31919                 tt = tk[KC - 1];
31920                 tk[0] ^= S[tt >> 16 & 0xFF] << 24 ^ S[tt >> 8 & 0xFF] << 16 ^ S[tt & 0xFF] << 8 ^ S[tt >> 24 & 0xFF] ^ rcon[rconpointer] << 24;
31921                 rconpointer += 1; // key expansion (for non-256 bit)
31922
31923                 if (KC != 8) {
31924                   for (var i = 1; i < KC; i++) {
31925                     tk[i] ^= tk[i - 1];
31926                   } // key expansion for 256-bit keys is "slightly different" (fips-197)
31927
31928                 } else {
31929                   for (var i = 1; i < KC / 2; i++) {
31930                     tk[i] ^= tk[i - 1];
31931                   }
31932
31933                   tt = tk[KC / 2 - 1];
31934                   tk[KC / 2] ^= S[tt & 0xFF] ^ S[tt >> 8 & 0xFF] << 8 ^ S[tt >> 16 & 0xFF] << 16 ^ S[tt >> 24 & 0xFF] << 24;
31935
31936                   for (var i = KC / 2 + 1; i < KC; i++) {
31937                     tk[i] ^= tk[i - 1];
31938                   }
31939                 } // copy values into round key arrays
31940
31941
31942                 var i = 0,
31943                     r,
31944                     c;
31945
31946                 while (i < KC && t < roundKeyCount) {
31947                   r = t >> 2;
31948                   c = t % 4;
31949                   this._Ke[r][c] = tk[i];
31950                   this._Kd[rounds - r][c] = tk[i++];
31951                   t++;
31952                 }
31953               } // inverse-cipher-ify the decryption round key (fips-197 section 5.3)
31954
31955
31956               for (var r = 1; r < rounds; r++) {
31957                 for (var c = 0; c < 4; c++) {
31958                   tt = this._Kd[r][c];
31959                   this._Kd[r][c] = U1[tt >> 24 & 0xFF] ^ U2[tt >> 16 & 0xFF] ^ U3[tt >> 8 & 0xFF] ^ U4[tt & 0xFF];
31960                 }
31961               }
31962             };
31963
31964             AES.prototype.encrypt = function (plaintext) {
31965               if (plaintext.length != 16) {
31966                 throw new Error('invalid plaintext size (must be 16 bytes)');
31967               }
31968
31969               var rounds = this._Ke.length - 1;
31970               var a = [0, 0, 0, 0]; // convert plaintext to (ints ^ key)
31971
31972               var t = convertToInt32(plaintext);
31973
31974               for (var i = 0; i < 4; i++) {
31975                 t[i] ^= this._Ke[0][i];
31976               } // apply round transforms
31977
31978
31979               for (var r = 1; r < rounds; r++) {
31980                 for (var i = 0; i < 4; i++) {
31981                   a[i] = T1[t[i] >> 24 & 0xff] ^ T2[t[(i + 1) % 4] >> 16 & 0xff] ^ T3[t[(i + 2) % 4] >> 8 & 0xff] ^ T4[t[(i + 3) % 4] & 0xff] ^ this._Ke[r][i];
31982                 }
31983
31984                 t = a.slice();
31985               } // the last round is special
31986
31987
31988               var result = createArray(16),
31989                   tt;
31990
31991               for (var i = 0; i < 4; i++) {
31992                 tt = this._Ke[rounds][i];
31993                 result[4 * i] = (S[t[i] >> 24 & 0xff] ^ tt >> 24) & 0xff;
31994                 result[4 * i + 1] = (S[t[(i + 1) % 4] >> 16 & 0xff] ^ tt >> 16) & 0xff;
31995                 result[4 * i + 2] = (S[t[(i + 2) % 4] >> 8 & 0xff] ^ tt >> 8) & 0xff;
31996                 result[4 * i + 3] = (S[t[(i + 3) % 4] & 0xff] ^ tt) & 0xff;
31997               }
31998
31999               return result;
32000             };
32001
32002             AES.prototype.decrypt = function (ciphertext) {
32003               if (ciphertext.length != 16) {
32004                 throw new Error('invalid ciphertext size (must be 16 bytes)');
32005               }
32006
32007               var rounds = this._Kd.length - 1;
32008               var a = [0, 0, 0, 0]; // convert plaintext to (ints ^ key)
32009
32010               var t = convertToInt32(ciphertext);
32011
32012               for (var i = 0; i < 4; i++) {
32013                 t[i] ^= this._Kd[0][i];
32014               } // apply round transforms
32015
32016
32017               for (var r = 1; r < rounds; r++) {
32018                 for (var i = 0; i < 4; i++) {
32019                   a[i] = T5[t[i] >> 24 & 0xff] ^ T6[t[(i + 3) % 4] >> 16 & 0xff] ^ T7[t[(i + 2) % 4] >> 8 & 0xff] ^ T8[t[(i + 1) % 4] & 0xff] ^ this._Kd[r][i];
32020                 }
32021
32022                 t = a.slice();
32023               } // the last round is special
32024
32025
32026               var result = createArray(16),
32027                   tt;
32028
32029               for (var i = 0; i < 4; i++) {
32030                 tt = this._Kd[rounds][i];
32031                 result[4 * i] = (Si[t[i] >> 24 & 0xff] ^ tt >> 24) & 0xff;
32032                 result[4 * i + 1] = (Si[t[(i + 3) % 4] >> 16 & 0xff] ^ tt >> 16) & 0xff;
32033                 result[4 * i + 2] = (Si[t[(i + 2) % 4] >> 8 & 0xff] ^ tt >> 8) & 0xff;
32034                 result[4 * i + 3] = (Si[t[(i + 1) % 4] & 0xff] ^ tt) & 0xff;
32035               }
32036
32037               return result;
32038             };
32039             /**
32040              *  Mode Of Operation - Electonic Codebook (ECB)
32041              */
32042
32043
32044             var ModeOfOperationECB = function ModeOfOperationECB(key) {
32045               if (!(this instanceof ModeOfOperationECB)) {
32046                 throw Error('AES must be instanitated with `new`');
32047               }
32048
32049               this.description = "Electronic Code Block";
32050               this.name = "ecb";
32051               this._aes = new AES(key);
32052             };
32053
32054             ModeOfOperationECB.prototype.encrypt = function (plaintext) {
32055               plaintext = coerceArray(plaintext);
32056
32057               if (plaintext.length % 16 !== 0) {
32058                 throw new Error('invalid plaintext size (must be multiple of 16 bytes)');
32059               }
32060
32061               var ciphertext = createArray(plaintext.length);
32062               var block = createArray(16);
32063
32064               for (var i = 0; i < plaintext.length; i += 16) {
32065                 copyArray(plaintext, block, 0, i, i + 16);
32066                 block = this._aes.encrypt(block);
32067                 copyArray(block, ciphertext, i);
32068               }
32069
32070               return ciphertext;
32071             };
32072
32073             ModeOfOperationECB.prototype.decrypt = function (ciphertext) {
32074               ciphertext = coerceArray(ciphertext);
32075
32076               if (ciphertext.length % 16 !== 0) {
32077                 throw new Error('invalid ciphertext size (must be multiple of 16 bytes)');
32078               }
32079
32080               var plaintext = createArray(ciphertext.length);
32081               var block = createArray(16);
32082
32083               for (var i = 0; i < ciphertext.length; i += 16) {
32084                 copyArray(ciphertext, block, 0, i, i + 16);
32085                 block = this._aes.decrypt(block);
32086                 copyArray(block, plaintext, i);
32087               }
32088
32089               return plaintext;
32090             };
32091             /**
32092              *  Mode Of Operation - Cipher Block Chaining (CBC)
32093              */
32094
32095
32096             var ModeOfOperationCBC = function ModeOfOperationCBC(key, iv) {
32097               if (!(this instanceof ModeOfOperationCBC)) {
32098                 throw Error('AES must be instanitated with `new`');
32099               }
32100
32101               this.description = "Cipher Block Chaining";
32102               this.name = "cbc";
32103
32104               if (!iv) {
32105                 iv = createArray(16);
32106               } else if (iv.length != 16) {
32107                 throw new Error('invalid initialation vector size (must be 16 bytes)');
32108               }
32109
32110               this._lastCipherblock = coerceArray(iv, true);
32111               this._aes = new AES(key);
32112             };
32113
32114             ModeOfOperationCBC.prototype.encrypt = function (plaintext) {
32115               plaintext = coerceArray(plaintext);
32116
32117               if (plaintext.length % 16 !== 0) {
32118                 throw new Error('invalid plaintext size (must be multiple of 16 bytes)');
32119               }
32120
32121               var ciphertext = createArray(plaintext.length);
32122               var block = createArray(16);
32123
32124               for (var i = 0; i < plaintext.length; i += 16) {
32125                 copyArray(plaintext, block, 0, i, i + 16);
32126
32127                 for (var j = 0; j < 16; j++) {
32128                   block[j] ^= this._lastCipherblock[j];
32129                 }
32130
32131                 this._lastCipherblock = this._aes.encrypt(block);
32132                 copyArray(this._lastCipherblock, ciphertext, i);
32133               }
32134
32135               return ciphertext;
32136             };
32137
32138             ModeOfOperationCBC.prototype.decrypt = function (ciphertext) {
32139               ciphertext = coerceArray(ciphertext);
32140
32141               if (ciphertext.length % 16 !== 0) {
32142                 throw new Error('invalid ciphertext size (must be multiple of 16 bytes)');
32143               }
32144
32145               var plaintext = createArray(ciphertext.length);
32146               var block = createArray(16);
32147
32148               for (var i = 0; i < ciphertext.length; i += 16) {
32149                 copyArray(ciphertext, block, 0, i, i + 16);
32150                 block = this._aes.decrypt(block);
32151
32152                 for (var j = 0; j < 16; j++) {
32153                   plaintext[i + j] = block[j] ^ this._lastCipherblock[j];
32154                 }
32155
32156                 copyArray(ciphertext, this._lastCipherblock, 0, i, i + 16);
32157               }
32158
32159               return plaintext;
32160             };
32161             /**
32162              *  Mode Of Operation - Cipher Feedback (CFB)
32163              */
32164
32165
32166             var ModeOfOperationCFB = function ModeOfOperationCFB(key, iv, segmentSize) {
32167               if (!(this instanceof ModeOfOperationCFB)) {
32168                 throw Error('AES must be instanitated with `new`');
32169               }
32170
32171               this.description = "Cipher Feedback";
32172               this.name = "cfb";
32173
32174               if (!iv) {
32175                 iv = createArray(16);
32176               } else if (iv.length != 16) {
32177                 throw new Error('invalid initialation vector size (must be 16 size)');
32178               }
32179
32180               if (!segmentSize) {
32181                 segmentSize = 1;
32182               }
32183
32184               this.segmentSize = segmentSize;
32185               this._shiftRegister = coerceArray(iv, true);
32186               this._aes = new AES(key);
32187             };
32188
32189             ModeOfOperationCFB.prototype.encrypt = function (plaintext) {
32190               if (plaintext.length % this.segmentSize != 0) {
32191                 throw new Error('invalid plaintext size (must be segmentSize bytes)');
32192               }
32193
32194               var encrypted = coerceArray(plaintext, true);
32195               var xorSegment;
32196
32197               for (var i = 0; i < encrypted.length; i += this.segmentSize) {
32198                 xorSegment = this._aes.encrypt(this._shiftRegister);
32199
32200                 for (var j = 0; j < this.segmentSize; j++) {
32201                   encrypted[i + j] ^= xorSegment[j];
32202                 } // Shift the register
32203
32204
32205                 copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize);
32206                 copyArray(encrypted, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize);
32207               }
32208
32209               return encrypted;
32210             };
32211
32212             ModeOfOperationCFB.prototype.decrypt = function (ciphertext) {
32213               if (ciphertext.length % this.segmentSize != 0) {
32214                 throw new Error('invalid ciphertext size (must be segmentSize bytes)');
32215               }
32216
32217               var plaintext = coerceArray(ciphertext, true);
32218               var xorSegment;
32219
32220               for (var i = 0; i < plaintext.length; i += this.segmentSize) {
32221                 xorSegment = this._aes.encrypt(this._shiftRegister);
32222
32223                 for (var j = 0; j < this.segmentSize; j++) {
32224                   plaintext[i + j] ^= xorSegment[j];
32225                 } // Shift the register
32226
32227
32228                 copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize);
32229                 copyArray(ciphertext, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize);
32230               }
32231
32232               return plaintext;
32233             };
32234             /**
32235              *  Mode Of Operation - Output Feedback (OFB)
32236              */
32237
32238
32239             var ModeOfOperationOFB = function ModeOfOperationOFB(key, iv) {
32240               if (!(this instanceof ModeOfOperationOFB)) {
32241                 throw Error('AES must be instanitated with `new`');
32242               }
32243
32244               this.description = "Output Feedback";
32245               this.name = "ofb";
32246
32247               if (!iv) {
32248                 iv = createArray(16);
32249               } else if (iv.length != 16) {
32250                 throw new Error('invalid initialation vector size (must be 16 bytes)');
32251               }
32252
32253               this._lastPrecipher = coerceArray(iv, true);
32254               this._lastPrecipherIndex = 16;
32255               this._aes = new AES(key);
32256             };
32257
32258             ModeOfOperationOFB.prototype.encrypt = function (plaintext) {
32259               var encrypted = coerceArray(plaintext, true);
32260
32261               for (var i = 0; i < encrypted.length; i++) {
32262                 if (this._lastPrecipherIndex === 16) {
32263                   this._lastPrecipher = this._aes.encrypt(this._lastPrecipher);
32264                   this._lastPrecipherIndex = 0;
32265                 }
32266
32267                 encrypted[i] ^= this._lastPrecipher[this._lastPrecipherIndex++];
32268               }
32269
32270               return encrypted;
32271             }; // Decryption is symetric
32272
32273
32274             ModeOfOperationOFB.prototype.decrypt = ModeOfOperationOFB.prototype.encrypt;
32275             /**
32276              *  Counter object for CTR common mode of operation
32277              */
32278
32279             var Counter = function Counter(initialValue) {
32280               if (!(this instanceof Counter)) {
32281                 throw Error('Counter must be instanitated with `new`');
32282               } // We allow 0, but anything false-ish uses the default 1
32283
32284
32285               if (initialValue !== 0 && !initialValue) {
32286                 initialValue = 1;
32287               }
32288
32289               if (typeof initialValue === 'number') {
32290                 this._counter = createArray(16);
32291                 this.setValue(initialValue);
32292               } else {
32293                 this.setBytes(initialValue);
32294               }
32295             };
32296
32297             Counter.prototype.setValue = function (value) {
32298               if (typeof value !== 'number' || parseInt(value) != value) {
32299                 throw new Error('invalid counter value (must be an integer)');
32300               } // We cannot safely handle numbers beyond the safe range for integers
32301
32302
32303               if (value > Number.MAX_SAFE_INTEGER) {
32304                 throw new Error('integer value out of safe range');
32305               }
32306
32307               for (var index = 15; index >= 0; --index) {
32308                 this._counter[index] = value % 256;
32309                 value = parseInt(value / 256);
32310               }
32311             };
32312
32313             Counter.prototype.setBytes = function (bytes) {
32314               bytes = coerceArray(bytes, true);
32315
32316               if (bytes.length != 16) {
32317                 throw new Error('invalid counter bytes size (must be 16 bytes)');
32318               }
32319
32320               this._counter = bytes;
32321             };
32322
32323             Counter.prototype.increment = function () {
32324               for (var i = 15; i >= 0; i--) {
32325                 if (this._counter[i] === 255) {
32326                   this._counter[i] = 0;
32327                 } else {
32328                   this._counter[i]++;
32329                   break;
32330                 }
32331               }
32332             };
32333             /**
32334              *  Mode Of Operation - Counter (CTR)
32335              */
32336
32337
32338             var ModeOfOperationCTR = function ModeOfOperationCTR(key, counter) {
32339               if (!(this instanceof ModeOfOperationCTR)) {
32340                 throw Error('AES must be instanitated with `new`');
32341               }
32342
32343               this.description = "Counter";
32344               this.name = "ctr";
32345
32346               if (!(counter instanceof Counter)) {
32347                 counter = new Counter(counter);
32348               }
32349
32350               this._counter = counter;
32351               this._remainingCounter = null;
32352               this._remainingCounterIndex = 16;
32353               this._aes = new AES(key);
32354             };
32355
32356             ModeOfOperationCTR.prototype.encrypt = function (plaintext) {
32357               var encrypted = coerceArray(plaintext, true);
32358
32359               for (var i = 0; i < encrypted.length; i++) {
32360                 if (this._remainingCounterIndex === 16) {
32361                   this._remainingCounter = this._aes.encrypt(this._counter._counter);
32362                   this._remainingCounterIndex = 0;
32363
32364                   this._counter.increment();
32365                 }
32366
32367                 encrypted[i] ^= this._remainingCounter[this._remainingCounterIndex++];
32368               }
32369
32370               return encrypted;
32371             }; // Decryption is symetric
32372
32373
32374             ModeOfOperationCTR.prototype.decrypt = ModeOfOperationCTR.prototype.encrypt; ///////////////////////
32375             // Padding
32376             // See:https://tools.ietf.org/html/rfc2315
32377
32378             function pkcs7pad(data) {
32379               data = coerceArray(data, true);
32380               var padder = 16 - data.length % 16;
32381               var result = createArray(data.length + padder);
32382               copyArray(data, result);
32383
32384               for (var i = data.length; i < result.length; i++) {
32385                 result[i] = padder;
32386               }
32387
32388               return result;
32389             }
32390
32391             function pkcs7strip(data) {
32392               data = coerceArray(data, true);
32393
32394               if (data.length < 16) {
32395                 throw new Error('PKCS#7 invalid length');
32396               }
32397
32398               var padder = data[data.length - 1];
32399
32400               if (padder > 16) {
32401                 throw new Error('PKCS#7 padding byte out of range');
32402               }
32403
32404               var length = data.length - padder;
32405
32406               for (var i = 0; i < padder; i++) {
32407                 if (data[length + i] !== padder) {
32408                   throw new Error('PKCS#7 invalid padding byte');
32409                 }
32410               }
32411
32412               var result = createArray(length);
32413               copyArray(data, result, 0, 0, length);
32414               return result;
32415             } ///////////////////////
32416             // Exporting
32417             // The block cipher
32418
32419
32420             var aesjs = {
32421               AES: AES,
32422               Counter: Counter,
32423               ModeOfOperation: {
32424                 ecb: ModeOfOperationECB,
32425                 cbc: ModeOfOperationCBC,
32426                 cfb: ModeOfOperationCFB,
32427                 ofb: ModeOfOperationOFB,
32428                 ctr: ModeOfOperationCTR
32429               },
32430               utils: {
32431                 hex: convertHex,
32432                 utf8: convertUtf8
32433               },
32434               padding: {
32435                 pkcs7: {
32436                   pad: pkcs7pad,
32437                   strip: pkcs7strip
32438                 }
32439               },
32440               _arrayTest: {
32441                 coerceArray: coerceArray,
32442                 createArray: createArray,
32443                 copyArray: copyArray
32444               }
32445             }; // node.js
32446
32447             {
32448               module.exports = aesjs; // RequireJS/AMD
32449               // http://www.requirejs.org/docs/api.html
32450               // https://github.com/amdjs/amdjs-api/wiki/AMD
32451             }
32452           })();
32453         })(aesJs);
32454
32455         var aesjs = aesJs.exports;
32456
32457         // We can use keys that are 128 bits (16 bytes), 192 bits (24 bytes) or 256 bits (32 bytes).
32458         // To generate a random key:  window.crypto.getRandomValues(new Uint8Array(16));
32459         // This default signing key is built into iD and can be used to mask/unmask sensitive values.
32460
32461         var DEFAULT_128 = [250, 157, 60, 79, 142, 134, 229, 129, 138, 126, 210, 129, 29, 71, 160, 208];
32462         function utilAesEncrypt(text, key) {
32463           key = key || DEFAULT_128;
32464           var textBytes = aesjs.utils.utf8.toBytes(text);
32465           var aesCtr = new aesjs.ModeOfOperation.ctr(key);
32466           var encryptedBytes = aesCtr.encrypt(textBytes);
32467           var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
32468           return encryptedHex;
32469         }
32470         function utilAesDecrypt(encryptedHex, key) {
32471           key = key || DEFAULT_128;
32472           var encryptedBytes = aesjs.utils.hex.toBytes(encryptedHex);
32473           var aesCtr = new aesjs.ModeOfOperation.ctr(key);
32474           var decryptedBytes = aesCtr.decrypt(encryptedBytes);
32475           var text = aesjs.utils.utf8.fromBytes(decryptedBytes);
32476           return text;
32477         }
32478
32479         function utilCleanTags(tags) {
32480           var out = {};
32481
32482           for (var k in tags) {
32483             if (!k) continue;
32484             var v = tags[k];
32485
32486             if (v !== undefined) {
32487               out[k] = cleanValue(k, v);
32488             }
32489           }
32490
32491           return out;
32492
32493           function cleanValue(k, v) {
32494             function keepSpaces(k) {
32495               return /_hours|_times|:conditional$/.test(k);
32496             }
32497
32498             function skip(k) {
32499               return /^(description|note|fixme)$/.test(k);
32500             }
32501
32502             if (skip(k)) return v;
32503             var cleaned = v.split(';').map(function (s) {
32504               return s.trim();
32505             }).join(keepSpaces(k) ? '; ' : ';'); // The code below is not intended to validate websites and emails.
32506             // It is only intended to prevent obvious copy-paste errors. (#2323)
32507             // clean website- and email-like tags
32508
32509             if (k.indexOf('website') !== -1 || k.indexOf('email') !== -1 || cleaned.indexOf('http') === 0) {
32510               cleaned = cleaned.replace(/[\u200B-\u200F\uFEFF]/g, ''); // strip LRM and other zero width chars
32511             }
32512
32513             return cleaned;
32514           }
32515         }
32516
32517         var _detected;
32518
32519         function utilDetect(refresh) {
32520           if (_detected && !refresh) return _detected;
32521           _detected = {};
32522           var ua = navigator.userAgent;
32523           var m = null;
32524           /* Browser */
32525
32526           m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i); // Edge
32527
32528           if (m !== null) {
32529             _detected.browser = m[1];
32530             _detected.version = m[2];
32531           }
32532
32533           if (!_detected.browser) {
32534             m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i); // IE11
32535
32536             if (m !== null) {
32537               _detected.browser = 'msie';
32538               _detected.version = m[1];
32539             }
32540           }
32541
32542           if (!_detected.browser) {
32543             m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i); // Opera 15+
32544
32545             if (m !== null) {
32546               _detected.browser = 'Opera';
32547               _detected.version = m[2];
32548             }
32549           }
32550
32551           if (!_detected.browser) {
32552             m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
32553
32554             if (m !== null) {
32555               _detected.browser = m[1];
32556               _detected.version = m[2];
32557               m = ua.match(/version\/([\.\d]+)/i);
32558               if (m !== null) _detected.version = m[1];
32559             }
32560           }
32561
32562           if (!_detected.browser) {
32563             _detected.browser = navigator.appName;
32564             _detected.version = navigator.appVersion;
32565           } // keep major.minor version only..
32566
32567
32568           _detected.version = _detected.version.split(/\W/).slice(0, 2).join('.'); // detect other browser capabilities
32569           // Legacy Opera has incomplete svg style support. See #715
32570
32571           _detected.opera = _detected.browser.toLowerCase() === 'opera' && parseFloat(_detected.version) < 15;
32572
32573           if (_detected.browser.toLowerCase() === 'msie') {
32574             _detected.ie = true;
32575             _detected.browser = 'Internet Explorer';
32576             _detected.support = parseFloat(_detected.version) >= 11;
32577           } else {
32578             _detected.ie = false;
32579             _detected.support = true;
32580           }
32581
32582           _detected.filedrop = window.FileReader && 'ondrop' in window;
32583           _detected.download = !(_detected.ie || _detected.browser.toLowerCase() === 'edge');
32584           _detected.cssfilters = !(_detected.ie || _detected.browser.toLowerCase() === 'edge');
32585           /* Platform */
32586
32587           if (/Win/.test(ua)) {
32588             _detected.os = 'win';
32589             _detected.platform = 'Windows';
32590           } else if (/Mac/.test(ua)) {
32591             _detected.os = 'mac';
32592             _detected.platform = 'Macintosh';
32593           } else if (/X11/.test(ua) || /Linux/.test(ua)) {
32594             _detected.os = 'linux';
32595             _detected.platform = 'Linux';
32596           } else {
32597             _detected.os = 'win';
32598             _detected.platform = 'Unknown';
32599           }
32600
32601           _detected.isMobileWebKit = (/\b(iPad|iPhone|iPod)\b/.test(ua) || // HACK: iPadOS 13+ requests desktop sites by default by using a Mac user agent,
32602           // so assume any "mac" with multitouch is actually iOS
32603           navigator.platform === 'MacIntel' && 'maxTouchPoints' in navigator && navigator.maxTouchPoints > 1) && /WebKit/.test(ua) && !/Edge/.test(ua) && !window.MSStream;
32604           /* Locale */
32605           // An array of locales requested by the browser in priority order.
32606
32607           _detected.browserLocales = Array.from(new Set( // remove duplicates
32608           [navigator.language].concat(navigator.languages || []).concat([// old property for backwards compatibility
32609           navigator.userLanguage]) // remove any undefined values
32610           .filter(Boolean)));
32611           /* Host */
32612
32613           var loc = window.top.location;
32614           var origin = loc.origin;
32615
32616           if (!origin) {
32617             // for unpatched IE11
32618             origin = loc.protocol + '//' + loc.hostname + (loc.port ? ':' + loc.port : '');
32619           }
32620
32621           _detected.host = origin + loc.pathname;
32622           return _detected;
32623         }
32624
32625         // Like selection.property('value', ...), but avoids no-op value sets,
32626         // which can result in layout/repaint thrashing in some situations.
32627
32628         /** @returns {string} */
32629         function utilGetSetValue(selection, value) {
32630           function d3_selection_value(value) {
32631             function valueNull() {
32632               delete this.value;
32633             }
32634
32635             function valueConstant() {
32636               if (this.value !== value) {
32637                 this.value = value;
32638               }
32639             }
32640
32641             function valueFunction() {
32642               var x = value.apply(this, arguments);
32643
32644               if (x === null || x === undefined) {
32645                 delete this.value;
32646               } else if (this.value !== x) {
32647                 this.value = x;
32648               }
32649             }
32650
32651             return value === null || value === undefined ? valueNull : typeof value === 'function' ? valueFunction : valueConstant;
32652           }
32653
32654           if (arguments.length === 1) {
32655             return selection.property('value');
32656           }
32657
32658           return selection.each(d3_selection_value(value));
32659         }
32660
32661         function utilKeybinding(namespace) {
32662           var _keybindings = {};
32663
32664           function testBindings(d3_event, isCapturing) {
32665             var didMatch = false;
32666             var bindings = Object.keys(_keybindings).map(function (id) {
32667               return _keybindings[id];
32668             });
32669             var i, binding; // Most key shortcuts will accept either lower or uppercase ('h' or 'H'),
32670             // so we don't strictly match on the shift key, but we prioritize
32671             // shifted keybindings first, and fallback to unshifted only if no match.
32672             // (This lets us differentiate between '←'/'⇧←' or '⌘Z'/'⌘⇧Z')
32673             // priority match shifted keybindings first
32674
32675             for (i = 0; i < bindings.length; i++) {
32676               binding = bindings[i];
32677               if (!binding.event.modifiers.shiftKey) continue; // no shift
32678
32679               if (!!binding.capture !== isCapturing) continue;
32680
32681               if (matches(d3_event, binding, true)) {
32682                 binding.callback(d3_event);
32683                 didMatch = true; // match a max of one binding per event
32684
32685                 break;
32686               }
32687             }
32688
32689             if (didMatch) return; // then unshifted keybindings
32690
32691             for (i = 0; i < bindings.length; i++) {
32692               binding = bindings[i];
32693               if (binding.event.modifiers.shiftKey) continue; // shift
32694
32695               if (!!binding.capture !== isCapturing) continue;
32696
32697               if (matches(d3_event, binding, false)) {
32698                 binding.callback(d3_event);
32699                 break;
32700               }
32701             }
32702
32703             function matches(d3_event, binding, testShift) {
32704               var event = d3_event;
32705               var isMatch = false;
32706               var tryKeyCode = true; // Prefer a match on `KeyboardEvent.key`
32707
32708               if (event.key !== undefined) {
32709                 tryKeyCode = event.key.charCodeAt(0) > 255; // outside ISO-Latin-1
32710
32711                 isMatch = true;
32712
32713                 if (binding.event.key === undefined) {
32714                   isMatch = false;
32715                 } else if (Array.isArray(binding.event.key)) {
32716                   if (binding.event.key.map(function (s) {
32717                     return s.toLowerCase();
32718                   }).indexOf(event.key.toLowerCase()) === -1) {
32719                     isMatch = false;
32720                   }
32721                 } else {
32722                   if (event.key.toLowerCase() !== binding.event.key.toLowerCase()) {
32723                     isMatch = false;
32724                   }
32725                 }
32726               } // Fallback match on `KeyboardEvent.keyCode`, can happen if:
32727               // - browser doesn't support `KeyboardEvent.key`
32728               // - `KeyboardEvent.key` is outside ISO-Latin-1 range (cyrillic?)
32729
32730
32731               if (!isMatch && tryKeyCode) {
32732                 isMatch = event.keyCode === binding.event.keyCode;
32733               }
32734
32735               if (!isMatch) return false; // test modifier keys
32736
32737               if (!(event.ctrlKey && event.altKey)) {
32738                 // if both are set, assume AltGr and skip it - #4096
32739                 if (event.ctrlKey !== binding.event.modifiers.ctrlKey) return false;
32740                 if (event.altKey !== binding.event.modifiers.altKey) return false;
32741               }
32742
32743               if (event.metaKey !== binding.event.modifiers.metaKey) return false;
32744               if (testShift && event.shiftKey !== binding.event.modifiers.shiftKey) return false;
32745               return true;
32746             }
32747           }
32748
32749           function capture(d3_event) {
32750             testBindings(d3_event, true);
32751           }
32752
32753           function bubble(d3_event) {
32754             var tagName = select(d3_event.target).node().tagName;
32755
32756             if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
32757               return;
32758             }
32759
32760             testBindings(d3_event, false);
32761           }
32762
32763           function keybinding(selection) {
32764             selection = selection || select(document);
32765             selection.on('keydown.capture.' + namespace, capture, true);
32766             selection.on('keydown.bubble.' + namespace, bubble, false);
32767             return keybinding;
32768           } // was: keybinding.off()
32769
32770
32771           keybinding.unbind = function (selection) {
32772             _keybindings = [];
32773             selection = selection || select(document);
32774             selection.on('keydown.capture.' + namespace, null);
32775             selection.on('keydown.bubble.' + namespace, null);
32776             return keybinding;
32777           };
32778
32779           keybinding.clear = function () {
32780             _keybindings = {};
32781             return keybinding;
32782           }; // Remove one or more keycode bindings.
32783
32784
32785           keybinding.off = function (codes, capture) {
32786             var arr = utilArrayUniq([].concat(codes));
32787
32788             for (var i = 0; i < arr.length; i++) {
32789               var id = arr[i] + (capture ? '-capture' : '-bubble');
32790               delete _keybindings[id];
32791             }
32792
32793             return keybinding;
32794           }; // Add one or more keycode bindings.
32795
32796
32797           keybinding.on = function (codes, callback, capture) {
32798             if (typeof callback !== 'function') {
32799               return keybinding.off(codes, capture);
32800             }
32801
32802             var arr = utilArrayUniq([].concat(codes));
32803
32804             for (var i = 0; i < arr.length; i++) {
32805               var id = arr[i] + (capture ? '-capture' : '-bubble');
32806               var binding = {
32807                 id: id,
32808                 capture: capture,
32809                 callback: callback,
32810                 event: {
32811                   key: undefined,
32812                   // preferred
32813                   keyCode: 0,
32814                   // fallback
32815                   modifiers: {
32816                     shiftKey: false,
32817                     ctrlKey: false,
32818                     altKey: false,
32819                     metaKey: false
32820                   }
32821                 }
32822               };
32823
32824               if (_keybindings[id]) {
32825                 console.warn('warning: duplicate keybinding for "' + id + '"'); // eslint-disable-line no-console
32826               }
32827
32828               _keybindings[id] = binding;
32829               var matches = arr[i].toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
32830
32831               for (var j = 0; j < matches.length; j++) {
32832                 // Normalise matching errors
32833                 if (matches[j] === '++') matches[j] = '+';
32834
32835                 if (matches[j] in utilKeybinding.modifierCodes) {
32836                   var prop = utilKeybinding.modifierProperties[utilKeybinding.modifierCodes[matches[j]]];
32837                   binding.event.modifiers[prop] = true;
32838                 } else {
32839                   binding.event.key = utilKeybinding.keys[matches[j]] || matches[j];
32840
32841                   if (matches[j] in utilKeybinding.keyCodes) {
32842                     binding.event.keyCode = utilKeybinding.keyCodes[matches[j]];
32843                   }
32844                 }
32845               }
32846             }
32847
32848             return keybinding;
32849           };
32850
32851           return keybinding;
32852         }
32853         /*
32854          * See https://github.com/keithamus/jwerty
32855          */
32856
32857         utilKeybinding.modifierCodes = {
32858           // Shift key, ⇧
32859           '⇧': 16,
32860           shift: 16,
32861           // CTRL key, on Mac: ⌃
32862           '⌃': 17,
32863           ctrl: 17,
32864           // ALT key, on Mac: ⌥ (Alt)
32865           '⌥': 18,
32866           alt: 18,
32867           option: 18,
32868           // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
32869           '⌘': 91,
32870           meta: 91,
32871           cmd: 91,
32872           'super': 91,
32873           win: 91
32874         };
32875         utilKeybinding.modifierProperties = {
32876           16: 'shiftKey',
32877           17: 'ctrlKey',
32878           18: 'altKey',
32879           91: 'metaKey'
32880         };
32881         utilKeybinding.plusKeys = ['plus', 'ffplus', '=', 'ffequals', '≠', '±'];
32882         utilKeybinding.minusKeys = ['_', '-', 'ffminus', 'dash', '–', '—'];
32883         utilKeybinding.keys = {
32884           // Backspace key, on Mac: ⌫ (Backspace)
32885           '⌫': 'Backspace',
32886           backspace: 'Backspace',
32887           // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
32888           '⇥': 'Tab',
32889           '⇆': 'Tab',
32890           tab: 'Tab',
32891           // Return key, ↩
32892           '↩': 'Enter',
32893           '↵': 'Enter',
32894           '⏎': 'Enter',
32895           'return': 'Enter',
32896           enter: 'Enter',
32897           '⌅': 'Enter',
32898           // Pause/Break key
32899           'pause': 'Pause',
32900           'pause-break': 'Pause',
32901           // Caps Lock key, ⇪
32902           '⇪': 'CapsLock',
32903           caps: 'CapsLock',
32904           'caps-lock': 'CapsLock',
32905           // Escape key, on Mac: ⎋, on Windows: Esc
32906           '⎋': ['Escape', 'Esc'],
32907           escape: ['Escape', 'Esc'],
32908           esc: ['Escape', 'Esc'],
32909           // Space key
32910           space: [' ', 'Spacebar'],
32911           // Page-Up key, or pgup, on Mac: ↖
32912           '↖': 'PageUp',
32913           pgup: 'PageUp',
32914           'page-up': 'PageUp',
32915           // Page-Down key, or pgdown, on Mac: ↘
32916           '↘': 'PageDown',
32917           pgdown: 'PageDown',
32918           'page-down': 'PageDown',
32919           // END key, on Mac: ⇟
32920           '⇟': 'End',
32921           end: 'End',
32922           // HOME key, on Mac: ⇞
32923           '⇞': 'Home',
32924           home: 'Home',
32925           // Insert key, or ins
32926           ins: 'Insert',
32927           insert: 'Insert',
32928           // Delete key, on Mac: ⌦ (Delete)
32929           '⌦': ['Delete', 'Del'],
32930           del: ['Delete', 'Del'],
32931           'delete': ['Delete', 'Del'],
32932           // Left Arrow Key, or ←
32933           '←': ['ArrowLeft', 'Left'],
32934           left: ['ArrowLeft', 'Left'],
32935           'arrow-left': ['ArrowLeft', 'Left'],
32936           // Up Arrow Key, or ↑
32937           '↑': ['ArrowUp', 'Up'],
32938           up: ['ArrowUp', 'Up'],
32939           'arrow-up': ['ArrowUp', 'Up'],
32940           // Right Arrow Key, or →
32941           '→': ['ArrowRight', 'Right'],
32942           right: ['ArrowRight', 'Right'],
32943           'arrow-right': ['ArrowRight', 'Right'],
32944           // Up Arrow Key, or ↓
32945           '↓': ['ArrowDown', 'Down'],
32946           down: ['ArrowDown', 'Down'],
32947           'arrow-down': ['ArrowDown', 'Down'],
32948           // odities, stuff for backward compatibility (browsers and code):
32949           // Num-Multiply, or *
32950           '*': ['*', 'Multiply'],
32951           star: ['*', 'Multiply'],
32952           asterisk: ['*', 'Multiply'],
32953           multiply: ['*', 'Multiply'],
32954           // Num-Plus or +
32955           '+': ['+', 'Add'],
32956           'plus': ['+', 'Add'],
32957           // Num-Subtract, or -
32958           '-': ['-', 'Subtract'],
32959           subtract: ['-', 'Subtract'],
32960           'dash': ['-', 'Subtract'],
32961           // Semicolon
32962           semicolon: ';',
32963           // = or equals
32964           equals: '=',
32965           // Comma, or ,
32966           comma: ',',
32967           // Period, or ., or full-stop
32968           period: '.',
32969           'full-stop': '.',
32970           // Slash, or /, or forward-slash
32971           slash: '/',
32972           'forward-slash': '/',
32973           // Tick, or `, or back-quote
32974           tick: '`',
32975           'back-quote': '`',
32976           // Open bracket, or [
32977           'open-bracket': '[',
32978           // Back slash, or \
32979           'back-slash': '\\',
32980           // Close backet, or ]
32981           'close-bracket': ']',
32982           // Apostrophe, or Quote, or '
32983           quote: '\'',
32984           apostrophe: '\'',
32985           // NUMPAD 0-9
32986           'num-0': '0',
32987           'num-1': '1',
32988           'num-2': '2',
32989           'num-3': '3',
32990           'num-4': '4',
32991           'num-5': '5',
32992           'num-6': '6',
32993           'num-7': '7',
32994           'num-8': '8',
32995           'num-9': '9',
32996           // F1-F25
32997           f1: 'F1',
32998           f2: 'F2',
32999           f3: 'F3',
33000           f4: 'F4',
33001           f5: 'F5',
33002           f6: 'F6',
33003           f7: 'F7',
33004           f8: 'F8',
33005           f9: 'F9',
33006           f10: 'F10',
33007           f11: 'F11',
33008           f12: 'F12',
33009           f13: 'F13',
33010           f14: 'F14',
33011           f15: 'F15',
33012           f16: 'F16',
33013           f17: 'F17',
33014           f18: 'F18',
33015           f19: 'F19',
33016           f20: 'F20',
33017           f21: 'F21',
33018           f22: 'F22',
33019           f23: 'F23',
33020           f24: 'F24',
33021           f25: 'F25'
33022         };
33023         utilKeybinding.keyCodes = {
33024           // Backspace key, on Mac: ⌫ (Backspace)
33025           '⌫': 8,
33026           backspace: 8,
33027           // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
33028           '⇥': 9,
33029           '⇆': 9,
33030           tab: 9,
33031           // Return key, ↩
33032           '↩': 13,
33033           '↵': 13,
33034           '⏎': 13,
33035           'return': 13,
33036           enter: 13,
33037           '⌅': 13,
33038           // Pause/Break key
33039           'pause': 19,
33040           'pause-break': 19,
33041           // Caps Lock key, ⇪
33042           '⇪': 20,
33043           caps: 20,
33044           'caps-lock': 20,
33045           // Escape key, on Mac: ⎋, on Windows: Esc
33046           '⎋': 27,
33047           escape: 27,
33048           esc: 27,
33049           // Space key
33050           space: 32,
33051           // Page-Up key, or pgup, on Mac: ↖
33052           '↖': 33,
33053           pgup: 33,
33054           'page-up': 33,
33055           // Page-Down key, or pgdown, on Mac: ↘
33056           '↘': 34,
33057           pgdown: 34,
33058           'page-down': 34,
33059           // END key, on Mac: ⇟
33060           '⇟': 35,
33061           end: 35,
33062           // HOME key, on Mac: ⇞
33063           '⇞': 36,
33064           home: 36,
33065           // Insert key, or ins
33066           ins: 45,
33067           insert: 45,
33068           // Delete key, on Mac: ⌦ (Delete)
33069           '⌦': 46,
33070           del: 46,
33071           'delete': 46,
33072           // Left Arrow Key, or ←
33073           '←': 37,
33074           left: 37,
33075           'arrow-left': 37,
33076           // Up Arrow Key, or ↑
33077           '↑': 38,
33078           up: 38,
33079           'arrow-up': 38,
33080           // Right Arrow Key, or →
33081           '→': 39,
33082           right: 39,
33083           'arrow-right': 39,
33084           // Up Arrow Key, or ↓
33085           '↓': 40,
33086           down: 40,
33087           'arrow-down': 40,
33088           // odities, printing characters that come out wrong:
33089           // Firefox Equals
33090           'ffequals': 61,
33091           // Num-Multiply, or *
33092           '*': 106,
33093           star: 106,
33094           asterisk: 106,
33095           multiply: 106,
33096           // Num-Plus or +
33097           '+': 107,
33098           'plus': 107,
33099           // Num-Subtract, or -
33100           '-': 109,
33101           subtract: 109,
33102           // Vertical Bar / Pipe
33103           '|': 124,
33104           // Firefox Plus
33105           'ffplus': 171,
33106           // Firefox Minus
33107           'ffminus': 173,
33108           // Semicolon
33109           ';': 186,
33110           semicolon: 186,
33111           // = or equals
33112           '=': 187,
33113           'equals': 187,
33114           // Comma, or ,
33115           ',': 188,
33116           comma: 188,
33117           // Dash / Underscore key
33118           'dash': 189,
33119           // Period, or ., or full-stop
33120           '.': 190,
33121           period: 190,
33122           'full-stop': 190,
33123           // Slash, or /, or forward-slash
33124           '/': 191,
33125           slash: 191,
33126           'forward-slash': 191,
33127           // Tick, or `, or back-quote
33128           '`': 192,
33129           tick: 192,
33130           'back-quote': 192,
33131           // Open bracket, or [
33132           '[': 219,
33133           'open-bracket': 219,
33134           // Back slash, or \
33135           '\\': 220,
33136           'back-slash': 220,
33137           // Close backet, or ]
33138           ']': 221,
33139           'close-bracket': 221,
33140           // Apostrophe, or Quote, or '
33141           '\'': 222,
33142           quote: 222,
33143           apostrophe: 222
33144         }; // NUMPAD 0-9
33145
33146         var i = 95,
33147             n = 0;
33148
33149         while (++i < 106) {
33150           utilKeybinding.keyCodes['num-' + n] = i;
33151           ++n;
33152         } // 0-9
33153
33154
33155         i = 47;
33156         n = 0;
33157
33158         while (++i < 58) {
33159           utilKeybinding.keyCodes[n] = i;
33160           ++n;
33161         } // F1-F25
33162
33163
33164         i = 111;
33165         n = 1;
33166
33167         while (++i < 136) {
33168           utilKeybinding.keyCodes['f' + n] = i;
33169           ++n;
33170         } // a-z
33171
33172
33173         i = 64;
33174
33175         while (++i < 91) {
33176           utilKeybinding.keyCodes[String.fromCharCode(i).toLowerCase()] = i;
33177         }
33178
33179         function utilObjectOmit(obj, omitKeys) {
33180           return Object.keys(obj).reduce(function (result, key) {
33181             if (omitKeys.indexOf(key) === -1) {
33182               result[key] = obj[key]; // keep
33183             }
33184
33185             return result;
33186           }, {});
33187         }
33188
33189         // Copies a variable number of methods from source to target.
33190         function utilRebind(target, source) {
33191           var i = 1,
33192               n = arguments.length,
33193               method;
33194
33195           while (++i < n) {
33196             target[method = arguments[i]] = d3_rebind(target, source, source[method]);
33197           }
33198
33199           return target;
33200         } // Method is assumed to be a standard D3 getter-setter:
33201         // If passed with no arguments, gets the value.
33202         // If passed with arguments, sets the value and returns the target.
33203
33204         function d3_rebind(target, source, method) {
33205           return function () {
33206             var value = method.apply(source, arguments);
33207             return value === source ? target : value;
33208           };
33209         }
33210
33211         // A per-domain session mutex backed by a cookie and dead man's
33212         // switch. If the session crashes, the mutex will auto-release
33213         // after 5 seconds.
33214         // This accepts a string and returns an object that complies with utilSessionMutexType
33215         function utilSessionMutex(name) {
33216           var mutex = {};
33217           var intervalID;
33218
33219           function renew() {
33220             var expires = new Date();
33221             expires.setSeconds(expires.getSeconds() + 5);
33222             document.cookie = name + '=1; expires=' + expires.toUTCString() + '; sameSite=strict';
33223           }
33224
33225           mutex.lock = function () {
33226             if (intervalID) return true;
33227             var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
33228             if (cookie) return false;
33229             renew();
33230             intervalID = window.setInterval(renew, 4000);
33231             return true;
33232           };
33233
33234           mutex.unlock = function () {
33235             if (!intervalID) return;
33236             document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; sameSite=strict';
33237             clearInterval(intervalID);
33238             intervalID = null;
33239           };
33240
33241           mutex.locked = function () {
33242             return !!intervalID;
33243           };
33244
33245           return mutex;
33246         }
33247
33248         function utilTiler() {
33249           var _size = [256, 256];
33250           var _scale = 256;
33251           var _tileSize = 256;
33252           var _zoomExtent = [0, 20];
33253           var _translate = [_size[0] / 2, _size[1] / 2];
33254           var _margin = 0;
33255           var _skipNullIsland = false;
33256
33257           function clamp(num, min, max) {
33258             return Math.max(min, Math.min(num, max));
33259           }
33260
33261           function nearNullIsland(tile) {
33262             var x = tile[0];
33263             var y = tile[1];
33264             var z = tile[2];
33265
33266             if (z >= 7) {
33267               var center = Math.pow(2, z - 1);
33268               var width = Math.pow(2, z - 6);
33269               var min = center - width / 2;
33270               var max = center + width / 2 - 1;
33271               return x >= min && x <= max && y >= min && y <= max;
33272             }
33273
33274             return false;
33275           }
33276
33277           function tiler() {
33278             var z = geoScaleToZoom(_scale / (2 * Math.PI), _tileSize);
33279             var z0 = clamp(Math.round(z), _zoomExtent[0], _zoomExtent[1]);
33280             var tileMin = 0;
33281             var tileMax = Math.pow(2, z0) - 1;
33282             var log2ts = Math.log(_tileSize) * Math.LOG2E;
33283             var k = Math.pow(2, z - z0 + log2ts);
33284             var origin = [(_translate[0] - _scale / 2) / k, (_translate[1] - _scale / 2) / k];
33285             var cols = range$1(clamp(Math.floor(-origin[0]) - _margin, tileMin, tileMax + 1), clamp(Math.ceil(_size[0] / k - origin[0]) + _margin, tileMin, tileMax + 1));
33286             var rows = range$1(clamp(Math.floor(-origin[1]) - _margin, tileMin, tileMax + 1), clamp(Math.ceil(_size[1] / k - origin[1]) + _margin, tileMin, tileMax + 1));
33287             var tiles = [];
33288
33289             for (var i = 0; i < rows.length; i++) {
33290               var y = rows[i];
33291
33292               for (var j = 0; j < cols.length; j++) {
33293                 var x = cols[j];
33294
33295                 if (i >= _margin && i <= rows.length - _margin && j >= _margin && j <= cols.length - _margin) {
33296                   tiles.unshift([x, y, z0]); // tiles in view at beginning
33297                 } else {
33298                   tiles.push([x, y, z0]); // tiles in margin at the end
33299                 }
33300               }
33301             }
33302
33303             tiles.translate = origin;
33304             tiles.scale = k;
33305             return tiles;
33306           }
33307           /**
33308            * getTiles() returns an array of tiles that cover the map view
33309            */
33310
33311
33312           tiler.getTiles = function (projection) {
33313             var origin = [projection.scale() * Math.PI - projection.translate()[0], projection.scale() * Math.PI - projection.translate()[1]];
33314             this.size(projection.clipExtent()[1]).scale(projection.scale() * 2 * Math.PI).translate(projection.translate());
33315             var tiles = tiler();
33316             var ts = tiles.scale;
33317             return tiles.map(function (tile) {
33318               if (_skipNullIsland && nearNullIsland(tile)) {
33319                 return false;
33320               }
33321
33322               var x = tile[0] * ts - origin[0];
33323               var y = tile[1] * ts - origin[1];
33324               return {
33325                 id: tile.toString(),
33326                 xyz: tile,
33327                 extent: geoExtent(projection.invert([x, y + ts]), projection.invert([x + ts, y]))
33328               };
33329             }).filter(Boolean);
33330           };
33331           /**
33332            * getGeoJSON() returns a FeatureCollection for debugging tiles
33333            */
33334
33335
33336           tiler.getGeoJSON = function (projection) {
33337             var features = tiler.getTiles(projection).map(function (tile) {
33338               return {
33339                 type: 'Feature',
33340                 properties: {
33341                   id: tile.id,
33342                   name: tile.id
33343                 },
33344                 geometry: {
33345                   type: 'Polygon',
33346                   coordinates: [tile.extent.polygon()]
33347                 }
33348               };
33349             });
33350             return {
33351               type: 'FeatureCollection',
33352               features: features
33353             };
33354           };
33355
33356           tiler.tileSize = function (val) {
33357             if (!arguments.length) return _tileSize;
33358             _tileSize = val;
33359             return tiler;
33360           };
33361
33362           tiler.zoomExtent = function (val) {
33363             if (!arguments.length) return _zoomExtent;
33364             _zoomExtent = val;
33365             return tiler;
33366           };
33367
33368           tiler.size = function (val) {
33369             if (!arguments.length) return _size;
33370             _size = val;
33371             return tiler;
33372           };
33373
33374           tiler.scale = function (val) {
33375             if (!arguments.length) return _scale;
33376             _scale = val;
33377             return tiler;
33378           };
33379
33380           tiler.translate = function (val) {
33381             if (!arguments.length) return _translate;
33382             _translate = val;
33383             return tiler;
33384           }; // number to extend the rows/columns beyond those covering the viewport
33385
33386
33387           tiler.margin = function (val) {
33388             if (!arguments.length) return _margin;
33389             _margin = +val;
33390             return tiler;
33391           };
33392
33393           tiler.skipNullIsland = function (val) {
33394             if (!arguments.length) return _skipNullIsland;
33395             _skipNullIsland = val;
33396             return tiler;
33397           };
33398
33399           return tiler;
33400         }
33401
33402         function utilTriggerEvent(target, type) {
33403           target.each(function () {
33404             var evt = document.createEvent('HTMLEvents');
33405             evt.initEvent(type, true, true);
33406             this.dispatchEvent(evt);
33407           });
33408         }
33409
33410         var _mainLocations = coreLocations(); // singleton
33411         // `coreLocations` maintains an internal index of all the boundaries/geofences used by iD.
33412         // It's used by presets, community index, background imagery, to know where in the world these things are valid.
33413         // These geofences should be defined by `locationSet` objects:
33414         //
33415         // let locationSet = {
33416         //   include: [ Array of locations ],
33417         //   exclude: [ Array of locations ]
33418         // };
33419         //
33420         // For more info see the location-conflation and country-coder projects, see:
33421         // https://github.com/ideditor/location-conflation
33422         // https://github.com/ideditor/country-coder
33423         //
33424
33425         function coreLocations() {
33426           var _this = {};
33427           var _resolvedFeatures = {}; // cache of *resolved* locationSet features
33428
33429           var _loco = new _default(); // instance of a location-conflation resolver
33430
33431
33432           var _wp; // instance of a which-polygon index
33433           // pre-resolve the worldwide locationSet
33434
33435
33436           var world = {
33437             locationSet: {
33438               include: ['Q2']
33439             }
33440           };
33441           resolveLocationSet(world);
33442           rebuildIndex();
33443           var _queue = [];
33444
33445           var _deferred = new Set();
33446
33447           var _inProcess; // Returns a Promise to process the queue
33448
33449
33450           function processQueue() {
33451             if (!_queue.length) return Promise.resolve(); // console.log(`queue length ${_queue.length}`);
33452
33453             var chunk = _queue.pop();
33454
33455             return new Promise(function (resolvePromise) {
33456               var handle = window.requestIdleCallback(function () {
33457                 _deferred["delete"](handle); // const t0 = performance.now();
33458
33459
33460                 chunk.forEach(resolveLocationSet); // const t1 = performance.now();
33461                 // console.log('chunk processed in ' + (t1 - t0) + ' ms');
33462
33463                 resolvePromise();
33464               });
33465
33466               _deferred.add(handle);
33467             }).then(function () {
33468               return processQueue();
33469             });
33470           } // Pass an Object with a `locationSet` property,
33471           // Performs the locationSet resolution, caches the result, and sets a `locationSetID` property on the object.
33472
33473
33474           function resolveLocationSet(obj) {
33475             if (obj.locationSetID) return; // work was done already
33476
33477             try {
33478               var locationSet = obj.locationSet;
33479
33480               if (!locationSet) {
33481                 throw new Error('object missing locationSet property');
33482               }
33483
33484               if (!locationSet.include) {
33485                 // missing `include`, default to worldwide include
33486                 locationSet.include = ['Q2']; // https://github.com/openstreetmap/iD/pull/8305#discussion_r662344647
33487               }
33488
33489               var resolved = _loco.resolveLocationSet(locationSet);
33490
33491               var locationSetID = resolved.id;
33492               obj.locationSetID = locationSetID;
33493
33494               if (!resolved.feature.geometry.coordinates.length || !resolved.feature.properties.area) {
33495                 throw new Error("locationSet ".concat(locationSetID, " resolves to an empty feature."));
33496               }
33497
33498               if (!_resolvedFeatures[locationSetID]) {
33499                 // First time seeing this locationSet feature
33500                 var feature = JSON.parse(JSON.stringify(resolved.feature)); // deep clone
33501
33502                 feature.id = locationSetID; // Important: always use the locationSet `id` (`+[Q30]`), not the feature `id` (`Q30`)
33503
33504                 feature.properties.id = locationSetID;
33505                 _resolvedFeatures[locationSetID] = feature; // insert into cache
33506               }
33507             } catch (err) {
33508               obj.locationSet = {
33509                 include: ['Q2']
33510               }; // default worldwide
33511
33512               obj.locationSetID = '+[Q2]';
33513             }
33514           } // Rebuilds the whichPolygon index with whatever features have been resolved.
33515
33516
33517           function rebuildIndex() {
33518             _wp = whichPolygon_1({
33519               features: Object.values(_resolvedFeatures)
33520             });
33521           } //
33522           // `mergeCustomGeoJSON`
33523           //  Accepts an FeatureCollection-like object containing custom locations
33524           //  Each feature must have a filename-like `id`, for example: `something.geojson`
33525           //
33526           //  {
33527           //    "type": "FeatureCollection"
33528           //    "features": [
33529           //      {
33530           //        "type": "Feature",
33531           //        "id": "philly_metro.geojson",
33532           //        "properties": { … },
33533           //        "geometry": { … }
33534           //      }
33535           //    ]
33536           //  }
33537           //
33538
33539
33540           _this.mergeCustomGeoJSON = function (fc) {
33541             if (fc && fc.type === 'FeatureCollection' && Array.isArray(fc.features)) {
33542               fc.features.forEach(function (feature) {
33543                 feature.properties = feature.properties || {};
33544                 var props = feature.properties; // Get `id` from either `id` or `properties`
33545
33546                 var id = feature.id || props.id;
33547                 if (!id || !/^\S+\.geojson$/i.test(id)) return; // Ensure `id` exists and is lowercase
33548
33549                 id = id.toLowerCase();
33550                 feature.id = id;
33551                 props.id = id; // Ensure `area` property exists
33552
33553                 if (!props.area) {
33554                   var area = geojsonArea.geometry(feature.geometry) / 1e6; // m² to km²
33555
33556                   props.area = Number(area.toFixed(2));
33557                 }
33558
33559                 _loco._cache[id] = feature;
33560               });
33561             }
33562           }; //
33563           // `mergeLocationSets`
33564           //  Accepts an Array of Objects containing `locationSet` properties.
33565           //  The locationSets will be resolved and indexed in the background.
33566           //  [
33567           //   { id: 'preset1', locationSet: {…} },
33568           //   { id: 'preset2', locationSet: {…} },
33569           //   { id: 'preset3', locationSet: {…} },
33570           //   …
33571           //  ]
33572           //  After resolving and indexing, the Objects will be decorated with a
33573           //  `locationSetID` property.
33574           //  [
33575           //   { id: 'preset1', locationSet: {…}, locationSetID: '+[Q2]' },
33576           //   { id: 'preset2', locationSet: {…}, locationSetID: '+[Q30]' },
33577           //   { id: 'preset3', locationSet: {…}, locationSetID: '+[Q2]' },
33578           //   …
33579           //  ]
33580           //
33581           //  Returns a Promise fulfilled when the resolving/indexing has been completed
33582           //  This will take some seconds but happen in the background during browser idle time.
33583           //
33584
33585
33586           _this.mergeLocationSets = function (objects) {
33587             if (!Array.isArray(objects)) return Promise.reject('nothing to do'); // Resolve all locationSets -> geojson, processing data in chunks
33588             //
33589             // Because this will happen during idle callbacks, we want to choose a chunk size
33590             // that won't make the browser stutter too badly.  LocationSets that are a simple
33591             // country coder include will resolve instantly, but ones that involve complex
33592             // include/exclude operations will take some milliseconds longer.
33593             //
33594             // Some discussion and performance results on these tickets:
33595             // https://github.com/ideditor/location-conflation/issues/26
33596             // https://github.com/osmlab/name-suggestion-index/issues/4784#issuecomment-742003434
33597
33598             _queue = _queue.concat(utilArrayChunk(objects, 200));
33599
33600             if (!_inProcess) {
33601               _inProcess = processQueue().then(function () {
33602                 rebuildIndex();
33603                 _inProcess = null;
33604                 return objects;
33605               });
33606             }
33607
33608             return _inProcess;
33609           }; //
33610           // `locationSetID`
33611           // Returns a locationSetID for a given locationSet (fallback to `+[Q2]`, world)
33612           // (The locationset doesn't necessarily need to be resolved to compute its `id`)
33613           //
33614           // Arguments
33615           //   `locationSet`: A locationSet, e.g. `{ include: ['us'] }`
33616           // Returns
33617           //   The locationSetID, e.g. `+[Q30]`
33618           //
33619
33620
33621           _this.locationSetID = function (locationSet) {
33622             var locationSetID;
33623
33624             try {
33625               locationSetID = _loco.validateLocationSet(locationSet).id;
33626             } catch (err) {
33627               locationSetID = '+[Q2]'; // the world
33628             }
33629
33630             return locationSetID;
33631           }; //
33632           // `feature`
33633           // Returns the resolved GeoJSON feature for a given locationSetID (fallback to 'world')
33634           //
33635           // Arguments
33636           //   `locationSetID`: id of the form like `+[Q30]`  (United States)
33637           // Returns
33638           //   A GeoJSON feature:
33639           //   {
33640           //     type: 'Feature',
33641           //     id: '+[Q30]',
33642           //     properties: { id: '+[Q30]', area: 21817019.17, … },
33643           //     geometry: { … }
33644           //   }
33645
33646
33647           _this.feature = function (locationSetID) {
33648             return _resolvedFeatures[locationSetID] || _resolvedFeatures['+[Q2]'];
33649           }; //
33650           // `locationsAt`
33651           // Find all the resolved locationSets valid at the given location.
33652           // Results include the area (in km²) to facilitate sorting.
33653           //
33654           // Arguments
33655           //   `loc`: the [lon,lat] location to query, e.g. `[-74.4813, 40.7967]`
33656           // Returns
33657           //   Object of locationSetIDs to areas (in km²)
33658           //   {
33659           //     "+[Q2]": 511207893.3958111,
33660           //     "+[Q30]": 21817019.17,
33661           //     "+[new_jersey.geojson]": 22390.77,
33662           //     …
33663           //   }
33664           //
33665
33666
33667           _this.locationsAt = function (loc) {
33668             var result = {};
33669             (_wp(loc, true) || []).forEach(function (prop) {
33670               return result[prop.id] = prop.area;
33671             });
33672             return result;
33673           }; //
33674           // `query`
33675           // Execute a query directly against which-polygon
33676           // https://github.com/mapbox/which-polygon
33677           //
33678           // Arguments
33679           //   `loc`: the [lon,lat] location to query,
33680           //   `multi`: `true` to return all results, `false` to return first result
33681           // Returns
33682           //   Array of GeoJSON *properties* for the locationSet features that exist at `loc`
33683           //
33684
33685
33686           _this.query = function (loc, multi) {
33687             return _wp(loc, multi);
33688           }; // Direct access to the location-conflation resolver
33689
33690
33691           _this.loco = function () {
33692             return _loco;
33693           }; // Direct access to the which-polygon index
33694
33695
33696           _this.wp = function () {
33697             return _wp;
33698           };
33699
33700           return _this;
33701         }
33702
33703         var $$h = _export;
33704         var $findIndex = arrayIteration.findIndex;
33705         var addToUnscopables$1 = addToUnscopables$6;
33706
33707         var FIND_INDEX = 'findIndex';
33708         var SKIPS_HOLES = true;
33709
33710         // Shouldn't skip holes
33711         if (FIND_INDEX in []) Array(1)[FIND_INDEX](function () { SKIPS_HOLES = false; });
33712
33713         // `Array.prototype.findIndex` method
33714         // https://tc39.es/ecma262/#sec-array.prototype.findindex
33715         $$h({ target: 'Array', proto: true, forced: SKIPS_HOLES }, {
33716           findIndex: function findIndex(callbackfn /* , that = undefined */) {
33717             return $findIndex(this, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
33718           }
33719         });
33720
33721         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
33722         addToUnscopables$1(FIND_INDEX);
33723
33724         var global$5 = global$1o;
33725         var isRegExp = isRegexp;
33726
33727         var TypeError$3 = global$5.TypeError;
33728
33729         var notARegexp = function (it) {
33730           if (isRegExp(it)) {
33731             throw TypeError$3("The method doesn't accept regular expressions");
33732           } return it;
33733         };
33734
33735         var wellKnownSymbol = wellKnownSymbol$t;
33736
33737         var MATCH = wellKnownSymbol('match');
33738
33739         var correctIsRegexpLogic = function (METHOD_NAME) {
33740           var regexp = /./;
33741           try {
33742             '/./'[METHOD_NAME](regexp);
33743           } catch (error1) {
33744             try {
33745               regexp[MATCH] = false;
33746               return '/./'[METHOD_NAME](regexp);
33747             } catch (error2) { /* empty */ }
33748           } return false;
33749         };
33750
33751         var $$g = _export;
33752         var uncurryThis$7 = functionUncurryThis;
33753         var notARegExp$2 = notARegexp;
33754         var requireObjectCoercible$3 = requireObjectCoercible$e;
33755         var toString$4 = toString$k;
33756         var correctIsRegExpLogic$2 = correctIsRegexpLogic;
33757
33758         var stringIndexOf = uncurryThis$7(''.indexOf);
33759
33760         // `String.prototype.includes` method
33761         // https://tc39.es/ecma262/#sec-string.prototype.includes
33762         $$g({ target: 'String', proto: true, forced: !correctIsRegExpLogic$2('includes') }, {
33763           includes: function includes(searchString /* , position = 0 */) {
33764             return !!~stringIndexOf(
33765               toString$4(requireObjectCoercible$3(this)),
33766               toString$4(notARegExp$2(searchString)),
33767               arguments.length > 1 ? arguments[1] : undefined
33768             );
33769           }
33770         });
33771
33772         /** Detect free variable `global` from Node.js. */
33773         var freeGlobal = (typeof global === "undefined" ? "undefined" : _typeof(global)) == 'object' && global && global.Object === Object && global;
33774
33775         /** Detect free variable `self`. */
33776
33777         var freeSelf = (typeof self === "undefined" ? "undefined" : _typeof(self)) == 'object' && self && self.Object === Object && self;
33778         /** Used as a reference to the global object. */
33779
33780         var root = freeGlobal || freeSelf || Function('return this')();
33781
33782         /** Built-in value references. */
33783
33784         var _Symbol = root.Symbol;
33785
33786         /** Used for built-in method references. */
33787
33788         var objectProto$1 = Object.prototype;
33789         /** Used to check objects for own properties. */
33790
33791         var hasOwnProperty$2 = objectProto$1.hasOwnProperty;
33792         /**
33793          * Used to resolve the
33794          * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
33795          * of values.
33796          */
33797
33798         var nativeObjectToString$1 = objectProto$1.toString;
33799         /** Built-in value references. */
33800
33801         var symToStringTag$1 = _Symbol ? _Symbol.toStringTag : undefined;
33802         /**
33803          * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
33804          *
33805          * @private
33806          * @param {*} value The value to query.
33807          * @returns {string} Returns the raw `toStringTag`.
33808          */
33809
33810         function getRawTag(value) {
33811           var isOwn = hasOwnProperty$2.call(value, symToStringTag$1),
33812               tag = value[symToStringTag$1];
33813
33814           try {
33815             value[symToStringTag$1] = undefined;
33816             var unmasked = true;
33817           } catch (e) {}
33818
33819           var result = nativeObjectToString$1.call(value);
33820
33821           if (unmasked) {
33822             if (isOwn) {
33823               value[symToStringTag$1] = tag;
33824             } else {
33825               delete value[symToStringTag$1];
33826             }
33827           }
33828
33829           return result;
33830         }
33831
33832         /** Used for built-in method references. */
33833         var objectProto = Object.prototype;
33834         /**
33835          * Used to resolve the
33836          * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
33837          * of values.
33838          */
33839
33840         var nativeObjectToString = objectProto.toString;
33841         /**
33842          * Converts `value` to a string using `Object.prototype.toString`.
33843          *
33844          * @private
33845          * @param {*} value The value to convert.
33846          * @returns {string} Returns the converted string.
33847          */
33848
33849         function objectToString(value) {
33850           return nativeObjectToString.call(value);
33851         }
33852
33853         /** `Object#toString` result references. */
33854
33855         var nullTag = '[object Null]',
33856             undefinedTag = '[object Undefined]';
33857         /** Built-in value references. */
33858
33859         var symToStringTag = _Symbol ? _Symbol.toStringTag : undefined;
33860         /**
33861          * The base implementation of `getTag` without fallbacks for buggy environments.
33862          *
33863          * @private
33864          * @param {*} value The value to query.
33865          * @returns {string} Returns the `toStringTag`.
33866          */
33867
33868         function baseGetTag(value) {
33869           if (value == null) {
33870             return value === undefined ? undefinedTag : nullTag;
33871           }
33872
33873           return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
33874         }
33875
33876         /**
33877          * Checks if `value` is object-like. A value is object-like if it's not `null`
33878          * and has a `typeof` result of "object".
33879          *
33880          * @static
33881          * @memberOf _
33882          * @since 4.0.0
33883          * @category Lang
33884          * @param {*} value The value to check.
33885          * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
33886          * @example
33887          *
33888          * _.isObjectLike({});
33889          * // => true
33890          *
33891          * _.isObjectLike([1, 2, 3]);
33892          * // => true
33893          *
33894          * _.isObjectLike(_.noop);
33895          * // => false
33896          *
33897          * _.isObjectLike(null);
33898          * // => false
33899          */
33900         function isObjectLike(value) {
33901           return value != null && _typeof(value) == 'object';
33902         }
33903
33904         /** `Object#toString` result references. */
33905
33906         var symbolTag = '[object Symbol]';
33907         /**
33908          * Checks if `value` is classified as a `Symbol` primitive or object.
33909          *
33910          * @static
33911          * @memberOf _
33912          * @since 4.0.0
33913          * @category Lang
33914          * @param {*} value The value to check.
33915          * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
33916          * @example
33917          *
33918          * _.isSymbol(Symbol.iterator);
33919          * // => true
33920          *
33921          * _.isSymbol('abc');
33922          * // => false
33923          */
33924
33925         function isSymbol(value) {
33926           return _typeof(value) == 'symbol' || isObjectLike(value) && baseGetTag(value) == symbolTag;
33927         }
33928
33929         /**
33930          * A specialized version of `_.map` for arrays without support for iteratee
33931          * shorthands.
33932          *
33933          * @private
33934          * @param {Array} [array] The array to iterate over.
33935          * @param {Function} iteratee The function invoked per iteration.
33936          * @returns {Array} Returns the new mapped array.
33937          */
33938         function arrayMap(array, iteratee) {
33939           var index = -1,
33940               length = array == null ? 0 : array.length,
33941               result = Array(length);
33942
33943           while (++index < length) {
33944             result[index] = iteratee(array[index], index, array);
33945           }
33946
33947           return result;
33948         }
33949
33950         /**
33951          * Checks if `value` is classified as an `Array` object.
33952          *
33953          * @static
33954          * @memberOf _
33955          * @since 0.1.0
33956          * @category Lang
33957          * @param {*} value The value to check.
33958          * @returns {boolean} Returns `true` if `value` is an array, else `false`.
33959          * @example
33960          *
33961          * _.isArray([1, 2, 3]);
33962          * // => true
33963          *
33964          * _.isArray(document.body.children);
33965          * // => false
33966          *
33967          * _.isArray('abc');
33968          * // => false
33969          *
33970          * _.isArray(_.noop);
33971          * // => false
33972          */
33973         var isArray$1 = Array.isArray;
33974
33975         /** Used as references for various `Number` constants. */
33976
33977         var INFINITY = 1 / 0;
33978         /** Used to convert symbols to primitives and strings. */
33979
33980         var symbolProto = _Symbol ? _Symbol.prototype : undefined,
33981             symbolToString = symbolProto ? symbolProto.toString : undefined;
33982         /**
33983          * The base implementation of `_.toString` which doesn't convert nullish
33984          * values to empty strings.
33985          *
33986          * @private
33987          * @param {*} value The value to process.
33988          * @returns {string} Returns the string.
33989          */
33990
33991         function baseToString(value) {
33992           // Exit early for strings to avoid a performance hit in some environments.
33993           if (typeof value == 'string') {
33994             return value;
33995           }
33996
33997           if (isArray$1(value)) {
33998             // Recursively convert values (susceptible to call stack limits).
33999             return arrayMap(value, baseToString) + '';
34000           }
34001
34002           if (isSymbol(value)) {
34003             return symbolToString ? symbolToString.call(value) : '';
34004           }
34005
34006           var result = value + '';
34007           return result == '0' && 1 / value == -INFINITY ? '-0' : result;
34008         }
34009
34010         /** Used to match a single whitespace character. */
34011         var reWhitespace = /\s/;
34012         /**
34013          * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
34014          * character of `string`.
34015          *
34016          * @private
34017          * @param {string} string The string to inspect.
34018          * @returns {number} Returns the index of the last non-whitespace character.
34019          */
34020
34021         function trimmedEndIndex(string) {
34022           var index = string.length;
34023
34024           while (index-- && reWhitespace.test(string.charAt(index))) {}
34025
34026           return index;
34027         }
34028
34029         /** Used to match leading whitespace. */
34030
34031         var reTrimStart = /^\s+/;
34032         /**
34033          * The base implementation of `_.trim`.
34034          *
34035          * @private
34036          * @param {string} string The string to trim.
34037          * @returns {string} Returns the trimmed string.
34038          */
34039
34040         function baseTrim(string) {
34041           return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') : string;
34042         }
34043
34044         /**
34045          * Checks if `value` is the
34046          * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
34047          * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
34048          *
34049          * @static
34050          * @memberOf _
34051          * @since 0.1.0
34052          * @category Lang
34053          * @param {*} value The value to check.
34054          * @returns {boolean} Returns `true` if `value` is an object, else `false`.
34055          * @example
34056          *
34057          * _.isObject({});
34058          * // => true
34059          *
34060          * _.isObject([1, 2, 3]);
34061          * // => true
34062          *
34063          * _.isObject(_.noop);
34064          * // => true
34065          *
34066          * _.isObject(null);
34067          * // => false
34068          */
34069         function isObject$2(value) {
34070           var type = _typeof(value);
34071
34072           return value != null && (type == 'object' || type == 'function');
34073         }
34074
34075         /** Used as references for various `Number` constants. */
34076
34077         var NAN = 0 / 0;
34078         /** Used to detect bad signed hexadecimal string values. */
34079
34080         var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
34081         /** Used to detect binary string values. */
34082
34083         var reIsBinary = /^0b[01]+$/i;
34084         /** Used to detect octal string values. */
34085
34086         var reIsOctal = /^0o[0-7]+$/i;
34087         /** Built-in method references without a dependency on `root`. */
34088
34089         var freeParseInt = parseInt;
34090         /**
34091          * Converts `value` to a number.
34092          *
34093          * @static
34094          * @memberOf _
34095          * @since 4.0.0
34096          * @category Lang
34097          * @param {*} value The value to process.
34098          * @returns {number} Returns the number.
34099          * @example
34100          *
34101          * _.toNumber(3.2);
34102          * // => 3.2
34103          *
34104          * _.toNumber(Number.MIN_VALUE);
34105          * // => 5e-324
34106          *
34107          * _.toNumber(Infinity);
34108          * // => Infinity
34109          *
34110          * _.toNumber('3.2');
34111          * // => 3.2
34112          */
34113
34114         function toNumber(value) {
34115           if (typeof value == 'number') {
34116             return value;
34117           }
34118
34119           if (isSymbol(value)) {
34120             return NAN;
34121           }
34122
34123           if (isObject$2(value)) {
34124             var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
34125             value = isObject$2(other) ? other + '' : other;
34126           }
34127
34128           if (typeof value != 'string') {
34129             return value === 0 ? value : +value;
34130           }
34131
34132           value = baseTrim(value);
34133           var isBinary = reIsBinary.test(value);
34134           return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
34135         }
34136
34137         /**
34138          * Converts `value` to a string. An empty string is returned for `null`
34139          * and `undefined` values. The sign of `-0` is preserved.
34140          *
34141          * @static
34142          * @memberOf _
34143          * @since 4.0.0
34144          * @category Lang
34145          * @param {*} value The value to convert.
34146          * @returns {string} Returns the converted string.
34147          * @example
34148          *
34149          * _.toString(null);
34150          * // => ''
34151          *
34152          * _.toString(-0);
34153          * // => '-0'
34154          *
34155          * _.toString([1, 2, 3]);
34156          * // => '1,2,3'
34157          */
34158
34159         function toString$3(value) {
34160           return value == null ? '' : baseToString(value);
34161         }
34162
34163         /**
34164          * The base implementation of `_.propertyOf` without support for deep paths.
34165          *
34166          * @private
34167          * @param {Object} object The object to query.
34168          * @returns {Function} Returns the new accessor function.
34169          */
34170         function basePropertyOf(object) {
34171           return function (key) {
34172             return object == null ? undefined : object[key];
34173           };
34174         }
34175
34176         /**
34177          * Gets the timestamp of the number of milliseconds that have elapsed since
34178          * the Unix epoch (1 January 1970 00:00:00 UTC).
34179          *
34180          * @static
34181          * @memberOf _
34182          * @since 2.4.0
34183          * @category Date
34184          * @returns {number} Returns the timestamp.
34185          * @example
34186          *
34187          * _.defer(function(stamp) {
34188          *   console.log(_.now() - stamp);
34189          * }, _.now());
34190          * // => Logs the number of milliseconds it took for the deferred invocation.
34191          */
34192
34193         var now = function now() {
34194           return root.Date.now();
34195         };
34196
34197         /** Error message constants. */
34198
34199         var FUNC_ERROR_TEXT$1 = 'Expected a function';
34200         /* Built-in method references for those with the same name as other `lodash` methods. */
34201
34202         var nativeMax = Math.max,
34203             nativeMin = Math.min;
34204         /**
34205          * Creates a debounced function that delays invoking `func` until after `wait`
34206          * milliseconds have elapsed since the last time the debounced function was
34207          * invoked. The debounced function comes with a `cancel` method to cancel
34208          * delayed `func` invocations and a `flush` method to immediately invoke them.
34209          * Provide `options` to indicate whether `func` should be invoked on the
34210          * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
34211          * with the last arguments provided to the debounced function. Subsequent
34212          * calls to the debounced function return the result of the last `func`
34213          * invocation.
34214          *
34215          * **Note:** If `leading` and `trailing` options are `true`, `func` is
34216          * invoked on the trailing edge of the timeout only if the debounced function
34217          * is invoked more than once during the `wait` timeout.
34218          *
34219          * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
34220          * until to the next tick, similar to `setTimeout` with a timeout of `0`.
34221          *
34222          * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
34223          * for details over the differences between `_.debounce` and `_.throttle`.
34224          *
34225          * @static
34226          * @memberOf _
34227          * @since 0.1.0
34228          * @category Function
34229          * @param {Function} func The function to debounce.
34230          * @param {number} [wait=0] The number of milliseconds to delay.
34231          * @param {Object} [options={}] The options object.
34232          * @param {boolean} [options.leading=false]
34233          *  Specify invoking on the leading edge of the timeout.
34234          * @param {number} [options.maxWait]
34235          *  The maximum time `func` is allowed to be delayed before it's invoked.
34236          * @param {boolean} [options.trailing=true]
34237          *  Specify invoking on the trailing edge of the timeout.
34238          * @returns {Function} Returns the new debounced function.
34239          * @example
34240          *
34241          * // Avoid costly calculations while the window size is in flux.
34242          * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
34243          *
34244          * // Invoke `sendMail` when clicked, debouncing subsequent calls.
34245          * jQuery(element).on('click', _.debounce(sendMail, 300, {
34246          *   'leading': true,
34247          *   'trailing': false
34248          * }));
34249          *
34250          * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
34251          * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
34252          * var source = new EventSource('/stream');
34253          * jQuery(source).on('message', debounced);
34254          *
34255          * // Cancel the trailing debounced invocation.
34256          * jQuery(window).on('popstate', debounced.cancel);
34257          */
34258
34259         function debounce(func, wait, options) {
34260           var lastArgs,
34261               lastThis,
34262               maxWait,
34263               result,
34264               timerId,
34265               lastCallTime,
34266               lastInvokeTime = 0,
34267               leading = false,
34268               maxing = false,
34269               trailing = true;
34270
34271           if (typeof func != 'function') {
34272             throw new TypeError(FUNC_ERROR_TEXT$1);
34273           }
34274
34275           wait = toNumber(wait) || 0;
34276
34277           if (isObject$2(options)) {
34278             leading = !!options.leading;
34279             maxing = 'maxWait' in options;
34280             maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
34281             trailing = 'trailing' in options ? !!options.trailing : trailing;
34282           }
34283
34284           function invokeFunc(time) {
34285             var args = lastArgs,
34286                 thisArg = lastThis;
34287             lastArgs = lastThis = undefined;
34288             lastInvokeTime = time;
34289             result = func.apply(thisArg, args);
34290             return result;
34291           }
34292
34293           function leadingEdge(time) {
34294             // Reset any `maxWait` timer.
34295             lastInvokeTime = time; // Start the timer for the trailing edge.
34296
34297             timerId = setTimeout(timerExpired, wait); // Invoke the leading edge.
34298
34299             return leading ? invokeFunc(time) : result;
34300           }
34301
34302           function remainingWait(time) {
34303             var timeSinceLastCall = time - lastCallTime,
34304                 timeSinceLastInvoke = time - lastInvokeTime,
34305                 timeWaiting = wait - timeSinceLastCall;
34306             return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
34307           }
34308
34309           function shouldInvoke(time) {
34310             var timeSinceLastCall = time - lastCallTime,
34311                 timeSinceLastInvoke = time - lastInvokeTime; // Either this is the first call, activity has stopped and we're at the
34312             // trailing edge, the system time has gone backwards and we're treating
34313             // it as the trailing edge, or we've hit the `maxWait` limit.
34314
34315             return lastCallTime === undefined || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
34316           }
34317
34318           function timerExpired() {
34319             var time = now();
34320
34321             if (shouldInvoke(time)) {
34322               return trailingEdge(time);
34323             } // Restart the timer.
34324
34325
34326             timerId = setTimeout(timerExpired, remainingWait(time));
34327           }
34328
34329           function trailingEdge(time) {
34330             timerId = undefined; // Only invoke if we have `lastArgs` which means `func` has been
34331             // debounced at least once.
34332
34333             if (trailing && lastArgs) {
34334               return invokeFunc(time);
34335             }
34336
34337             lastArgs = lastThis = undefined;
34338             return result;
34339           }
34340
34341           function cancel() {
34342             if (timerId !== undefined) {
34343               clearTimeout(timerId);
34344             }
34345
34346             lastInvokeTime = 0;
34347             lastArgs = lastCallTime = lastThis = timerId = undefined;
34348           }
34349
34350           function flush() {
34351             return timerId === undefined ? result : trailingEdge(now());
34352           }
34353
34354           function debounced() {
34355             var time = now(),
34356                 isInvoking = shouldInvoke(time);
34357             lastArgs = arguments;
34358             lastThis = this;
34359             lastCallTime = time;
34360
34361             if (isInvoking) {
34362               if (timerId === undefined) {
34363                 return leadingEdge(lastCallTime);
34364               }
34365
34366               if (maxing) {
34367                 // Handle invocations in a tight loop.
34368                 clearTimeout(timerId);
34369                 timerId = setTimeout(timerExpired, wait);
34370                 return invokeFunc(lastCallTime);
34371               }
34372             }
34373
34374             if (timerId === undefined) {
34375               timerId = setTimeout(timerExpired, wait);
34376             }
34377
34378             return result;
34379           }
34380
34381           debounced.cancel = cancel;
34382           debounced.flush = flush;
34383           return debounced;
34384         }
34385
34386         /** Used to map characters to HTML entities. */
34387
34388         var htmlEscapes = {
34389           '&': '&amp;',
34390           '<': '&lt;',
34391           '>': '&gt;',
34392           '"': '&quot;',
34393           "'": '&#39;'
34394         };
34395         /**
34396          * Used by `_.escape` to convert characters to HTML entities.
34397          *
34398          * @private
34399          * @param {string} chr The matched character to escape.
34400          * @returns {string} Returns the escaped character.
34401          */
34402
34403         var escapeHtmlChar = basePropertyOf(htmlEscapes);
34404
34405         /** Used to match HTML entities and HTML characters. */
34406
34407         var reUnescapedHtml = /[&<>"']/g,
34408             reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
34409         /**
34410          * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
34411          * corresponding HTML entities.
34412          *
34413          * **Note:** No other characters are escaped. To escape additional
34414          * characters use a third-party library like [_he_](https://mths.be/he).
34415          *
34416          * Though the ">" character is escaped for symmetry, characters like
34417          * ">" and "/" don't need escaping in HTML and have no special meaning
34418          * unless they're part of a tag or unquoted attribute value. See
34419          * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
34420          * (under "semi-related fun fact") for more details.
34421          *
34422          * When working with HTML you should always
34423          * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
34424          * XSS vectors.
34425          *
34426          * @static
34427          * @since 0.1.0
34428          * @memberOf _
34429          * @category String
34430          * @param {string} [string=''] The string to escape.
34431          * @returns {string} Returns the escaped string.
34432          * @example
34433          *
34434          * _.escape('fred, barney, & pebbles');
34435          * // => 'fred, barney, &amp; pebbles'
34436          */
34437
34438         function escape$4(string) {
34439           string = toString$3(string);
34440           return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string;
34441         }
34442
34443         /** Error message constants. */
34444
34445         var FUNC_ERROR_TEXT = 'Expected a function';
34446         /**
34447          * Creates a throttled function that only invokes `func` at most once per
34448          * every `wait` milliseconds. The throttled function comes with a `cancel`
34449          * method to cancel delayed `func` invocations and a `flush` method to
34450          * immediately invoke them. Provide `options` to indicate whether `func`
34451          * should be invoked on the leading and/or trailing edge of the `wait`
34452          * timeout. The `func` is invoked with the last arguments provided to the
34453          * throttled function. Subsequent calls to the throttled function return the
34454          * result of the last `func` invocation.
34455          *
34456          * **Note:** If `leading` and `trailing` options are `true`, `func` is
34457          * invoked on the trailing edge of the timeout only if the throttled function
34458          * is invoked more than once during the `wait` timeout.
34459          *
34460          * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
34461          * until to the next tick, similar to `setTimeout` with a timeout of `0`.
34462          *
34463          * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
34464          * for details over the differences between `_.throttle` and `_.debounce`.
34465          *
34466          * @static
34467          * @memberOf _
34468          * @since 0.1.0
34469          * @category Function
34470          * @param {Function} func The function to throttle.
34471          * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
34472          * @param {Object} [options={}] The options object.
34473          * @param {boolean} [options.leading=true]
34474          *  Specify invoking on the leading edge of the timeout.
34475          * @param {boolean} [options.trailing=true]
34476          *  Specify invoking on the trailing edge of the timeout.
34477          * @returns {Function} Returns the new throttled function.
34478          * @example
34479          *
34480          * // Avoid excessively updating the position while scrolling.
34481          * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
34482          *
34483          * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
34484          * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
34485          * jQuery(element).on('click', throttled);
34486          *
34487          * // Cancel the trailing throttled invocation.
34488          * jQuery(window).on('popstate', throttled.cancel);
34489          */
34490
34491         function throttle(func, wait, options) {
34492           var leading = true,
34493               trailing = true;
34494
34495           if (typeof func != 'function') {
34496             throw new TypeError(FUNC_ERROR_TEXT);
34497           }
34498
34499           if (isObject$2(options)) {
34500             leading = 'leading' in options ? !!options.leading : leading;
34501             trailing = 'trailing' in options ? !!options.trailing : trailing;
34502           }
34503
34504           return debounce(func, wait, {
34505             'leading': leading,
34506             'maxWait': wait,
34507             'trailing': trailing
34508           });
34509         }
34510
34511         var $$f = _export;
34512         var lastIndexOf = arrayLastIndexOf;
34513
34514         // `Array.prototype.lastIndexOf` method
34515         // https://tc39.es/ecma262/#sec-array.prototype.lastindexof
34516         // eslint-disable-next-line es/no-array-prototype-lastindexof -- required for testing
34517         $$f({ target: 'Array', proto: true, forced: lastIndexOf !== [].lastIndexOf }, {
34518           lastIndexOf: lastIndexOf
34519         });
34520
34521         /** Used to map HTML entities to characters. */
34522
34523         var htmlUnescapes = {
34524           '&amp;': '&',
34525           '&lt;': '<',
34526           '&gt;': '>',
34527           '&quot;': '"',
34528           '&#39;': "'"
34529         };
34530         /**
34531          * Used by `_.unescape` to convert HTML entities to characters.
34532          *
34533          * @private
34534          * @param {string} chr The matched character to unescape.
34535          * @returns {string} Returns the unescaped character.
34536          */
34537
34538         var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
34539
34540         /** Used to match HTML entities and HTML characters. */
34541
34542         var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
34543             reHasEscapedHtml = RegExp(reEscapedHtml.source);
34544         /**
34545          * The inverse of `_.escape`; this method converts the HTML entities
34546          * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to
34547          * their corresponding characters.
34548          *
34549          * **Note:** No other HTML entities are unescaped. To unescape additional
34550          * HTML entities use a third-party library like [_he_](https://mths.be/he).
34551          *
34552          * @static
34553          * @memberOf _
34554          * @since 0.6.0
34555          * @category String
34556          * @param {string} [string=''] The string to unescape.
34557          * @returns {string} Returns the unescaped string.
34558          * @example
34559          *
34560          * _.unescape('fred, barney, &amp; pebbles');
34561          * // => 'fred, barney, & pebbles'
34562          */
34563
34564         function unescape$3(string) {
34565           string = toString$3(string);
34566           return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string;
34567         }
34568
34569         var global$4 = global$1o;
34570         var isArray = isArray$8;
34571         var lengthOfArrayLike$1 = lengthOfArrayLike$i;
34572         var bind$3 = functionBindContext;
34573
34574         var TypeError$2 = global$4.TypeError;
34575
34576         // `FlattenIntoArray` abstract operation
34577         // https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray
34578         var flattenIntoArray$1 = function (target, original, source, sourceLen, start, depth, mapper, thisArg) {
34579           var targetIndex = start;
34580           var sourceIndex = 0;
34581           var mapFn = mapper ? bind$3(mapper, thisArg) : false;
34582           var element, elementLen;
34583
34584           while (sourceIndex < sourceLen) {
34585             if (sourceIndex in source) {
34586               element = mapFn ? mapFn(source[sourceIndex], sourceIndex, original) : source[sourceIndex];
34587
34588               if (depth > 0 && isArray(element)) {
34589                 elementLen = lengthOfArrayLike$1(element);
34590                 targetIndex = flattenIntoArray$1(target, original, element, elementLen, targetIndex, depth - 1) - 1;
34591               } else {
34592                 if (targetIndex >= 0x1FFFFFFFFFFFFF) throw TypeError$2('Exceed the acceptable array length');
34593                 target[targetIndex] = element;
34594               }
34595
34596               targetIndex++;
34597             }
34598             sourceIndex++;
34599           }
34600           return targetIndex;
34601         };
34602
34603         var flattenIntoArray_1 = flattenIntoArray$1;
34604
34605         var $$e = _export;
34606         var flattenIntoArray = flattenIntoArray_1;
34607         var aCallable = aCallable$a;
34608         var toObject = toObject$i;
34609         var lengthOfArrayLike = lengthOfArrayLike$i;
34610         var arraySpeciesCreate = arraySpeciesCreate$4;
34611
34612         // `Array.prototype.flatMap` method
34613         // https://tc39.es/ecma262/#sec-array.prototype.flatmap
34614         $$e({ target: 'Array', proto: true }, {
34615           flatMap: function flatMap(callbackfn /* , thisArg */) {
34616             var O = toObject(this);
34617             var sourceLen = lengthOfArrayLike(O);
34618             var A;
34619             aCallable(callbackfn);
34620             A = arraySpeciesCreate(O, 0);
34621             A.length = flattenIntoArray(A, O, O, sourceLen, 0, 1, callbackfn, arguments.length > 1 ? arguments[1] : undefined);
34622             return A;
34623           }
34624         });
34625
34626         // this method was added to unscopables after implementation
34627         // in popular engines, so it's moved to a separate module
34628         var addToUnscopables = addToUnscopables$6;
34629
34630         // https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
34631         addToUnscopables('flatMap');
34632
34633         var $$d = _export;
34634         var uncurryThis$6 = functionUncurryThis;
34635         var getOwnPropertyDescriptor$1 = objectGetOwnPropertyDescriptor.f;
34636         var toLength$2 = toLength$c;
34637         var toString$2 = toString$k;
34638         var notARegExp$1 = notARegexp;
34639         var requireObjectCoercible$2 = requireObjectCoercible$e;
34640         var correctIsRegExpLogic$1 = correctIsRegexpLogic;
34641
34642         // eslint-disable-next-line es/no-string-prototype-endswith -- safe
34643         var un$EndsWith = uncurryThis$6(''.endsWith);
34644         var slice$2 = uncurryThis$6(''.slice);
34645         var min$1 = Math.min;
34646
34647         var CORRECT_IS_REGEXP_LOGIC$1 = correctIsRegExpLogic$1('endsWith');
34648         // https://github.com/zloirock/core-js/pull/702
34649         var MDN_POLYFILL_BUG$1 = !CORRECT_IS_REGEXP_LOGIC$1 && !!function () {
34650           var descriptor = getOwnPropertyDescriptor$1(String.prototype, 'endsWith');
34651           return descriptor && !descriptor.writable;
34652         }();
34653
34654         // `String.prototype.endsWith` method
34655         // https://tc39.es/ecma262/#sec-string.prototype.endswith
34656         $$d({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG$1 && !CORRECT_IS_REGEXP_LOGIC$1 }, {
34657           endsWith: function endsWith(searchString /* , endPosition = @length */) {
34658             var that = toString$2(requireObjectCoercible$2(this));
34659             notARegExp$1(searchString);
34660             var endPosition = arguments.length > 1 ? arguments[1] : undefined;
34661             var len = that.length;
34662             var end = endPosition === undefined ? len : min$1(toLength$2(endPosition), len);
34663             var search = toString$2(searchString);
34664             return un$EndsWith
34665               ? un$EndsWith(that, search, end)
34666               : slice$2(that, end - search.length, end) === search;
34667           }
34668         });
34669
34670         // https://github.com/tc39/proposal-string-pad-start-end
34671         var uncurryThis$5 = functionUncurryThis;
34672         var toLength$1 = toLength$c;
34673         var toString$1 = toString$k;
34674         var $repeat = stringRepeat;
34675         var requireObjectCoercible$1 = requireObjectCoercible$e;
34676
34677         var repeat$1 = uncurryThis$5($repeat);
34678         var stringSlice$2 = uncurryThis$5(''.slice);
34679         var ceil = Math.ceil;
34680
34681         // `String.prototype.{ padStart, padEnd }` methods implementation
34682         var createMethod = function (IS_END) {
34683           return function ($this, maxLength, fillString) {
34684             var S = toString$1(requireObjectCoercible$1($this));
34685             var intMaxLength = toLength$1(maxLength);
34686             var stringLength = S.length;
34687             var fillStr = fillString === undefined ? ' ' : toString$1(fillString);
34688             var fillLen, stringFiller;
34689             if (intMaxLength <= stringLength || fillStr == '') return S;
34690             fillLen = intMaxLength - stringLength;
34691             stringFiller = repeat$1(fillStr, ceil(fillLen / fillStr.length));
34692             if (stringFiller.length > fillLen) stringFiller = stringSlice$2(stringFiller, 0, fillLen);
34693             return IS_END ? S + stringFiller : stringFiller + S;
34694           };
34695         };
34696
34697         var stringPad = {
34698           // `String.prototype.padStart` method
34699           // https://tc39.es/ecma262/#sec-string.prototype.padstart
34700           start: createMethod(false),
34701           // `String.prototype.padEnd` method
34702           // https://tc39.es/ecma262/#sec-string.prototype.padend
34703           end: createMethod(true)
34704         };
34705
34706         // https://github.com/zloirock/core-js/issues/280
34707         var userAgent = engineUserAgent;
34708
34709         var stringPadWebkitBug = /Version\/10(?:\.\d+){1,2}(?: [\w./]+)?(?: Mobile\/\w+)? Safari\//.test(userAgent);
34710
34711         var $$c = _export;
34712         var $padEnd = stringPad.end;
34713         var WEBKIT_BUG$1 = stringPadWebkitBug;
34714
34715         // `String.prototype.padEnd` method
34716         // https://tc39.es/ecma262/#sec-string.prototype.padend
34717         $$c({ target: 'String', proto: true, forced: WEBKIT_BUG$1 }, {
34718           padEnd: function padEnd(maxLength /* , fillString = ' ' */) {
34719             return $padEnd(this, maxLength, arguments.length > 1 ? arguments[1] : undefined);
34720           }
34721         });
34722
34723         var $$b = _export;
34724         var $padStart = stringPad.start;
34725         var WEBKIT_BUG = stringPadWebkitBug;
34726
34727         // `String.prototype.padStart` method
34728         // https://tc39.es/ecma262/#sec-string.prototype.padstart
34729         $$b({ target: 'String', proto: true, forced: WEBKIT_BUG }, {
34730           padStart: function padStart(maxLength /* , fillString = ' ' */) {
34731             return $padStart(this, maxLength, arguments.length > 1 ? arguments[1] : undefined);
34732           }
34733         });
34734
34735         var $$a = _export;
34736         var $reduceRight = arrayReduce.right;
34737         var arrayMethodIsStrict = arrayMethodIsStrict$9;
34738         var CHROME_VERSION = engineV8Version;
34739         var IS_NODE = engineIsNode;
34740
34741         var STRICT_METHOD = arrayMethodIsStrict('reduceRight');
34742         // Chrome 80-82 has a critical bug
34743         // https://bugs.chromium.org/p/chromium/issues/detail?id=1049982
34744         var CHROME_BUG = !IS_NODE && CHROME_VERSION > 79 && CHROME_VERSION < 83;
34745
34746         // `Array.prototype.reduceRight` method
34747         // https://tc39.es/ecma262/#sec-array.prototype.reduceright
34748         $$a({ target: 'Array', proto: true, forced: !STRICT_METHOD || CHROME_BUG }, {
34749           reduceRight: function reduceRight(callbackfn /* , initialValue */) {
34750             return $reduceRight(this, callbackfn, arguments.length, arguments.length > 1 ? arguments[1] : undefined);
34751           }
34752         });
34753
34754         var $$9 = _export;
34755         var repeat = stringRepeat;
34756
34757         // `String.prototype.repeat` method
34758         // https://tc39.es/ecma262/#sec-string.prototype.repeat
34759         $$9({ target: 'String', proto: true }, {
34760           repeat: repeat
34761         });
34762
34763         var $$8 = _export;
34764         var uncurryThis$4 = functionUncurryThis;
34765         var getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f;
34766         var toLength = toLength$c;
34767         var toString = toString$k;
34768         var notARegExp = notARegexp;
34769         var requireObjectCoercible = requireObjectCoercible$e;
34770         var correctIsRegExpLogic = correctIsRegexpLogic;
34771
34772         // eslint-disable-next-line es/no-string-prototype-startswith -- safe
34773         var un$StartsWith = uncurryThis$4(''.startsWith);
34774         var stringSlice$1 = uncurryThis$4(''.slice);
34775         var min = Math.min;
34776
34777         var CORRECT_IS_REGEXP_LOGIC = correctIsRegExpLogic('startsWith');
34778         // https://github.com/zloirock/core-js/pull/702
34779         var MDN_POLYFILL_BUG = !CORRECT_IS_REGEXP_LOGIC && !!function () {
34780           var descriptor = getOwnPropertyDescriptor(String.prototype, 'startsWith');
34781           return descriptor && !descriptor.writable;
34782         }();
34783
34784         // `String.prototype.startsWith` method
34785         // https://tc39.es/ecma262/#sec-string.prototype.startswith
34786         $$8({ target: 'String', proto: true, forced: !MDN_POLYFILL_BUG && !CORRECT_IS_REGEXP_LOGIC }, {
34787           startsWith: function startsWith(searchString /* , position = 0 */) {
34788             var that = toString(requireObjectCoercible(this));
34789             notARegExp(searchString);
34790             var index = toLength(min(arguments.length > 1 ? arguments[1] : undefined, that.length));
34791             var search = toString(searchString);
34792             return un$StartsWith
34793               ? un$StartsWith(that, search, index)
34794               : stringSlice$1(that, index, index + search.length) === search;
34795           }
34796         });
34797
34798         var $$7 = _export;
34799         var $trimEnd = stringTrim.end;
34800         var forcedStringTrimMethod$1 = stringTrimForced;
34801
34802         var FORCED$4 = forcedStringTrimMethod$1('trimEnd');
34803
34804         var trimEnd = FORCED$4 ? function trimEnd() {
34805           return $trimEnd(this);
34806         // eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe
34807         } : ''.trimEnd;
34808
34809         // `String.prototype.{ trimEnd, trimRight }` methods
34810         // https://tc39.es/ecma262/#sec-string.prototype.trimend
34811         // https://tc39.es/ecma262/#String.prototype.trimright
34812         $$7({ target: 'String', proto: true, name: 'trimEnd', forced: FORCED$4 }, {
34813           trimEnd: trimEnd,
34814           trimRight: trimEnd
34815         });
34816
34817         var $$6 = _export;
34818         var $trimStart = stringTrim.start;
34819         var forcedStringTrimMethod = stringTrimForced;
34820
34821         var FORCED$3 = forcedStringTrimMethod('trimStart');
34822
34823         var trimStart = FORCED$3 ? function trimStart() {
34824           return $trimStart(this);
34825         // eslint-disable-next-line es/no-string-prototype-trimstart-trimend -- safe
34826         } : ''.trimStart;
34827
34828         // `String.prototype.{ trimStart, trimLeft }` methods
34829         // https://tc39.es/ecma262/#sec-string.prototype.trimstart
34830         // https://tc39.es/ecma262/#String.prototype.trimleft
34831         $$6({ target: 'String', proto: true, name: 'trimStart', forced: FORCED$3 }, {
34832           trimStart: trimStart,
34833           trimLeft: trimStart
34834         });
34835
34836         var _mainLocalizer = coreLocalizer(); // singleton
34837
34838
34839         var _t = _mainLocalizer.t;
34840         // coreLocalizer manages language and locale parameters including translated strings
34841         //
34842
34843         function coreLocalizer() {
34844           var localizer = {};
34845           var _dataLanguages = {}; // `_dataLocales` is an object containing all _supported_ locale codes -> language info.
34846           // * `rtl` - right-to-left or left-to-right text direction
34847           // * `pct` - the percent of strings translated; 1 = 100%, full coverage
34848           //
34849           // {
34850           // en: { rtl: false, pct: {…} },
34851           // de: { rtl: false, pct: {…} },
34852           // …
34853           // }
34854
34855           var _dataLocales = {}; // `localeStrings` is an object containing all _loaded_ locale codes -> string data.
34856           // {
34857           // en: { icons: {…}, toolbar: {…}, modes: {…}, operations: {…}, … },
34858           // de: { icons: {…}, toolbar: {…}, modes: {…}, operations: {…}, … },
34859           // …
34860           // }
34861
34862           var _localeStrings = {}; // the current locale
34863
34864           var _localeCode = 'en-US'; // `_localeCodes` must contain `_localeCode` first, optionally followed by fallbacks
34865
34866           var _localeCodes = ['en-US', 'en'];
34867           var _languageCode = 'en';
34868           var _textDirection = 'ltr';
34869           var _usesMetric = false;
34870           var _languageNames = {};
34871           var _scriptNames = {}; // getters for the current locale parameters
34872
34873           localizer.localeCode = function () {
34874             return _localeCode;
34875           };
34876
34877           localizer.localeCodes = function () {
34878             return _localeCodes;
34879           };
34880
34881           localizer.languageCode = function () {
34882             return _languageCode;
34883           };
34884
34885           localizer.textDirection = function () {
34886             return _textDirection;
34887           };
34888
34889           localizer.usesMetric = function () {
34890             return _usesMetric;
34891           };
34892
34893           localizer.languageNames = function () {
34894             return _languageNames;
34895           };
34896
34897           localizer.scriptNames = function () {
34898             return _scriptNames;
34899           }; // The client app may want to manually set the locale, regardless of the
34900           // settings provided by the browser
34901
34902
34903           var _preferredLocaleCodes = [];
34904
34905           localizer.preferredLocaleCodes = function (codes) {
34906             if (!arguments.length) return _preferredLocaleCodes;
34907
34908             if (typeof codes === 'string') {
34909               // be generous and accept delimited strings as input
34910               _preferredLocaleCodes = codes.split(/,|;| /gi).filter(Boolean);
34911             } else {
34912               _preferredLocaleCodes = codes;
34913             }
34914
34915             return localizer;
34916           };
34917
34918           var _loadPromise;
34919
34920           localizer.ensureLoaded = function () {
34921             if (_loadPromise) return _loadPromise;
34922             var filesToFetch = ['languages', // load the list of languages
34923             'locales' // load the list of supported locales
34924             ];
34925             var localeDirs = {
34926               general: 'locales',
34927               tagging: 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@3/dist/translations'
34928             };
34929             var fileMap = _mainFileFetcher.fileMap();
34930
34931             for (var scopeId in localeDirs) {
34932               var key = "locales_index_".concat(scopeId);
34933
34934               if (!fileMap[key]) {
34935                 fileMap[key] = localeDirs[scopeId] + '/index.min.json';
34936               }
34937
34938               filesToFetch.push(key);
34939             }
34940
34941             return _loadPromise = Promise.all(filesToFetch.map(function (key) {
34942               return _mainFileFetcher.get(key);
34943             })).then(function (results) {
34944               _dataLanguages = results[0];
34945               _dataLocales = results[1];
34946               var indexes = results.slice(2);
34947
34948               var requestedLocales = (_preferredLocaleCodes || []).concat(utilDetect().browserLocales) // List of locales preferred by the browser in priority order.
34949               .concat(['en']); // fallback to English since it's the only guaranteed complete language
34950
34951
34952               _localeCodes = localesToUseFrom(requestedLocales);
34953               _localeCode = _localeCodes[0]; // Run iD in the highest-priority locale; the rest are fallbacks
34954
34955               var loadStringsPromises = [];
34956               indexes.forEach(function (index, i) {
34957                 // Will always return the index for `en` if nothing else
34958                 var fullCoverageIndex = _localeCodes.findIndex(function (locale) {
34959                   return index[locale] && index[locale].pct === 1;
34960                 }); // We only need to load locales up until we find one with full coverage
34961
34962
34963                 _localeCodes.slice(0, fullCoverageIndex + 1).forEach(function (code) {
34964                   var scopeId = Object.keys(localeDirs)[i];
34965                   var directory = Object.values(localeDirs)[i];
34966                   if (index[code]) loadStringsPromises.push(localizer.loadLocale(code, scopeId, directory));
34967                 });
34968               });
34969               return Promise.all(loadStringsPromises);
34970             }).then(function () {
34971               updateForCurrentLocale();
34972             })["catch"](function (err) {
34973               return console.error(err);
34974             }); // eslint-disable-line
34975           }; // Returns the locales from `requestedLocales` supported by iD that we should use
34976
34977
34978           function localesToUseFrom(requestedLocales) {
34979             var supportedLocales = _dataLocales;
34980             var toUse = [];
34981
34982             for (var i in requestedLocales) {
34983               var locale = requestedLocales[i];
34984               if (supportedLocales[locale]) toUse.push(locale);
34985
34986               if (locale.includes('-')) {
34987                 // Full locale ('es-ES'), add fallback to the base ('es')
34988                 var langPart = locale.split('-')[0];
34989                 if (supportedLocales[langPart]) toUse.push(langPart);
34990               }
34991             } // remove duplicates
34992
34993
34994             return utilArrayUniq(toUse);
34995           }
34996
34997           function updateForCurrentLocale() {
34998             if (!_localeCode) return;
34999             _languageCode = _localeCode.split('-')[0];
35000             var currentData = _dataLocales[_localeCode] || _dataLocales[_languageCode];
35001             var hash = utilStringQs(window.location.hash);
35002
35003             if (hash.rtl === 'true') {
35004               _textDirection = 'rtl';
35005             } else if (hash.rtl === 'false') {
35006               _textDirection = 'ltr';
35007             } else {
35008               _textDirection = currentData && currentData.rtl ? 'rtl' : 'ltr';
35009             }
35010
35011             var locale = _localeCode;
35012             if (locale.toLowerCase() === 'en-us') locale = 'en';
35013             _languageNames = _localeStrings.general[locale].languageNames;
35014             _scriptNames = _localeStrings.general[locale].scriptNames;
35015             _usesMetric = _localeCode.slice(-3).toLowerCase() !== '-us';
35016           }
35017           /* Locales */
35018           // Returns a Promise to load the strings for the requested locale
35019
35020
35021           localizer.loadLocale = function (locale, scopeId, directory) {
35022             // US English is the default
35023             if (locale.toLowerCase() === 'en-us') locale = 'en';
35024
35025             if (_localeStrings[scopeId] && _localeStrings[scopeId][locale]) {
35026               // already loaded
35027               return Promise.resolve(locale);
35028             }
35029
35030             var fileMap = _mainFileFetcher.fileMap();
35031             var key = "locale_".concat(scopeId, "_").concat(locale);
35032
35033             if (!fileMap[key]) {
35034               fileMap[key] = "".concat(directory, "/").concat(locale, ".min.json");
35035             }
35036
35037             return _mainFileFetcher.get(key).then(function (d) {
35038               if (!_localeStrings[scopeId]) _localeStrings[scopeId] = {};
35039               _localeStrings[scopeId][locale] = d[locale];
35040               return locale;
35041             });
35042           };
35043
35044           localizer.pluralRule = function (number) {
35045             return pluralRule(number, _localeCode);
35046           }; // Returns the plural rule for the given `number` with the given `localeCode`.
35047           // One of: `zero`, `one`, `two`, `few`, `many`, `other`
35048
35049
35050           function pluralRule(number, localeCode) {
35051             // modern browsers have this functionality built-in
35052             var rules = 'Intl' in window && Intl.PluralRules && new Intl.PluralRules(localeCode);
35053
35054             if (rules) {
35055               return rules.select(number);
35056             } // fallback to basic one/other, as in English
35057
35058
35059             if (number === 1) return 'one';
35060             return 'other';
35061           }
35062           /**
35063           * Try to find that string in `locale` or the current `_localeCode` matching
35064           * the given `stringId`. If no string can be found in the requested locale,
35065           * we'll recurse down all the `_localeCodes` until one is found.
35066           *
35067           * @param  {string}   stringId      string identifier
35068           * @param  {object?}  replacements  token replacements and default string
35069           * @param  {string?}  locale        locale to use (defaults to currentLocale)
35070           * @return {string?}  localized string
35071           */
35072
35073
35074           localizer.tInfo = function (origStringId, replacements, locale) {
35075             var stringId = origStringId.trim();
35076             var scopeId = 'general';
35077
35078             if (stringId[0] === '_') {
35079               var split = stringId.split('.');
35080               scopeId = split[0].slice(1);
35081               stringId = split.slice(1).join('.');
35082             }
35083
35084             locale = locale || _localeCode;
35085             var path = stringId.split('.').map(function (s) {
35086               return s.replace(/<TX_DOT>/g, '.');
35087             }).reverse();
35088             var stringsKey = locale; // US English is the default
35089
35090             if (stringsKey.toLowerCase() === 'en-us') stringsKey = 'en';
35091             var result = _localeStrings && _localeStrings[scopeId] && _localeStrings[scopeId][stringsKey];
35092
35093             while (result !== undefined && path.length) {
35094               result = result[path.pop()];
35095             }
35096
35097             if (result !== undefined) {
35098               if (replacements) {
35099                 if (_typeof(result) === 'object' && Object.keys(result).length) {
35100                   // If plural forms are provided, dig one level deeper based on the
35101                   // first numeric token replacement provided.
35102                   var number = Object.values(replacements).find(function (value) {
35103                     return typeof value === 'number';
35104                   });
35105
35106                   if (number !== undefined) {
35107                     var rule = pluralRule(number, locale);
35108
35109                     if (result[rule]) {
35110                       result = result[rule];
35111                     } else {
35112                       // We're pretty sure this should be a plural but no string
35113                       // could be found for the given rule. Just pick the first
35114                       // string and hope it makes sense.
35115                       result = Object.values(result)[0];
35116                     }
35117                   }
35118                 }
35119
35120                 if (typeof result === 'string') {
35121                   for (var key in replacements) {
35122                     var value = replacements[key];
35123
35124                     if (typeof value === 'number') {
35125                       if (value.toLocaleString) {
35126                         // format numbers for the locale
35127                         value = value.toLocaleString(locale, {
35128                           style: 'decimal',
35129                           useGrouping: true,
35130                           minimumFractionDigits: 0
35131                         });
35132                       } else {
35133                         value = value.toString();
35134                       }
35135                     }
35136
35137                     var token = "{".concat(key, "}");
35138                     var regex = new RegExp(token, 'g');
35139                     result = result.replace(regex, value);
35140                   }
35141                 }
35142               }
35143
35144               if (typeof result === 'string') {
35145                 // found a localized string!
35146                 return {
35147                   text: result,
35148                   locale: locale
35149                 };
35150               }
35151             } // no localized string found...
35152             // attempt to fallback to a lower-priority language
35153
35154
35155             var index = _localeCodes.indexOf(locale);
35156
35157             if (index >= 0 && index < _localeCodes.length - 1) {
35158               // eventually this will be 'en' or another locale with 100% coverage
35159               var fallback = _localeCodes[index + 1];
35160               return localizer.tInfo(origStringId, replacements, fallback);
35161             }
35162
35163             if (replacements && 'default' in replacements) {
35164               // Fallback to a default value if one is specified in `replacements`
35165               return {
35166                 text: replacements["default"],
35167                 locale: null
35168               };
35169             }
35170
35171             var missing = "Missing ".concat(locale, " translation: ").concat(origStringId);
35172             if (typeof console !== 'undefined') console.error(missing); // eslint-disable-line
35173
35174             return {
35175               text: missing,
35176               locale: 'en'
35177             };
35178           };
35179
35180           localizer.hasTextForStringId = function (stringId) {
35181             return !!localizer.tInfo(stringId, {
35182               "default": 'nothing found'
35183             }).locale;
35184           }; // Returns only the localized text, discarding the locale info
35185
35186
35187           localizer.t = function (stringId, replacements, locale) {
35188             return localizer.tInfo(stringId, replacements, locale).text;
35189           }; // Returns the localized text wrapped in an HTML element encoding the locale info
35190
35191           /**
35192            * @deprecated This method is considered deprecated. Instead, use the direct DOM manipulating
35193            *             method `t.append`.
35194            */
35195
35196
35197           localizer.t.html = function (stringId, replacements, locale) {
35198             // replacement string might be html unsafe, so we need to escape it except if it is explicitly marked as html code
35199             replacements = Object.assign({}, replacements);
35200
35201             for (var k in replacements) {
35202               if (typeof replacements[k] === 'string') {
35203                 replacements[k] = escape$4(replacements[k]);
35204               }
35205
35206               if (_typeof(replacements[k]) === 'object' && typeof replacements[k].html === 'string') {
35207                 replacements[k] = replacements[k].html;
35208               }
35209             }
35210
35211             var info = localizer.tInfo(stringId, replacements, locale); // text may be empty or undefined if `replacements.default` is
35212
35213             if (info.text) {
35214               return "<span class=\"localized-text\" lang=\"".concat(info.locale || 'und', "\">").concat(info.text, "</span>");
35215             } else {
35216               return '';
35217             }
35218           }; // Adds localized text wrapped as an HTML span element with locale info to the DOM
35219
35220
35221           localizer.t.append = function (stringId, replacements, locale) {
35222             return function (selection) {
35223               var info = localizer.tInfo(stringId, replacements, locale);
35224               return selection.append('span').attr('class', 'localized-text').attr('lang', info.locale || 'und').text((replacements && replacements.prefix || '') + info.text + (replacements && replacements.suffix || ''));
35225             };
35226           };
35227
35228           localizer.languageName = function (code, options) {
35229             if (_languageNames[code]) {
35230               // name in locale language
35231               // e.g. "German"
35232               return _languageNames[code];
35233             } // sometimes we only want the local name
35234
35235
35236             if (options && options.localOnly) return null;
35237             var langInfo = _dataLanguages[code];
35238
35239             if (langInfo) {
35240               if (langInfo.nativeName) {
35241                 // name in native language
35242                 // e.g. "Deutsch (de)"
35243                 return localizer.t('translate.language_and_code', {
35244                   language: langInfo.nativeName,
35245                   code: code
35246                 });
35247               } else if (langInfo.base && langInfo.script) {
35248                 var base = langInfo.base; // the code of the language this is based on
35249
35250                 if (_languageNames[base]) {
35251                   // base language name in locale language
35252                   var scriptCode = langInfo.script;
35253                   var script = _scriptNames[scriptCode] || scriptCode; // e.g. "Serbian (Cyrillic)"
35254
35255                   return localizer.t('translate.language_and_code', {
35256                     language: _languageNames[base],
35257                     code: script
35258                   });
35259                 } else if (_dataLanguages[base] && _dataLanguages[base].nativeName) {
35260                   // e.g. "српски (sr-Cyrl)"
35261                   return localizer.t('translate.language_and_code', {
35262                     language: _dataLanguages[base].nativeName,
35263                     code: code
35264                   });
35265                 }
35266               }
35267             }
35268
35269             return code; // if not found, use the code
35270           };
35271
35272           return localizer;
35273         }
35274
35275         // `presetCollection` is a wrapper around an `Array` of presets `collection`,
35276         // and decorated with some extra methods for searching and matching geometry
35277         //
35278
35279         function presetCollection(collection) {
35280           var MAXRESULTS = 50;
35281           var _this = {};
35282           var _memo = {};
35283           _this.collection = collection;
35284
35285           _this.item = function (id) {
35286             if (_memo[id]) return _memo[id];
35287
35288             var found = _this.collection.find(function (d) {
35289               return d.id === id;
35290             });
35291
35292             if (found) _memo[id] = found;
35293             return found;
35294           };
35295
35296           _this.index = function (id) {
35297             return _this.collection.findIndex(function (d) {
35298               return d.id === id;
35299             });
35300           };
35301
35302           _this.matchGeometry = function (geometry) {
35303             return presetCollection(_this.collection.filter(function (d) {
35304               return d.matchGeometry(geometry);
35305             }));
35306           };
35307
35308           _this.matchAllGeometry = function (geometries) {
35309             return presetCollection(_this.collection.filter(function (d) {
35310               return d && d.matchAllGeometry(geometries);
35311             }));
35312           };
35313
35314           _this.matchAnyGeometry = function (geometries) {
35315             return presetCollection(_this.collection.filter(function (d) {
35316               return geometries.some(function (geom) {
35317                 return d.matchGeometry(geom);
35318               });
35319             }));
35320           };
35321
35322           _this.fallback = function (geometry) {
35323             var id = geometry;
35324             if (id === 'vertex') id = 'point';
35325             return _this.item(id);
35326           };
35327
35328           _this.search = function (value, geometry, loc) {
35329             if (!value) return _this; // don't remove diacritical characters since we're assuming the user is being intentional
35330
35331             value = value.toLowerCase().trim(); // match at name beginning or just after a space (e.g. "office" -> match "Law Office")
35332
35333             function leading(a) {
35334               var index = a.indexOf(value);
35335               return index === 0 || a[index - 1] === ' ';
35336             } // match at name beginning only
35337
35338
35339             function leadingStrict(a) {
35340               var index = a.indexOf(value);
35341               return index === 0;
35342             }
35343
35344             function sortPresets(nameProp) {
35345               return function sortNames(a, b) {
35346                 var aCompare = a[nameProp]();
35347                 var bCompare = b[nameProp](); // priority if search string matches preset name exactly - #4325
35348
35349                 if (value === aCompare) return -1;
35350                 if (value === bCompare) return 1; // priority for higher matchScore
35351
35352                 var i = b.originalScore - a.originalScore;
35353                 if (i !== 0) return i; // priority if search string appears earlier in preset name
35354
35355                 i = aCompare.indexOf(value) - bCompare.indexOf(value);
35356                 if (i !== 0) return i; // priority for shorter preset names
35357
35358                 return aCompare.length - bCompare.length;
35359               };
35360             }
35361
35362             var pool = _this.collection;
35363
35364             if (Array.isArray(loc)) {
35365               var validLocations = _mainLocations.locationsAt(loc);
35366               pool = pool.filter(function (a) {
35367                 return !a.locationSetID || validLocations[a.locationSetID];
35368               });
35369             }
35370
35371             var searchable = pool.filter(function (a) {
35372               return a.searchable !== false && a.suggestion !== true;
35373             });
35374             var suggestions = pool.filter(function (a) {
35375               return a.suggestion === true;
35376             }); // matches value to preset.name
35377
35378             var leadingNames = searchable.filter(function (a) {
35379               return leading(a.searchName());
35380             }).sort(sortPresets('searchName')); // matches value to preset suggestion name
35381
35382             var leadingSuggestions = suggestions.filter(function (a) {
35383               return leadingStrict(a.searchName());
35384             }).sort(sortPresets('searchName'));
35385             var leadingNamesStripped = searchable.filter(function (a) {
35386               return leading(a.searchNameStripped());
35387             }).sort(sortPresets('searchNameStripped'));
35388             var leadingSuggestionsStripped = suggestions.filter(function (a) {
35389               return leadingStrict(a.searchNameStripped());
35390             }).sort(sortPresets('searchNameStripped')); // matches value to preset.terms values
35391
35392             var leadingTerms = searchable.filter(function (a) {
35393               return (a.terms() || []).some(leading);
35394             });
35395             var leadingSuggestionTerms = suggestions.filter(function (a) {
35396               return (a.terms() || []).some(leading);
35397             }); // matches value to preset.tags values
35398
35399             var leadingTagValues = searchable.filter(function (a) {
35400               return Object.values(a.tags || {}).filter(function (val) {
35401                 return val !== '*';
35402               }).some(leading);
35403             }); // finds close matches to value in preset.name
35404
35405             var similarName = searchable.map(function (a) {
35406               return {
35407                 preset: a,
35408                 dist: utilEditDistance(value, a.searchName())
35409               };
35410             }).filter(function (a) {
35411               return a.dist + Math.min(value.length - a.preset.searchName().length, 0) < 3;
35412             }).sort(function (a, b) {
35413               return a.dist - b.dist;
35414             }).map(function (a) {
35415               return a.preset;
35416             }); // finds close matches to value to preset suggestion name
35417
35418             var similarSuggestions = suggestions.map(function (a) {
35419               return {
35420                 preset: a,
35421                 dist: utilEditDistance(value, a.searchName())
35422               };
35423             }).filter(function (a) {
35424               return a.dist + Math.min(value.length - a.preset.searchName().length, 0) < 1;
35425             }).sort(function (a, b) {
35426               return a.dist - b.dist;
35427             }).map(function (a) {
35428               return a.preset;
35429             }); // finds close matches to value in preset.terms
35430
35431             var similarTerms = searchable.filter(function (a) {
35432               return (a.terms() || []).some(function (b) {
35433                 return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
35434               });
35435             });
35436             var results = leadingNames.concat(leadingSuggestions, leadingNamesStripped, leadingSuggestionsStripped, leadingTerms, leadingSuggestionTerms, leadingTagValues, similarName, similarSuggestions, similarTerms).slice(0, MAXRESULTS - 1);
35437
35438             if (geometry) {
35439               if (typeof geometry === 'string') {
35440                 results.push(_this.fallback(geometry));
35441               } else {
35442                 geometry.forEach(function (geom) {
35443                   return results.push(_this.fallback(geom));
35444                 });
35445               }
35446             }
35447
35448             return presetCollection(utilArrayUniq(results));
35449           };
35450
35451           return _this;
35452         }
35453
35454         // `presetCategory` builds a `presetCollection` of member presets,
35455         // decorated with some extra methods for searching and matching geometry
35456         //
35457
35458         function presetCategory(categoryID, category, allPresets) {
35459           var _this = Object.assign({}, category); // shallow copy
35460
35461
35462           var _searchName; // cache
35463
35464
35465           var _searchNameStripped; // cache
35466
35467
35468           _this.id = categoryID;
35469           _this.members = presetCollection((category.members || []).map(function (presetID) {
35470             return allPresets[presetID];
35471           }).filter(Boolean));
35472           _this.geometry = _this.members.collection.reduce(function (acc, preset) {
35473             for (var i in preset.geometry) {
35474               var geometry = preset.geometry[i];
35475
35476               if (acc.indexOf(geometry) === -1) {
35477                 acc.push(geometry);
35478               }
35479             }
35480
35481             return acc;
35482           }, []);
35483
35484           _this.matchGeometry = function (geom) {
35485             return _this.geometry.indexOf(geom) >= 0;
35486           };
35487
35488           _this.matchAllGeometry = function (geometries) {
35489             return _this.members.collection.some(function (preset) {
35490               return preset.matchAllGeometry(geometries);
35491             });
35492           };
35493
35494           _this.matchScore = function () {
35495             return -1;
35496           };
35497
35498           _this.name = function () {
35499             return _t("_tagging.presets.categories.".concat(categoryID, ".name"), {
35500               'default': categoryID
35501             });
35502           };
35503
35504           _this.nameLabel = function () {
35505             return _t.html("_tagging.presets.categories.".concat(categoryID, ".name"), {
35506               'default': categoryID
35507             });
35508           };
35509
35510           _this.terms = function () {
35511             return [];
35512           };
35513
35514           _this.searchName = function () {
35515             if (!_searchName) {
35516               _searchName = (_this.suggestion ? _this.originalName : _this.name()).toLowerCase();
35517             }
35518
35519             return _searchName;
35520           };
35521
35522           _this.searchNameStripped = function () {
35523             if (!_searchNameStripped) {
35524               _searchNameStripped = _this.searchName(); // split combined diacritical characters into their parts
35525
35526               if (_searchNameStripped.normalize) _searchNameStripped = _searchNameStripped.normalize('NFD'); // remove diacritics
35527
35528               _searchNameStripped = _searchNameStripped.replace(/[\u0300-\u036f]/g, '');
35529             }
35530
35531             return _searchNameStripped;
35532           };
35533
35534           return _this;
35535         }
35536
35537         // `presetField` decorates a given `field` Object
35538         // with some extra methods for searching and matching geometry
35539         //
35540
35541         function presetField(fieldID, field) {
35542           var _this = Object.assign({}, field); // shallow copy
35543
35544
35545           _this.id = fieldID; // for use in classes, element ids, css selectors
35546
35547           _this.safeid = utilSafeClassName(fieldID);
35548
35549           _this.matchGeometry = function (geom) {
35550             return !_this.geometry || _this.geometry.indexOf(geom) !== -1;
35551           };
35552
35553           _this.matchAllGeometry = function (geometries) {
35554             return !_this.geometry || geometries.every(function (geom) {
35555               return _this.geometry.indexOf(geom) !== -1;
35556             });
35557           };
35558
35559           _this.t = function (scope, options) {
35560             return _t("_tagging.presets.fields.".concat(fieldID, ".").concat(scope), options);
35561           };
35562
35563           _this.t.html = function (scope, options) {
35564             return _t.html("_tagging.presets.fields.".concat(fieldID, ".").concat(scope), options);
35565           };
35566
35567           _this.hasTextForStringId = function (scope) {
35568             return _mainLocalizer.hasTextForStringId("_tagging.presets.fields.".concat(fieldID, ".").concat(scope));
35569           };
35570
35571           _this.title = function () {
35572             return _this.overrideLabel || _this.t('label', {
35573               'default': fieldID
35574             });
35575           };
35576
35577           _this.label = function () {
35578             return _this.overrideLabel || _this.t.html('label', {
35579               'default': fieldID
35580             });
35581           };
35582
35583           var _placeholder = _this.placeholder;
35584
35585           _this.placeholder = function () {
35586             return _this.t('placeholder', {
35587               'default': _placeholder
35588             });
35589           };
35590
35591           _this.originalTerms = (_this.terms || []).join();
35592
35593           _this.terms = function () {
35594             return _this.t('terms', {
35595               'default': _this.originalTerms
35596             }).toLowerCase().trim().split(/\s*,+\s*/);
35597           };
35598
35599           _this.increment = _this.type === 'number' ? _this.increment || 1 : undefined;
35600           return _this;
35601         }
35602
35603         // `presetPreset` decorates a given `preset` Object
35604         // with some extra methods for searching and matching geometry
35605         //
35606
35607         function presetPreset(presetID, preset, addable, allFields, allPresets) {
35608           allFields = allFields || {};
35609           allPresets = allPresets || {};
35610
35611           var _this = Object.assign({}, preset); // shallow copy
35612
35613
35614           var _addable = addable || false;
35615
35616           var _resolvedFields; // cache
35617
35618
35619           var _resolvedMoreFields; // cache
35620
35621
35622           var _searchName; // cache
35623
35624
35625           var _searchNameStripped; // cache
35626
35627
35628           _this.id = presetID;
35629           _this.safeid = utilSafeClassName(presetID); // for use in css classes, selectors, element ids
35630
35631           _this.originalTerms = (_this.terms || []).join();
35632           _this.originalName = _this.name || '';
35633           _this.originalScore = _this.matchScore || 1;
35634           _this.originalReference = _this.reference || {};
35635           _this.originalFields = _this.fields || [];
35636           _this.originalMoreFields = _this.moreFields || [];
35637
35638           _this.fields = function () {
35639             return _resolvedFields || (_resolvedFields = resolve('fields'));
35640           };
35641
35642           _this.moreFields = function () {
35643             return _resolvedMoreFields || (_resolvedMoreFields = resolve('moreFields'));
35644           };
35645
35646           _this.resetFields = function () {
35647             return _resolvedFields = _resolvedMoreFields = null;
35648           };
35649
35650           _this.tags = _this.tags || {};
35651           _this.addTags = _this.addTags || _this.tags;
35652           _this.removeTags = _this.removeTags || _this.addTags;
35653           _this.geometry = _this.geometry || [];
35654
35655           _this.matchGeometry = function (geom) {
35656             return _this.geometry.indexOf(geom) >= 0;
35657           };
35658
35659           _this.matchAllGeometry = function (geoms) {
35660             return geoms.every(_this.matchGeometry);
35661           };
35662
35663           _this.matchScore = function (entityTags) {
35664             var tags = _this.tags;
35665             var seen = {};
35666             var score = 0; // match on tags
35667
35668             for (var k in tags) {
35669               seen[k] = true;
35670
35671               if (entityTags[k] === tags[k]) {
35672                 score += _this.originalScore;
35673               } else if (tags[k] === '*' && k in entityTags) {
35674                 score += _this.originalScore / 2;
35675               } else {
35676                 return -1;
35677               }
35678             } // boost score for additional matches in addTags - #6802
35679
35680
35681             var addTags = _this.addTags;
35682
35683             for (var _k in addTags) {
35684               if (!seen[_k] && entityTags[_k] === addTags[_k]) {
35685                 score += _this.originalScore;
35686               }
35687             }
35688
35689             return score;
35690           };
35691
35692           _this.t = function (scope, options) {
35693             var textID = "_tagging.presets.presets.".concat(presetID, ".").concat(scope);
35694             return _t(textID, options);
35695           };
35696
35697           _this.t.html = function (scope, options) {
35698             var textID = "_tagging.presets.presets.".concat(presetID, ".").concat(scope);
35699             return _t.html(textID, options);
35700           };
35701
35702           _this.name = function () {
35703             return _this.t('name', {
35704               'default': _this.originalName
35705             });
35706           };
35707
35708           _this.nameLabel = function () {
35709             return _this.t.html('name', {
35710               'default': _this.originalName
35711             });
35712           };
35713
35714           _this.subtitle = function () {
35715             if (_this.suggestion) {
35716               var path = presetID.split('/');
35717               path.pop(); // remove brand name
35718
35719               return _t('_tagging.presets.presets.' + path.join('/') + '.name');
35720             }
35721
35722             return null;
35723           };
35724
35725           _this.subtitleLabel = function () {
35726             if (_this.suggestion) {
35727               var path = presetID.split('/');
35728               path.pop(); // remove brand name
35729
35730               return _t.html('_tagging.presets.presets.' + path.join('/') + '.name');
35731             }
35732
35733             return null;
35734           };
35735
35736           _this.terms = function () {
35737             return _this.t('terms', {
35738               'default': _this.originalTerms
35739             }).toLowerCase().trim().split(/\s*,+\s*/);
35740           };
35741
35742           _this.searchName = function () {
35743             if (!_searchName) {
35744               _searchName = (_this.suggestion ? _this.originalName : _this.name()).toLowerCase();
35745             }
35746
35747             return _searchName;
35748           };
35749
35750           _this.searchNameStripped = function () {
35751             if (!_searchNameStripped) {
35752               _searchNameStripped = _this.searchName(); // split combined diacritical characters into their parts
35753
35754               if (_searchNameStripped.normalize) _searchNameStripped = _searchNameStripped.normalize('NFD'); // remove diacritics
35755
35756               _searchNameStripped = _searchNameStripped.replace(/[\u0300-\u036f]/g, '');
35757             }
35758
35759             return _searchNameStripped;
35760           };
35761
35762           _this.isFallback = function () {
35763             var tagCount = Object.keys(_this.tags).length;
35764             return tagCount === 0 || tagCount === 1 && _this.tags.hasOwnProperty('area');
35765           };
35766
35767           _this.addable = function (val) {
35768             if (!arguments.length) return _addable;
35769             _addable = val;
35770             return _this;
35771           };
35772
35773           _this.reference = function () {
35774             // Lookup documentation on Wikidata...
35775             var qid = _this.tags.wikidata || _this.tags['flag:wikidata'] || _this.tags['brand:wikidata'] || _this.tags['network:wikidata'] || _this.tags['operator:wikidata'];
35776
35777             if (qid) {
35778               return {
35779                 qid: qid
35780               };
35781             } // Lookup documentation on OSM Wikibase...
35782
35783
35784             var key = _this.originalReference.key || Object.keys(utilObjectOmit(_this.tags, 'name'))[0];
35785             var value = _this.originalReference.value || _this.tags[key];
35786
35787             if (value === '*') {
35788               return {
35789                 key: key
35790               };
35791             } else {
35792               return {
35793                 key: key,
35794                 value: value
35795               };
35796             }
35797           };
35798
35799           _this.unsetTags = function (tags, geometry, ignoringKeys, skipFieldDefaults) {
35800             // allow manually keeping some tags
35801             var removeTags = ignoringKeys ? utilObjectOmit(_this.removeTags, ignoringKeys) : _this.removeTags;
35802             tags = utilObjectOmit(tags, Object.keys(removeTags));
35803
35804             if (geometry && !skipFieldDefaults) {
35805               _this.fields().forEach(function (field) {
35806                 if (field.matchGeometry(geometry) && field.key && field["default"] === tags[field.key]) {
35807                   delete tags[field.key];
35808                 }
35809               });
35810             }
35811
35812             delete tags.area;
35813             return tags;
35814           };
35815
35816           _this.setTags = function (tags, geometry, skipFieldDefaults) {
35817             var addTags = _this.addTags;
35818             tags = Object.assign({}, tags); // shallow copy
35819
35820             for (var k in addTags) {
35821               if (addTags[k] === '*') {
35822                 // if this tag is ancillary, don't override an existing value since any value is okay
35823                 if (_this.tags[k] || !tags[k] || tags[k] === 'no') {
35824                   tags[k] = 'yes';
35825                 }
35826               } else {
35827                 tags[k] = addTags[k];
35828               }
35829             } // Add area=yes if necessary.
35830             // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
35831             // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
35832             // 2. chosen preset doesn't have a key in osmAreaKeys (`railway=station`)
35833
35834
35835             if (!addTags.hasOwnProperty('area')) {
35836               delete tags.area;
35837
35838               if (geometry === 'area') {
35839                 var needsAreaTag = true;
35840
35841                 if (_this.geometry.indexOf('line') === -1) {
35842                   for (var _k2 in addTags) {
35843                     if (_k2 in osmAreaKeys) {
35844                       needsAreaTag = false;
35845                       break;
35846                     }
35847                   }
35848                 }
35849
35850                 if (needsAreaTag) {
35851                   tags.area = 'yes';
35852                 }
35853               }
35854             }
35855
35856             if (geometry && !skipFieldDefaults) {
35857               _this.fields().forEach(function (field) {
35858                 if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field["default"]) {
35859                   tags[field.key] = field["default"];
35860                 }
35861               });
35862             }
35863
35864             return tags;
35865           }; // For a preset without fields, use the fields of the parent preset.
35866           // Replace {preset} placeholders with the fields of the specified presets.
35867
35868
35869           function resolve(which) {
35870             var fieldIDs = which === 'fields' ? _this.originalFields : _this.originalMoreFields;
35871             var resolved = [];
35872             fieldIDs.forEach(function (fieldID) {
35873               var match = fieldID.match(/\{(.*)\}/);
35874
35875               if (match !== null) {
35876                 // a presetID wrapped in braces {}
35877                 resolved = resolved.concat(inheritFields(match[1], which));
35878               } else if (allFields[fieldID]) {
35879                 // a normal fieldID
35880                 resolved.push(allFields[fieldID]);
35881               } else {
35882                 console.log("Cannot resolve \"".concat(fieldID, "\" found in ").concat(_this.id, ".").concat(which)); // eslint-disable-line no-console
35883               }
35884             }); // no fields resolved, so use the parent's if possible
35885
35886             if (!resolved.length) {
35887               var endIndex = _this.id.lastIndexOf('/');
35888
35889               var parentID = endIndex && _this.id.substring(0, endIndex);
35890
35891               if (parentID) {
35892                 resolved = inheritFields(parentID, which);
35893               }
35894             }
35895
35896             return utilArrayUniq(resolved); // returns an array of fields to inherit from the given presetID, if found
35897
35898             function inheritFields(presetID, which) {
35899               var parent = allPresets[presetID];
35900               if (!parent) return [];
35901
35902               if (which === 'fields') {
35903                 return parent.fields().filter(shouldInherit);
35904               } else if (which === 'moreFields') {
35905                 return parent.moreFields();
35906               } else {
35907                 return [];
35908               }
35909             } // Skip `fields` for the keys which define the preset.
35910             // These are usually `typeCombo` fields like `shop=*`
35911
35912
35913             function shouldInherit(f) {
35914               if (f.key && _this.tags[f.key] !== undefined && // inherit anyway if multiple values are allowed or just a checkbox
35915               f.type !== 'multiCombo' && f.type !== 'semiCombo' && f.type !== 'manyCombo' && f.type !== 'check') return false;
35916               return true;
35917             }
35918           }
35919
35920           return _this;
35921         }
35922
35923         var _mainPresetIndex = presetIndex(); // singleton
35924         // `presetIndex` wraps a `presetCollection`
35925         // with methods for loading new data and returning defaults
35926         //
35927
35928         function presetIndex() {
35929           var dispatch = dispatch$8('favoritePreset', 'recentsChange');
35930           var MAXRECENTS = 30; // seed the preset lists with geometry fallbacks
35931
35932           var POINT = presetPreset('point', {
35933             name: 'Point',
35934             tags: {},
35935             geometry: ['point', 'vertex'],
35936             matchScore: 0.1
35937           });
35938           var LINE = presetPreset('line', {
35939             name: 'Line',
35940             tags: {},
35941             geometry: ['line'],
35942             matchScore: 0.1
35943           });
35944           var AREA = presetPreset('area', {
35945             name: 'Area',
35946             tags: {
35947               area: 'yes'
35948             },
35949             geometry: ['area'],
35950             matchScore: 0.1
35951           });
35952           var RELATION = presetPreset('relation', {
35953             name: 'Relation',
35954             tags: {},
35955             geometry: ['relation'],
35956             matchScore: 0.1
35957           });
35958
35959           var _this = presetCollection([POINT, LINE, AREA, RELATION]);
35960
35961           var _presets = {
35962             point: POINT,
35963             line: LINE,
35964             area: AREA,
35965             relation: RELATION
35966           };
35967           var _defaults = {
35968             point: presetCollection([POINT]),
35969             vertex: presetCollection([POINT]),
35970             line: presetCollection([LINE]),
35971             area: presetCollection([AREA]),
35972             relation: presetCollection([RELATION])
35973           };
35974           var _fields = {};
35975           var _categories = {};
35976           var _universal = [];
35977           var _addablePresetIDs = null; // Set of preset IDs that the user can add
35978
35979           var _recents;
35980
35981           var _favorites; // Index of presets by (geometry, tag key).
35982
35983
35984           var _geometryIndex = {
35985             point: {},
35986             vertex: {},
35987             line: {},
35988             area: {},
35989             relation: {}
35990           };
35991
35992           var _loadPromise;
35993
35994           _this.ensureLoaded = function () {
35995             if (_loadPromise) return _loadPromise;
35996             return _loadPromise = Promise.all([_mainFileFetcher.get('preset_categories'), _mainFileFetcher.get('preset_defaults'), _mainFileFetcher.get('preset_presets'), _mainFileFetcher.get('preset_fields')]).then(function (vals) {
35997               _this.merge({
35998                 categories: vals[0],
35999                 defaults: vals[1],
36000                 presets: vals[2],
36001                 fields: vals[3]
36002               });
36003
36004               osmSetAreaKeys(_this.areaKeys());
36005               osmSetPointTags(_this.pointTags());
36006               osmSetVertexTags(_this.vertexTags());
36007             });
36008           }; // `merge` accepts an object containing new preset data (all properties optional):
36009           // {
36010           //   fields: {},
36011           //   presets: {},
36012           //   categories: {},
36013           //   defaults: {},
36014           //   featureCollection: {}
36015           //}
36016
36017
36018           _this.merge = function (d) {
36019             var newLocationSets = []; // Merge Fields
36020
36021             if (d.fields) {
36022               Object.keys(d.fields).forEach(function (fieldID) {
36023                 var f = d.fields[fieldID];
36024
36025                 if (f) {
36026                   // add or replace
36027                   f = presetField(fieldID, f);
36028                   if (f.locationSet) newLocationSets.push(f);
36029                   _fields[fieldID] = f;
36030                 } else {
36031                   // remove
36032                   delete _fields[fieldID];
36033                 }
36034               });
36035             } // Merge Presets
36036
36037
36038             if (d.presets) {
36039               Object.keys(d.presets).forEach(function (presetID) {
36040                 var p = d.presets[presetID];
36041
36042                 if (p) {
36043                   // add or replace
36044                   var isAddable = !_addablePresetIDs || _addablePresetIDs.has(presetID);
36045
36046                   p = presetPreset(presetID, p, isAddable, _fields, _presets);
36047                   if (p.locationSet) newLocationSets.push(p);
36048                   _presets[presetID] = p;
36049                 } else {
36050                   // remove (but not if it's a fallback)
36051                   var existing = _presets[presetID];
36052
36053                   if (existing && !existing.isFallback()) {
36054                     delete _presets[presetID];
36055                   }
36056                 }
36057               });
36058             } // Merge Categories
36059
36060
36061             if (d.categories) {
36062               Object.keys(d.categories).forEach(function (categoryID) {
36063                 var c = d.categories[categoryID];
36064
36065                 if (c) {
36066                   // add or replace
36067                   c = presetCategory(categoryID, c, _presets);
36068                   if (c.locationSet) newLocationSets.push(c);
36069                   _categories[categoryID] = c;
36070                 } else {
36071                   // remove
36072                   delete _categories[categoryID];
36073                 }
36074               });
36075             } // Rebuild _this.collection after changing presets and categories
36076
36077
36078             _this.collection = Object.values(_presets).concat(Object.values(_categories)); // Merge Defaults
36079
36080             if (d.defaults) {
36081               Object.keys(d.defaults).forEach(function (geometry) {
36082                 var def = d.defaults[geometry];
36083
36084                 if (Array.isArray(def)) {
36085                   // add or replace
36086                   _defaults[geometry] = presetCollection(def.map(function (id) {
36087                     return _presets[id] || _categories[id];
36088                   }).filter(Boolean));
36089                 } else {
36090                   // remove
36091                   delete _defaults[geometry];
36092                 }
36093               });
36094             } // Rebuild universal fields array
36095
36096
36097             _universal = Object.values(_fields).filter(function (field) {
36098               return field.universal;
36099             }); // Reset all the preset fields - they'll need to be resolved again
36100
36101             Object.values(_presets).forEach(function (preset) {
36102               return preset.resetFields();
36103             }); // Rebuild geometry index
36104
36105             _geometryIndex = {
36106               point: {},
36107               vertex: {},
36108               line: {},
36109               area: {},
36110               relation: {}
36111             };
36112
36113             _this.collection.forEach(function (preset) {
36114               (preset.geometry || []).forEach(function (geometry) {
36115                 var g = _geometryIndex[geometry];
36116
36117                 for (var key in preset.tags) {
36118                   g[key] = g[key] || {};
36119                   var value = preset.tags[key];
36120                   (g[key][value] = g[key][value] || []).push(preset);
36121                 }
36122               });
36123             }); // Merge Custom Features
36124
36125
36126             if (d.featureCollection && Array.isArray(d.featureCollection.features)) {
36127               _mainLocations.mergeCustomGeoJSON(d.featureCollection);
36128             } // Resolve all locationSet features.
36129
36130
36131             if (newLocationSets.length) {
36132               _mainLocations.mergeLocationSets(newLocationSets);
36133             }
36134
36135             return _this;
36136           };
36137
36138           _this.match = function (entity, resolver) {
36139             return resolver["transient"](entity, 'presetMatch', function () {
36140               var geometry = entity.geometry(resolver); // Treat entities on addr:interpolation lines as points, not vertices - #3241
36141
36142               if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
36143                 geometry = 'point';
36144               }
36145
36146               var entityExtent = entity.extent(resolver);
36147               return _this.matchTags(entity.tags, geometry, entityExtent.center());
36148             });
36149           };
36150
36151           _this.matchTags = function (tags, geometry, loc) {
36152             var keyIndex = _geometryIndex[geometry];
36153             var bestScore = -1;
36154             var bestMatch;
36155             var matchCandidates = [];
36156
36157             for (var k in tags) {
36158               var indexMatches = [];
36159               var valueIndex = keyIndex[k];
36160               if (!valueIndex) continue;
36161               var keyValueMatches = valueIndex[tags[k]];
36162               if (keyValueMatches) indexMatches.push.apply(indexMatches, _toConsumableArray(keyValueMatches));
36163               var keyStarMatches = valueIndex['*'];
36164               if (keyStarMatches) indexMatches.push.apply(indexMatches, _toConsumableArray(keyStarMatches));
36165               if (indexMatches.length === 0) continue;
36166
36167               for (var i = 0; i < indexMatches.length; i++) {
36168                 var candidate = indexMatches[i];
36169                 var score = candidate.matchScore(tags);
36170
36171                 if (score === -1) {
36172                   continue;
36173                 }
36174
36175                 matchCandidates.push({
36176                   score: score,
36177                   candidate: candidate
36178                 });
36179
36180                 if (score > bestScore) {
36181                   bestScore = score;
36182                   bestMatch = candidate;
36183                 }
36184               }
36185             }
36186
36187             if (bestMatch && bestMatch.locationSetID && bestMatch.locationSetID !== '+[Q2]' && Array.isArray(loc)) {
36188               var validLocations = _mainLocations.locationsAt(loc);
36189
36190               if (!validLocations[bestMatch.locationSetID]) {
36191                 matchCandidates.sort(function (a, b) {
36192                   return a.score < b.score ? 1 : -1;
36193                 });
36194
36195                 for (var _i = 0; _i < matchCandidates.length; _i++) {
36196                   var candidateScore = matchCandidates[_i];
36197
36198                   if (!candidateScore.candidate.locationSetID || validLocations[candidateScore.candidate.locationSetID]) {
36199                     bestMatch = candidateScore.candidate;
36200                     bestScore = candidateScore.score;
36201                     break;
36202                   }
36203                 }
36204               }
36205             } // If any part of an address is present, allow fallback to "Address" preset - #4353
36206
36207
36208             if (!bestMatch || bestMatch.isFallback()) {
36209               for (var _k in tags) {
36210                 if (/^addr:/.test(_k) && keyIndex['addr:*'] && keyIndex['addr:*']['*']) {
36211                   bestMatch = keyIndex['addr:*']['*'][0];
36212                   break;
36213                 }
36214               }
36215             }
36216
36217             return bestMatch || _this.fallback(geometry);
36218           };
36219
36220           _this.allowsVertex = function (entity, resolver) {
36221             if (entity.type !== 'node') return false;
36222             if (Object.keys(entity.tags).length === 0) return true;
36223             return resolver["transient"](entity, 'vertexMatch', function () {
36224               // address lines allow vertices to act as standalone points
36225               if (entity.isOnAddressLine(resolver)) return true;
36226               var geometries = osmNodeGeometriesForTags(entity.tags);
36227               if (geometries.vertex) return true;
36228               if (geometries.point) return false; // allow vertices for unspecified points
36229
36230               return true;
36231             });
36232           }; // Because of the open nature of tagging, iD will never have a complete
36233           // list of tags used in OSM, so we want it to have logic like "assume
36234           // that a closed way with an amenity tag is an area, unless the amenity
36235           // is one of these specific types". This function computes a structure
36236           // that allows testing of such conditions, based on the presets designated
36237           // as as supporting (or not supporting) the area geometry.
36238           //
36239           // The returned object L is a keeplist/discardlist of tags. A closed way
36240           // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
36241           // (see `Way#isArea()`). In other words, the keys of L form the keeplist,
36242           // and the subkeys form the discardlist.
36243
36244
36245           _this.areaKeys = function () {
36246             // The ignore list is for keys that imply lines. (We always add `area=yes` for exceptions)
36247             var ignore = ['barrier', 'highway', 'footway', 'railway', 'junction', 'type'];
36248             var areaKeys = {}; // ignore name-suggestion-index and deprecated presets
36249
36250             var presets = _this.collection.filter(function (p) {
36251               return !p.suggestion && !p.replacement;
36252             }); // keeplist
36253
36254
36255             presets.forEach(function (p) {
36256               var keys = p.tags && Object.keys(p.tags);
36257               var key = keys && keys.length && keys[0]; // pick the first tag
36258
36259               if (!key) return;
36260               if (ignore.indexOf(key) !== -1) return;
36261
36262               if (p.geometry.indexOf('area') !== -1) {
36263                 // probably an area..
36264                 areaKeys[key] = areaKeys[key] || {};
36265               }
36266             }); // discardlist
36267
36268             presets.forEach(function (p) {
36269               var key;
36270
36271               for (key in p.addTags) {
36272                 // examine all addTags to get a better sense of what can be tagged on lines - #6800
36273                 var value = p.addTags[key];
36274
36275                 if (key in areaKeys && // probably an area...
36276                 p.geometry.indexOf('line') !== -1 && // but sometimes a line
36277                 value !== '*') {
36278                   areaKeys[key][value] = true;
36279                 }
36280               }
36281             });
36282             return areaKeys;
36283           };
36284
36285           _this.pointTags = function () {
36286             return _this.collection.reduce(function (pointTags, d) {
36287               // ignore name-suggestion-index, deprecated, and generic presets
36288               if (d.suggestion || d.replacement || d.searchable === false) return pointTags; // only care about the primary tag
36289
36290               var keys = d.tags && Object.keys(d.tags);
36291               var key = keys && keys.length && keys[0]; // pick the first tag
36292
36293               if (!key) return pointTags; // if this can be a point
36294
36295               if (d.geometry.indexOf('point') !== -1) {
36296                 pointTags[key] = pointTags[key] || {};
36297                 pointTags[key][d.tags[key]] = true;
36298               }
36299
36300               return pointTags;
36301             }, {});
36302           };
36303
36304           _this.vertexTags = function () {
36305             return _this.collection.reduce(function (vertexTags, d) {
36306               // ignore name-suggestion-index, deprecated, and generic presets
36307               if (d.suggestion || d.replacement || d.searchable === false) return vertexTags; // only care about the primary tag
36308
36309               var keys = d.tags && Object.keys(d.tags);
36310               var key = keys && keys.length && keys[0]; // pick the first tag
36311
36312               if (!key) return vertexTags; // if this can be a vertex
36313
36314               if (d.geometry.indexOf('vertex') !== -1) {
36315                 vertexTags[key] = vertexTags[key] || {};
36316                 vertexTags[key][d.tags[key]] = true;
36317               }
36318
36319               return vertexTags;
36320             }, {});
36321           };
36322
36323           _this.field = function (id) {
36324             return _fields[id];
36325           };
36326
36327           _this.universal = function () {
36328             return _universal;
36329           };
36330
36331           _this.defaults = function (geometry, n, startWithRecents, loc) {
36332             var recents = [];
36333
36334             if (startWithRecents) {
36335               recents = _this.recent().matchGeometry(geometry).collection.slice(0, 4);
36336             }
36337
36338             var defaults;
36339
36340             if (_addablePresetIDs) {
36341               defaults = Array.from(_addablePresetIDs).map(function (id) {
36342                 var preset = _this.item(id);
36343
36344                 if (preset && preset.matchGeometry(geometry)) return preset;
36345                 return null;
36346               }).filter(Boolean);
36347             } else {
36348               defaults = _defaults[geometry].collection.concat(_this.fallback(geometry));
36349             }
36350
36351             var result = presetCollection(utilArrayUniq(recents.concat(defaults)).slice(0, n - 1));
36352
36353             if (Array.isArray(loc)) {
36354               var validLocations = _mainLocations.locationsAt(loc);
36355               result.collection = result.collection.filter(function (a) {
36356                 return !a.locationSetID || validLocations[a.locationSetID];
36357               });
36358             }
36359
36360             return result;
36361           }; // pass a Set of addable preset ids
36362
36363
36364           _this.addablePresetIDs = function (val) {
36365             if (!arguments.length) return _addablePresetIDs; // accept and convert arrays
36366
36367             if (Array.isArray(val)) val = new Set(val);
36368             _addablePresetIDs = val;
36369
36370             if (_addablePresetIDs) {
36371               // reset all presets
36372               _this.collection.forEach(function (p) {
36373                 // categories aren't addable
36374                 if (p.addable) p.addable(_addablePresetIDs.has(p.id));
36375               });
36376             } else {
36377               _this.collection.forEach(function (p) {
36378                 if (p.addable) p.addable(true);
36379               });
36380             }
36381
36382             return _this;
36383           };
36384
36385           _this.recent = function () {
36386             return presetCollection(utilArrayUniq(_this.getRecents().map(function (d) {
36387               return d.preset;
36388             })));
36389           };
36390
36391           function RibbonItem(preset, source) {
36392             var item = {};
36393             item.preset = preset;
36394             item.source = source;
36395
36396             item.isFavorite = function () {
36397               return item.source === 'favorite';
36398             };
36399
36400             item.isRecent = function () {
36401               return item.source === 'recent';
36402             };
36403
36404             item.matches = function (preset) {
36405               return item.preset.id === preset.id;
36406             };
36407
36408             item.minified = function () {
36409               return {
36410                 pID: item.preset.id
36411               };
36412             };
36413
36414             return item;
36415           }
36416
36417           function ribbonItemForMinified(d, source) {
36418             if (d && d.pID) {
36419               var preset = _this.item(d.pID);
36420
36421               if (!preset) return null;
36422               return RibbonItem(preset, source);
36423             }
36424
36425             return null;
36426           }
36427
36428           _this.getGenericRibbonItems = function () {
36429             return ['point', 'line', 'area'].map(function (id) {
36430               return RibbonItem(_this.item(id), 'generic');
36431             });
36432           };
36433
36434           _this.getAddable = function () {
36435             if (!_addablePresetIDs) return [];
36436             return _addablePresetIDs.map(function (id) {
36437               var preset = _this.item(id);
36438
36439               if (preset) return RibbonItem(preset, 'addable');
36440               return null;
36441             }).filter(Boolean);
36442           };
36443
36444           function setRecents(items) {
36445             _recents = items;
36446             var minifiedItems = items.map(function (d) {
36447               return d.minified();
36448             });
36449             corePreferences('preset_recents', JSON.stringify(minifiedItems));
36450             dispatch.call('recentsChange');
36451           }
36452
36453           _this.getRecents = function () {
36454             if (!_recents) {
36455               // fetch from local storage
36456               _recents = (JSON.parse(corePreferences('preset_recents')) || []).reduce(function (acc, d) {
36457                 var item = ribbonItemForMinified(d, 'recent');
36458                 if (item && item.preset.addable()) acc.push(item);
36459                 return acc;
36460               }, []);
36461             }
36462
36463             return _recents;
36464           };
36465
36466           _this.addRecent = function (preset, besidePreset, after) {
36467             var recents = _this.getRecents();
36468
36469             var beforeItem = _this.recentMatching(besidePreset);
36470
36471             var toIndex = recents.indexOf(beforeItem);
36472             if (after) toIndex += 1;
36473             var newItem = RibbonItem(preset, 'recent');
36474             recents.splice(toIndex, 0, newItem);
36475             setRecents(recents);
36476           };
36477
36478           _this.removeRecent = function (preset) {
36479             var item = _this.recentMatching(preset);
36480
36481             if (item) {
36482               var items = _this.getRecents();
36483
36484               items.splice(items.indexOf(item), 1);
36485               setRecents(items);
36486             }
36487           };
36488
36489           _this.recentMatching = function (preset) {
36490             var items = _this.getRecents();
36491
36492             for (var i in items) {
36493               if (items[i].matches(preset)) {
36494                 return items[i];
36495               }
36496             }
36497
36498             return null;
36499           };
36500
36501           _this.moveItem = function (items, fromIndex, toIndex) {
36502             if (fromIndex === toIndex || fromIndex < 0 || toIndex < 0 || fromIndex >= items.length || toIndex >= items.length) return null;
36503             items.splice(toIndex, 0, items.splice(fromIndex, 1)[0]);
36504             return items;
36505           };
36506
36507           _this.moveRecent = function (item, beforeItem) {
36508             var recents = _this.getRecents();
36509
36510             var fromIndex = recents.indexOf(item);
36511             var toIndex = recents.indexOf(beforeItem);
36512
36513             var items = _this.moveItem(recents, fromIndex, toIndex);
36514
36515             if (items) setRecents(items);
36516           };
36517
36518           _this.setMostRecent = function (preset) {
36519             if (preset.searchable === false) return;
36520
36521             var items = _this.getRecents();
36522
36523             var item = _this.recentMatching(preset);
36524
36525             if (item) {
36526               items.splice(items.indexOf(item), 1);
36527             } else {
36528               item = RibbonItem(preset, 'recent');
36529             } // remove the last recent (first in, first out)
36530
36531
36532             while (items.length >= MAXRECENTS) {
36533               items.pop();
36534             } // prepend array
36535
36536
36537             items.unshift(item);
36538             setRecents(items);
36539           };
36540
36541           function setFavorites(items) {
36542             _favorites = items;
36543             var minifiedItems = items.map(function (d) {
36544               return d.minified();
36545             });
36546             corePreferences('preset_favorites', JSON.stringify(minifiedItems)); // call update
36547
36548             dispatch.call('favoritePreset');
36549           }
36550
36551           _this.addFavorite = function (preset, besidePreset, after) {
36552             var favorites = _this.getFavorites();
36553
36554             var beforeItem = _this.favoriteMatching(besidePreset);
36555
36556             var toIndex = favorites.indexOf(beforeItem);
36557             if (after) toIndex += 1;
36558             var newItem = RibbonItem(preset, 'favorite');
36559             favorites.splice(toIndex, 0, newItem);
36560             setFavorites(favorites);
36561           };
36562
36563           _this.toggleFavorite = function (preset) {
36564             var favs = _this.getFavorites();
36565
36566             var favorite = _this.favoriteMatching(preset);
36567
36568             if (favorite) {
36569               favs.splice(favs.indexOf(favorite), 1);
36570             } else {
36571               // only allow 10 favorites
36572               if (favs.length === 10) {
36573                 // remove the last favorite (last in, first out)
36574                 favs.pop();
36575               } // append array
36576
36577
36578               favs.push(RibbonItem(preset, 'favorite'));
36579             }
36580
36581             setFavorites(favs);
36582           };
36583
36584           _this.removeFavorite = function (preset) {
36585             var item = _this.favoriteMatching(preset);
36586
36587             if (item) {
36588               var items = _this.getFavorites();
36589
36590               items.splice(items.indexOf(item), 1);
36591               setFavorites(items);
36592             }
36593           };
36594
36595           _this.getFavorites = function () {
36596             if (!_favorites) {
36597               // fetch from local storage
36598               var rawFavorites = JSON.parse(corePreferences('preset_favorites'));
36599
36600               if (!rawFavorites) {
36601                 rawFavorites = [];
36602                 corePreferences('preset_favorites', JSON.stringify(rawFavorites));
36603               }
36604
36605               _favorites = rawFavorites.reduce(function (output, d) {
36606                 var item = ribbonItemForMinified(d, 'favorite');
36607                 if (item && item.preset.addable()) output.push(item);
36608                 return output;
36609               }, []);
36610             }
36611
36612             return _favorites;
36613           };
36614
36615           _this.favoriteMatching = function (preset) {
36616             var favs = _this.getFavorites();
36617
36618             for (var index in favs) {
36619               if (favs[index].matches(preset)) {
36620                 return favs[index];
36621               }
36622             }
36623
36624             return null;
36625           };
36626
36627           return utilRebind(_this, dispatch, 'on');
36628         }
36629
36630         function utilTagText(entity) {
36631           var obj = entity && entity.tags || {};
36632           return Object.keys(obj).map(function (k) {
36633             return k + '=' + obj[k];
36634           }).join(', ');
36635         }
36636         function utilTotalExtent(array, graph) {
36637           var extent = geoExtent();
36638           var val, entity;
36639
36640           for (var i = 0; i < array.length; i++) {
36641             val = array[i];
36642             entity = typeof val === 'string' ? graph.hasEntity(val) : val;
36643
36644             if (entity) {
36645               extent._extend(entity.extent(graph));
36646             }
36647           }
36648
36649           return extent;
36650         }
36651         function utilTagDiff(oldTags, newTags) {
36652           var tagDiff = [];
36653           var keys = utilArrayUnion(Object.keys(oldTags), Object.keys(newTags)).sort();
36654           keys.forEach(function (k) {
36655             var oldVal = oldTags[k];
36656             var newVal = newTags[k];
36657
36658             if ((oldVal || oldVal === '') && (newVal === undefined || newVal !== oldVal)) {
36659               tagDiff.push({
36660                 type: '-',
36661                 key: k,
36662                 oldVal: oldVal,
36663                 newVal: newVal,
36664                 display: '- ' + k + '=' + oldVal
36665               });
36666             }
36667
36668             if ((newVal || newVal === '') && (oldVal === undefined || newVal !== oldVal)) {
36669               tagDiff.push({
36670                 type: '+',
36671                 key: k,
36672                 oldVal: oldVal,
36673                 newVal: newVal,
36674                 display: '+ ' + k + '=' + newVal
36675               });
36676             }
36677           });
36678           return tagDiff;
36679         }
36680         function utilEntitySelector(ids) {
36681           return ids.length ? '.' + ids.join(',.') : 'nothing';
36682         } // returns an selector to select entity ids for:
36683         //  - entityIDs passed in
36684         //  - shallow descendant entityIDs for any of those entities that are relations
36685
36686         function utilEntityOrMemberSelector(ids, graph) {
36687           var seen = new Set(ids);
36688           ids.forEach(collectShallowDescendants);
36689           return utilEntitySelector(Array.from(seen));
36690
36691           function collectShallowDescendants(id) {
36692             var entity = graph.hasEntity(id);
36693             if (!entity || entity.type !== 'relation') return;
36694             entity.members.map(function (member) {
36695               return member.id;
36696             }).forEach(function (id) {
36697               seen.add(id);
36698             });
36699           }
36700         } // returns an selector to select entity ids for:
36701         //  - entityIDs passed in
36702         //  - deep descendant entityIDs for any of those entities that are relations
36703
36704         function utilEntityOrDeepMemberSelector(ids, graph) {
36705           return utilEntitySelector(utilEntityAndDeepMemberIDs(ids, graph));
36706         } // returns an selector to select entity ids for:
36707         //  - entityIDs passed in
36708         //  - deep descendant entityIDs for any of those entities that are relations
36709
36710         function utilEntityAndDeepMemberIDs(ids, graph) {
36711           var seen = new Set();
36712           ids.forEach(collectDeepDescendants);
36713           return Array.from(seen);
36714
36715           function collectDeepDescendants(id) {
36716             if (seen.has(id)) return;
36717             seen.add(id);
36718             var entity = graph.hasEntity(id);
36719             if (!entity || entity.type !== 'relation') return;
36720             entity.members.map(function (member) {
36721               return member.id;
36722             }).forEach(collectDeepDescendants); // recurse
36723           }
36724         } // returns an selector to select entity ids for:
36725         //  - deep descendant entityIDs for any of those entities that are relations
36726
36727         function utilDeepMemberSelector(ids, graph, skipMultipolgonMembers) {
36728           var idsSet = new Set(ids);
36729           var seen = new Set();
36730           var returners = new Set();
36731           ids.forEach(collectDeepDescendants);
36732           return utilEntitySelector(Array.from(returners));
36733
36734           function collectDeepDescendants(id) {
36735             if (seen.has(id)) return;
36736             seen.add(id);
36737
36738             if (!idsSet.has(id)) {
36739               returners.add(id);
36740             }
36741
36742             var entity = graph.hasEntity(id);
36743             if (!entity || entity.type !== 'relation') return;
36744             if (skipMultipolgonMembers && entity.isMultipolygon()) return;
36745             entity.members.map(function (member) {
36746               return member.id;
36747             }).forEach(collectDeepDescendants); // recurse
36748           }
36749         } // Adds or removes highlight styling for the specified entities
36750
36751         function utilHighlightEntities(ids, highlighted, context) {
36752           context.surface().selectAll(utilEntityOrDeepMemberSelector(ids, context.graph())).classed('highlighted', highlighted);
36753         } // returns an Array that is the union of:
36754         //  - nodes for any nodeIDs passed in
36755         //  - child nodes of any wayIDs passed in
36756         //  - descendant member and child nodes of relationIDs passed in
36757
36758         function utilGetAllNodes(ids, graph) {
36759           var seen = new Set();
36760           var nodes = new Set();
36761           ids.forEach(collectNodes);
36762           return Array.from(nodes);
36763
36764           function collectNodes(id) {
36765             if (seen.has(id)) return;
36766             seen.add(id);
36767             var entity = graph.hasEntity(id);
36768             if (!entity) return;
36769
36770             if (entity.type === 'node') {
36771               nodes.add(entity);
36772             } else if (entity.type === 'way') {
36773               entity.nodes.forEach(collectNodes);
36774             } else {
36775               entity.members.map(function (member) {
36776                 return member.id;
36777               }).forEach(collectNodes); // recurse
36778             }
36779           }
36780         }
36781         function utilDisplayName(entity) {
36782           var localizedNameKey = 'name:' + _mainLocalizer.languageCode().toLowerCase();
36783           var name = entity.tags[localizedNameKey] || entity.tags.name || '';
36784           if (name) return name;
36785           var tags = {
36786             direction: entity.tags.direction,
36787             from: entity.tags.from,
36788             network: entity.tags.cycle_network || entity.tags.network,
36789             ref: entity.tags.ref,
36790             to: entity.tags.to,
36791             via: entity.tags.via
36792           };
36793           var keyComponents = [];
36794
36795           if (tags.network) {
36796             keyComponents.push('network');
36797           }
36798
36799           if (tags.ref) {
36800             keyComponents.push('ref');
36801           } // Routes may need more disambiguation based on direction or destination
36802
36803
36804           if (entity.tags.route) {
36805             if (tags.direction) {
36806               keyComponents.push('direction');
36807             } else if (tags.from && tags.to) {
36808               keyComponents.push('from');
36809               keyComponents.push('to');
36810
36811               if (tags.via) {
36812                 keyComponents.push('via');
36813               }
36814             }
36815           }
36816
36817           if (keyComponents.length) {
36818             name = _t('inspector.display_name.' + keyComponents.join('_'), tags);
36819           }
36820
36821           return name;
36822         }
36823         function utilDisplayNameForPath(entity) {
36824           var name = utilDisplayName(entity);
36825           var isFirefox = utilDetect().browser.toLowerCase().indexOf('firefox') > -1;
36826           var isNewChromium = Number(utilDetect().version.split('.')[0]) >= 96.0;
36827
36828           if (!isFirefox && !isNewChromium && name && rtlRegex.test(name)) {
36829             name = fixRTLTextForSvg(name);
36830           }
36831
36832           return name;
36833         }
36834         function utilDisplayType(id) {
36835           return {
36836             n: _t('inspector.node'),
36837             w: _t('inspector.way'),
36838             r: _t('inspector.relation')
36839           }[id.charAt(0)];
36840         } // `utilDisplayLabel`
36841         // Returns a string suitable for display
36842         // By default returns something like name/ref, fallback to preset type, fallback to OSM type
36843         //   "Main Street" or "Tertiary Road"
36844         // If `verbose=true`, include both preset name and feature name.
36845         //   "Tertiary Road Main Street"
36846         //
36847
36848         function utilDisplayLabel(entity, graphOrGeometry, verbose) {
36849           var result;
36850           var displayName = utilDisplayName(entity);
36851           var preset = typeof graphOrGeometry === 'string' ? _mainPresetIndex.matchTags(entity.tags, graphOrGeometry) : _mainPresetIndex.match(entity, graphOrGeometry);
36852           var presetName = preset && (preset.suggestion ? preset.subtitle() : preset.name());
36853
36854           if (verbose) {
36855             result = [presetName, displayName].filter(Boolean).join(' ');
36856           } else {
36857             result = displayName || presetName;
36858           } // Fallback to the OSM type (node/way/relation)
36859
36860
36861           return result || utilDisplayType(entity.id);
36862         }
36863         function utilEntityRoot(entityType) {
36864           return {
36865             node: 'n',
36866             way: 'w',
36867             relation: 'r'
36868           }[entityType];
36869         } // Returns a single object containing the tags of all the given entities.
36870         // Example:
36871         // {
36872         //   highway: 'service',
36873         //   service: 'parking_aisle'
36874         // }
36875         //           +
36876         // {
36877         //   highway: 'service',
36878         //   service: 'driveway',
36879         //   width: '3'
36880         // }
36881         //           =
36882         // {
36883         //   highway: 'service',
36884         //   service: [ 'driveway', 'parking_aisle' ],
36885         //   width: [ '3', undefined ]
36886         // }
36887
36888         function utilCombinedTags(entityIDs, graph) {
36889           var tags = {};
36890           var tagCounts = {};
36891           var allKeys = new Set();
36892           var entities = entityIDs.map(function (entityID) {
36893             return graph.hasEntity(entityID);
36894           }).filter(Boolean); // gather the aggregate keys
36895
36896           entities.forEach(function (entity) {
36897             var keys = Object.keys(entity.tags).filter(Boolean);
36898             keys.forEach(function (key) {
36899               allKeys.add(key);
36900             });
36901           });
36902           entities.forEach(function (entity) {
36903             allKeys.forEach(function (key) {
36904               var value = entity.tags[key]; // purposely allow `undefined`
36905
36906               if (!tags.hasOwnProperty(key)) {
36907                 // first value, set as raw
36908                 tags[key] = value;
36909               } else {
36910                 if (!Array.isArray(tags[key])) {
36911                   if (tags[key] !== value) {
36912                     // first alternate value, replace single value with array
36913                     tags[key] = [tags[key], value];
36914                   }
36915                 } else {
36916                   // type is array
36917                   if (tags[key].indexOf(value) === -1) {
36918                     // subsequent alternate value, add to array
36919                     tags[key].push(value);
36920                   }
36921                 }
36922               }
36923
36924               var tagHash = key + '=' + value;
36925               if (!tagCounts[tagHash]) tagCounts[tagHash] = 0;
36926               tagCounts[tagHash] += 1;
36927             });
36928           });
36929
36930           for (var key in tags) {
36931             if (!Array.isArray(tags[key])) continue; // sort values by frequency then alphabetically
36932
36933             tags[key] = tags[key].sort(function (val1, val2) {
36934               var key = key; // capture
36935
36936               var count2 = tagCounts[key + '=' + val2];
36937               var count1 = tagCounts[key + '=' + val1];
36938
36939               if (count2 !== count1) {
36940                 return count2 - count1;
36941               }
36942
36943               if (val2 && val1) {
36944                 return val1.localeCompare(val2);
36945               }
36946
36947               return val1 ? 1 : -1;
36948             });
36949           }
36950
36951           return tags;
36952         }
36953         function utilStringQs(str) {
36954           var i = 0; // advance past any leading '?' or '#' characters
36955
36956           while (i < str.length && (str[i] === '?' || str[i] === '#')) {
36957             i++;
36958           }
36959
36960           str = str.slice(i);
36961           return str.split('&').reduce(function (obj, pair) {
36962             var parts = pair.split('=');
36963
36964             if (parts.length === 2) {
36965               obj[parts[0]] = null === parts[1] ? '' : decodeURIComponent(parts[1]);
36966             }
36967
36968             return obj;
36969           }, {});
36970         }
36971         function utilQsString(obj, noencode) {
36972           // encode everything except special characters used in certain hash parameters:
36973           // "/" in map states, ":", ",", {" and "}" in background
36974           function softEncode(s) {
36975             return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
36976           }
36977
36978           return Object.keys(obj).sort().map(function (key) {
36979             return encodeURIComponent(key) + '=' + (noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
36980           }).join('&');
36981         }
36982         function utilPrefixDOMProperty(property) {
36983           var prefixes = ['webkit', 'ms', 'moz', 'o'];
36984           var i = -1;
36985           var n = prefixes.length;
36986           var s = document.body;
36987           if (property in s) return property;
36988           property = property.substr(0, 1).toUpperCase() + property.substr(1);
36989
36990           while (++i < n) {
36991             if (prefixes[i] + property in s) {
36992               return prefixes[i] + property;
36993             }
36994           }
36995
36996           return false;
36997         }
36998         function utilPrefixCSSProperty(property) {
36999           var prefixes = ['webkit', 'ms', 'Moz', 'O'];
37000           var i = -1;
37001           var n = prefixes.length;
37002           var s = document.body.style;
37003
37004           if (property.toLowerCase() in s) {
37005             return property.toLowerCase();
37006           }
37007
37008           while (++i < n) {
37009             if (prefixes[i] + property in s) {
37010               return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
37011             }
37012           }
37013
37014           return false;
37015         }
37016         var transformProperty;
37017         function utilSetTransform(el, x, y, scale) {
37018           var prop = transformProperty = transformProperty || utilPrefixCSSProperty('Transform');
37019           var translate = utilDetect().opera ? 'translate(' + x + 'px,' + y + 'px)' : 'translate3d(' + x + 'px,' + y + 'px,0)';
37020           return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
37021         } // Calculates Levenshtein distance between two strings
37022         // see:  https://en.wikipedia.org/wiki/Levenshtein_distance
37023         // first converts the strings to lowercase and replaces diacritic marks with ascii equivalents.
37024
37025         function utilEditDistance(a, b) {
37026           a = remove$6(a.toLowerCase());
37027           b = remove$6(b.toLowerCase());
37028           if (a.length === 0) return b.length;
37029           if (b.length === 0) return a.length;
37030           var matrix = [];
37031           var i, j;
37032
37033           for (i = 0; i <= b.length; i++) {
37034             matrix[i] = [i];
37035           }
37036
37037           for (j = 0; j <= a.length; j++) {
37038             matrix[0][j] = j;
37039           }
37040
37041           for (i = 1; i <= b.length; i++) {
37042             for (j = 1; j <= a.length; j++) {
37043               if (b.charAt(i - 1) === a.charAt(j - 1)) {
37044                 matrix[i][j] = matrix[i - 1][j - 1];
37045               } else {
37046                 matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
37047                 Math.min(matrix[i][j - 1] + 1, // insertion
37048                 matrix[i - 1][j] + 1)); // deletion
37049               }
37050             }
37051           }
37052
37053           return matrix[b.length][a.length];
37054         } // a d3.mouse-alike which
37055         // 1. Only works on HTML elements, not SVG
37056         // 2. Does not cause style recalculation
37057
37058         function utilFastMouse(container) {
37059           var rect = container.getBoundingClientRect();
37060           var rectLeft = rect.left;
37061           var rectTop = rect.top;
37062           var clientLeft = +container.clientLeft;
37063           var clientTop = +container.clientTop;
37064           return function (e) {
37065             return [e.clientX - rectLeft - clientLeft, e.clientY - rectTop - clientTop];
37066           };
37067         }
37068         function utilAsyncMap(inputs, func, callback) {
37069           var remaining = inputs.length;
37070           var results = [];
37071           var errors = [];
37072           inputs.forEach(function (d, i) {
37073             func(d, function done(err, data) {
37074               errors[i] = err;
37075               results[i] = data;
37076               remaining--;
37077               if (!remaining) callback(errors, results);
37078             });
37079           });
37080         } // wraps an index to an interval [0..length-1]
37081
37082         function utilWrap(index, length) {
37083           if (index < 0) {
37084             index += Math.ceil(-index / length) * length;
37085           }
37086
37087           return index % length;
37088         }
37089         /**
37090          * a replacement for functor
37091          *
37092          * @param {*} value any value
37093          * @returns {Function} a function that returns that value or the value if it's a function
37094          */
37095
37096         function utilFunctor(value) {
37097           if (typeof value === 'function') return value;
37098           return function () {
37099             return value;
37100           };
37101         }
37102         function utilNoAuto(selection) {
37103           var isText = selection.size() && selection.node().tagName.toLowerCase() === 'textarea';
37104           return selection // assign 'new-password' even for non-password fields to prevent browsers (Chrome) ignoring 'off'
37105           .attr('autocomplete', 'new-password').attr('autocorrect', 'off').attr('autocapitalize', 'off').attr('spellcheck', isText ? 'true' : 'false');
37106         } // https://stackoverflow.com/questions/194846/is-there-any-kind-of-hash-code-function-in-javascript
37107         // https://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/
37108
37109         function utilHashcode(str) {
37110           var hash = 0;
37111
37112           if (str.length === 0) {
37113             return hash;
37114           }
37115
37116           for (var i = 0; i < str.length; i++) {
37117             var _char = str.charCodeAt(i);
37118
37119             hash = (hash << 5) - hash + _char;
37120             hash = hash & hash; // Convert to 32bit integer
37121           }
37122
37123           return hash;
37124         } // Returns version of `str` with all runs of special characters replaced by `_`;
37125         // suitable for HTML ids, classes, selectors, etc.
37126
37127         function utilSafeClassName(str) {
37128           return str.toLowerCase().replace(/[^a-z0-9]+/g, '_');
37129         } // Returns string based on `val` that is highly unlikely to collide with an id
37130         // used previously or that's present elsewhere in the document. Useful for preventing
37131         // browser-provided autofills or when embedding iD on pages with unknown elements.
37132
37133         function utilUniqueDomId(val) {
37134           return 'ideditor-' + utilSafeClassName(val.toString()) + '-' + new Date().getTime().toString();
37135         } // Returns the length of `str` in unicode characters. This can be less than
37136         // `String.length()` since a single unicode character can be composed of multiple
37137         // JavaScript UTF-16 code units.
37138
37139         function utilUnicodeCharsCount(str) {
37140           // Native ES2015 implementations of `Array.from` split strings into unicode characters
37141           return Array.from(str).length;
37142         } // Returns a new string representing `str` cut from its start to `limit` length
37143         // in unicode characters. Note that this runs the risk of splitting graphemes.
37144
37145         function utilUnicodeCharsTruncated(str, limit) {
37146           return Array.from(str).slice(0, limit).join('');
37147         }
37148
37149         function toNumericID(id) {
37150           var match = id.match(/^[cnwr](-?\d+)$/);
37151
37152           if (match) {
37153             return parseInt(match[1], 10);
37154           }
37155
37156           return NaN;
37157         }
37158
37159         function compareNumericIDs(left, right) {
37160           if (isNaN(left) && isNaN(right)) return -1;
37161           if (isNaN(left)) return 1;
37162           if (isNaN(right)) return -1;
37163           if (Math.sign(left) !== Math.sign(right)) return -Math.sign(left);
37164           if (Math.sign(left) < 0) return Math.sign(right - left);
37165           return Math.sign(left - right);
37166         } // Returns -1 if the first parameter ID is older than the second,
37167         // 1 if the second parameter is older, 0 if they are the same.
37168         // If both IDs are test IDs, the function returns -1.
37169
37170
37171         function utilCompareIDs(left, right) {
37172           return compareNumericIDs(toNumericID(left), toNumericID(right));
37173         } // Returns the chronologically oldest ID in the list.
37174         // Database IDs (with positive numbers) before editor ones (with negative numbers).
37175         // Among each category, the closest number to 0 is the oldest.
37176         // Test IDs (any string that does not conform to OSM's ID scheme) are taken last.
37177
37178         function utilOldestID(ids) {
37179           if (ids.length === 0) {
37180             return undefined;
37181           }
37182
37183           var oldestIDIndex = 0;
37184           var oldestID = toNumericID(ids[0]);
37185
37186           for (var i = 1; i < ids.length; i++) {
37187             var num = toNumericID(ids[i]);
37188
37189             if (compareNumericIDs(oldestID, num) === 1) {
37190               oldestIDIndex = i;
37191               oldestID = num;
37192             }
37193           }
37194
37195           return ids[oldestIDIndex];
37196         }
37197
37198         function osmEntity(attrs) {
37199           // For prototypal inheritance.
37200           if (this instanceof osmEntity) return; // Create the appropriate subtype.
37201
37202           if (attrs && attrs.type) {
37203             return osmEntity[attrs.type].apply(this, arguments);
37204           } else if (attrs && attrs.id) {
37205             return osmEntity[osmEntity.id.type(attrs.id)].apply(this, arguments);
37206           } // Initialize a generic Entity (used only in tests).
37207
37208
37209           return new osmEntity().initialize(arguments);
37210         }
37211
37212         osmEntity.id = function (type) {
37213           return osmEntity.id.fromOSM(type, osmEntity.id.next[type]--);
37214         };
37215
37216         osmEntity.id.next = {
37217           changeset: -1,
37218           node: -1,
37219           way: -1,
37220           relation: -1
37221         };
37222
37223         osmEntity.id.fromOSM = function (type, id) {
37224           return type[0] + id;
37225         };
37226
37227         osmEntity.id.toOSM = function (id) {
37228           var match = id.match(/^[cnwr](-?\d+)$/);
37229
37230           if (match) {
37231             return match[1];
37232           }
37233
37234           return '';
37235         };
37236
37237         osmEntity.id.type = function (id) {
37238           return {
37239             'c': 'changeset',
37240             'n': 'node',
37241             'w': 'way',
37242             'r': 'relation'
37243           }[id[0]];
37244         }; // A function suitable for use as the second argument to d3.selection#data().
37245
37246
37247         osmEntity.key = function (entity) {
37248           return entity.id + 'v' + (entity.v || 0);
37249         };
37250
37251         var _deprecatedTagValuesByKey;
37252
37253         osmEntity.deprecatedTagValuesByKey = function (dataDeprecated) {
37254           if (!_deprecatedTagValuesByKey) {
37255             _deprecatedTagValuesByKey = {};
37256             dataDeprecated.forEach(function (d) {
37257               var oldKeys = Object.keys(d.old);
37258
37259               if (oldKeys.length === 1) {
37260                 var oldKey = oldKeys[0];
37261                 var oldValue = d.old[oldKey];
37262
37263                 if (oldValue !== '*') {
37264                   if (!_deprecatedTagValuesByKey[oldKey]) {
37265                     _deprecatedTagValuesByKey[oldKey] = [oldValue];
37266                   } else {
37267                     _deprecatedTagValuesByKey[oldKey].push(oldValue);
37268                   }
37269                 }
37270               }
37271             });
37272           }
37273
37274           return _deprecatedTagValuesByKey;
37275         };
37276
37277         osmEntity.prototype = {
37278           tags: {},
37279           initialize: function initialize(sources) {
37280             for (var i = 0; i < sources.length; ++i) {
37281               var source = sources[i];
37282
37283               for (var prop in source) {
37284                 if (Object.prototype.hasOwnProperty.call(source, prop)) {
37285                   if (source[prop] === undefined) {
37286                     delete this[prop];
37287                   } else {
37288                     this[prop] = source[prop];
37289                   }
37290                 }
37291               }
37292             }
37293
37294             if (!this.id && this.type) {
37295               this.id = osmEntity.id(this.type);
37296             }
37297
37298             if (!this.hasOwnProperty('visible')) {
37299               this.visible = true;
37300             }
37301
37302             if (debug) {
37303               Object.freeze(this);
37304               Object.freeze(this.tags);
37305               if (this.loc) Object.freeze(this.loc);
37306               if (this.nodes) Object.freeze(this.nodes);
37307               if (this.members) Object.freeze(this.members);
37308             }
37309
37310             return this;
37311           },
37312           copy: function copy(resolver, copies) {
37313             if (copies[this.id]) return copies[this.id];
37314             var copy = osmEntity(this, {
37315               id: undefined,
37316               user: undefined,
37317               version: undefined
37318             });
37319             copies[this.id] = copy;
37320             return copy;
37321           },
37322           osmId: function osmId() {
37323             return osmEntity.id.toOSM(this.id);
37324           },
37325           isNew: function isNew() {
37326             var osmId = osmEntity.id.toOSM(this.id);
37327             return osmId.length === 0 || osmId[0] === '-';
37328           },
37329           update: function update(attrs) {
37330             return osmEntity(this, attrs, {
37331               v: 1 + (this.v || 0)
37332             });
37333           },
37334           mergeTags: function mergeTags(tags) {
37335             var merged = Object.assign({}, this.tags); // shallow copy
37336
37337             var changed = false;
37338
37339             for (var k in tags) {
37340               var t1 = merged[k];
37341               var t2 = tags[k];
37342
37343               if (!t1) {
37344                 changed = true;
37345                 merged[k] = t2;
37346               } else if (t1 !== t2) {
37347                 changed = true;
37348                 merged[k] = utilUnicodeCharsTruncated(utilArrayUnion(t1.split(/;\s*/), t2.split(/;\s*/)).join(';'), 255 // avoid exceeding character limit; see also services/osm.js -> maxCharsForTagValue()
37349                 );
37350               }
37351             }
37352
37353             return changed ? this.update({
37354               tags: merged
37355             }) : this;
37356           },
37357           intersects: function intersects(extent, resolver) {
37358             return this.extent(resolver).intersects(extent);
37359           },
37360           hasNonGeometryTags: function hasNonGeometryTags() {
37361             return Object.keys(this.tags).some(function (k) {
37362               return k !== 'area';
37363             });
37364           },
37365           hasParentRelations: function hasParentRelations(resolver) {
37366             return resolver.parentRelations(this).length > 0;
37367           },
37368           hasInterestingTags: function hasInterestingTags() {
37369             return Object.keys(this.tags).some(osmIsInterestingTag);
37370           },
37371           isHighwayIntersection: function isHighwayIntersection() {
37372             return false;
37373           },
37374           isDegenerate: function isDegenerate() {
37375             return true;
37376           },
37377           deprecatedTags: function deprecatedTags(dataDeprecated) {
37378             var tags = this.tags; // if there are no tags, none can be deprecated
37379
37380             if (Object.keys(tags).length === 0) return [];
37381             var deprecated = [];
37382             dataDeprecated.forEach(function (d) {
37383               var oldKeys = Object.keys(d.old);
37384
37385               if (d.replace) {
37386                 var hasExistingValues = Object.keys(d.replace).some(function (replaceKey) {
37387                   if (!tags[replaceKey] || d.old[replaceKey]) return false;
37388                   var replaceValue = d.replace[replaceKey];
37389                   if (replaceValue === '*') return false;
37390                   if (replaceValue === tags[replaceKey]) return false;
37391                   return true;
37392                 }); // don't flag deprecated tags if the upgrade path would overwrite existing data - #7843
37393
37394                 if (hasExistingValues) return;
37395               }
37396
37397               var matchesDeprecatedTags = oldKeys.every(function (oldKey) {
37398                 if (!tags[oldKey]) return false;
37399                 if (d.old[oldKey] === '*') return true;
37400                 if (d.old[oldKey] === tags[oldKey]) return true;
37401                 var vals = tags[oldKey].split(';').filter(Boolean);
37402
37403                 if (vals.length === 0) {
37404                   return false;
37405                 } else if (vals.length > 1) {
37406                   return vals.indexOf(d.old[oldKey]) !== -1;
37407                 } else {
37408                   if (tags[oldKey] === d.old[oldKey]) {
37409                     if (d.replace && d.old[oldKey] === d.replace[oldKey]) {
37410                       var replaceKeys = Object.keys(d.replace);
37411                       return !replaceKeys.every(function (replaceKey) {
37412                         return tags[replaceKey] === d.replace[replaceKey];
37413                       });
37414                     } else {
37415                       return true;
37416                     }
37417                   }
37418                 }
37419
37420                 return false;
37421               });
37422
37423               if (matchesDeprecatedTags) {
37424                 deprecated.push(d);
37425               }
37426             });
37427             return deprecated;
37428           }
37429         };
37430
37431         function osmLanes(entity) {
37432           if (entity.type !== 'way') return null;
37433           if (!entity.tags.highway) return null;
37434           var tags = entity.tags;
37435           var isOneWay = entity.isOneWay();
37436           var laneCount = getLaneCount(tags, isOneWay);
37437           var maxspeed = parseMaxspeed(tags);
37438           var laneDirections = parseLaneDirections(tags, isOneWay, laneCount);
37439           var forward = laneDirections.forward;
37440           var backward = laneDirections.backward;
37441           var bothways = laneDirections.bothways; // parse the piped string 'x|y|z' format
37442
37443           var turnLanes = {};
37444           turnLanes.unspecified = parseTurnLanes(tags['turn:lanes']);
37445           turnLanes.forward = parseTurnLanes(tags['turn:lanes:forward']);
37446           turnLanes.backward = parseTurnLanes(tags['turn:lanes:backward']);
37447           var maxspeedLanes = {};
37448           maxspeedLanes.unspecified = parseMaxspeedLanes(tags['maxspeed:lanes'], maxspeed);
37449           maxspeedLanes.forward = parseMaxspeedLanes(tags['maxspeed:lanes:forward'], maxspeed);
37450           maxspeedLanes.backward = parseMaxspeedLanes(tags['maxspeed:lanes:backward'], maxspeed);
37451           var psvLanes = {};
37452           psvLanes.unspecified = parseMiscLanes(tags['psv:lanes']);
37453           psvLanes.forward = parseMiscLanes(tags['psv:lanes:forward']);
37454           psvLanes.backward = parseMiscLanes(tags['psv:lanes:backward']);
37455           var busLanes = {};
37456           busLanes.unspecified = parseMiscLanes(tags['bus:lanes']);
37457           busLanes.forward = parseMiscLanes(tags['bus:lanes:forward']);
37458           busLanes.backward = parseMiscLanes(tags['bus:lanes:backward']);
37459           var taxiLanes = {};
37460           taxiLanes.unspecified = parseMiscLanes(tags['taxi:lanes']);
37461           taxiLanes.forward = parseMiscLanes(tags['taxi:lanes:forward']);
37462           taxiLanes.backward = parseMiscLanes(tags['taxi:lanes:backward']);
37463           var hovLanes = {};
37464           hovLanes.unspecified = parseMiscLanes(tags['hov:lanes']);
37465           hovLanes.forward = parseMiscLanes(tags['hov:lanes:forward']);
37466           hovLanes.backward = parseMiscLanes(tags['hov:lanes:backward']);
37467           var hgvLanes = {};
37468           hgvLanes.unspecified = parseMiscLanes(tags['hgv:lanes']);
37469           hgvLanes.forward = parseMiscLanes(tags['hgv:lanes:forward']);
37470           hgvLanes.backward = parseMiscLanes(tags['hgv:lanes:backward']);
37471           var bicyclewayLanes = {};
37472           bicyclewayLanes.unspecified = parseBicycleWay(tags['bicycleway:lanes']);
37473           bicyclewayLanes.forward = parseBicycleWay(tags['bicycleway:lanes:forward']);
37474           bicyclewayLanes.backward = parseBicycleWay(tags['bicycleway:lanes:backward']);
37475           var lanesObj = {
37476             forward: [],
37477             backward: [],
37478             unspecified: []
37479           }; // map forward/backward/unspecified of each lane type to lanesObj
37480
37481           mapToLanesObj(lanesObj, turnLanes, 'turnLane');
37482           mapToLanesObj(lanesObj, maxspeedLanes, 'maxspeed');
37483           mapToLanesObj(lanesObj, psvLanes, 'psv');
37484           mapToLanesObj(lanesObj, busLanes, 'bus');
37485           mapToLanesObj(lanesObj, taxiLanes, 'taxi');
37486           mapToLanesObj(lanesObj, hovLanes, 'hov');
37487           mapToLanesObj(lanesObj, hgvLanes, 'hgv');
37488           mapToLanesObj(lanesObj, bicyclewayLanes, 'bicycleway');
37489           return {
37490             metadata: {
37491               count: laneCount,
37492               oneway: isOneWay,
37493               forward: forward,
37494               backward: backward,
37495               bothways: bothways,
37496               turnLanes: turnLanes,
37497               maxspeed: maxspeed,
37498               maxspeedLanes: maxspeedLanes,
37499               psvLanes: psvLanes,
37500               busLanes: busLanes,
37501               taxiLanes: taxiLanes,
37502               hovLanes: hovLanes,
37503               hgvLanes: hgvLanes,
37504               bicyclewayLanes: bicyclewayLanes
37505             },
37506             lanes: lanesObj
37507           };
37508         }
37509
37510         function getLaneCount(tags, isOneWay) {
37511           var count;
37512
37513           if (tags.lanes) {
37514             count = parseInt(tags.lanes, 10);
37515
37516             if (count > 0) {
37517               return count;
37518             }
37519           }
37520
37521           switch (tags.highway) {
37522             case 'trunk':
37523             case 'motorway':
37524               count = isOneWay ? 2 : 4;
37525               break;
37526
37527             default:
37528               count = isOneWay ? 1 : 2;
37529               break;
37530           }
37531
37532           return count;
37533         }
37534
37535         function parseMaxspeed(tags) {
37536           var maxspeed = tags.maxspeed;
37537           if (!maxspeed) return;
37538           var maxspeedRegex = /^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/;
37539           if (!maxspeedRegex.test(maxspeed)) return;
37540           return parseInt(maxspeed, 10);
37541         }
37542
37543         function parseLaneDirections(tags, isOneWay, laneCount) {
37544           var forward = parseInt(tags['lanes:forward'], 10);
37545           var backward = parseInt(tags['lanes:backward'], 10);
37546           var bothways = parseInt(tags['lanes:both_ways'], 10) > 0 ? 1 : 0;
37547
37548           if (parseInt(tags.oneway, 10) === -1) {
37549             forward = 0;
37550             bothways = 0;
37551             backward = laneCount;
37552           } else if (isOneWay) {
37553             forward = laneCount;
37554             bothways = 0;
37555             backward = 0;
37556           } else if (isNaN(forward) && isNaN(backward)) {
37557             backward = Math.floor((laneCount - bothways) / 2);
37558             forward = laneCount - bothways - backward;
37559           } else if (isNaN(forward)) {
37560             if (backward > laneCount - bothways) {
37561               backward = laneCount - bothways;
37562             }
37563
37564             forward = laneCount - bothways - backward;
37565           } else if (isNaN(backward)) {
37566             if (forward > laneCount - bothways) {
37567               forward = laneCount - bothways;
37568             }
37569
37570             backward = laneCount - bothways - forward;
37571           }
37572
37573           return {
37574             forward: forward,
37575             backward: backward,
37576             bothways: bothways
37577           };
37578         }
37579
37580         function parseTurnLanes(tag) {
37581           if (!tag) return;
37582           var validValues = ['left', 'slight_left', 'sharp_left', 'through', 'right', 'slight_right', 'sharp_right', 'reverse', 'merge_to_left', 'merge_to_right', 'none'];
37583           return tag.split('|').map(function (s) {
37584             if (s === '') s = 'none';
37585             return s.split(';').map(function (d) {
37586               return validValues.indexOf(d) === -1 ? 'unknown' : d;
37587             });
37588           });
37589         }
37590
37591         function parseMaxspeedLanes(tag, maxspeed) {
37592           if (!tag) return;
37593           return tag.split('|').map(function (s) {
37594             if (s === 'none') return s;
37595             var m = parseInt(s, 10);
37596             if (s === '' || m === maxspeed) return null;
37597             return isNaN(m) ? 'unknown' : m;
37598           });
37599         }
37600
37601         function parseMiscLanes(tag) {
37602           if (!tag) return;
37603           var validValues = ['yes', 'no', 'designated'];
37604           return tag.split('|').map(function (s) {
37605             if (s === '') s = 'no';
37606             return validValues.indexOf(s) === -1 ? 'unknown' : s;
37607           });
37608         }
37609
37610         function parseBicycleWay(tag) {
37611           if (!tag) return;
37612           var validValues = ['yes', 'no', 'designated', 'lane'];
37613           return tag.split('|').map(function (s) {
37614             if (s === '') s = 'no';
37615             return validValues.indexOf(s) === -1 ? 'unknown' : s;
37616           });
37617         }
37618
37619         function mapToLanesObj(lanesObj, data, key) {
37620           if (data.forward) {
37621             data.forward.forEach(function (l, i) {
37622               if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
37623               lanesObj.forward[i][key] = l;
37624             });
37625           }
37626
37627           if (data.backward) {
37628             data.backward.forEach(function (l, i) {
37629               if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
37630               lanesObj.backward[i][key] = l;
37631             });
37632           }
37633
37634           if (data.unspecified) {
37635             data.unspecified.forEach(function (l, i) {
37636               if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
37637               lanesObj.unspecified[i][key] = l;
37638             });
37639           }
37640         }
37641
37642         function osmWay() {
37643           if (!(this instanceof osmWay)) {
37644             return new osmWay().initialize(arguments);
37645           } else if (arguments.length) {
37646             this.initialize(arguments);
37647           }
37648         }
37649         osmEntity.way = osmWay;
37650         osmWay.prototype = Object.create(osmEntity.prototype);
37651         Object.assign(osmWay.prototype, {
37652           type: 'way',
37653           nodes: [],
37654           copy: function copy(resolver, copies) {
37655             if (copies[this.id]) return copies[this.id];
37656             var copy = osmEntity.prototype.copy.call(this, resolver, copies);
37657             var nodes = this.nodes.map(function (id) {
37658               return resolver.entity(id).copy(resolver, copies).id;
37659             });
37660             copy = copy.update({
37661               nodes: nodes
37662             });
37663             copies[this.id] = copy;
37664             return copy;
37665           },
37666           extent: function extent(resolver) {
37667             return resolver["transient"](this, 'extent', function () {
37668               var extent = geoExtent();
37669
37670               for (var i = 0; i < this.nodes.length; i++) {
37671                 var node = resolver.hasEntity(this.nodes[i]);
37672
37673                 if (node) {
37674                   extent._extend(node.extent());
37675                 }
37676               }
37677
37678               return extent;
37679             });
37680           },
37681           first: function first() {
37682             return this.nodes[0];
37683           },
37684           last: function last() {
37685             return this.nodes[this.nodes.length - 1];
37686           },
37687           contains: function contains(node) {
37688             return this.nodes.indexOf(node) >= 0;
37689           },
37690           affix: function affix(node) {
37691             if (this.nodes[0] === node) return 'prefix';
37692             if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
37693           },
37694           layer: function layer() {
37695             // explicit layer tag, clamp between -10, 10..
37696             if (isFinite(this.tags.layer)) {
37697               return Math.max(-10, Math.min(+this.tags.layer, 10));
37698             } // implied layer tag..
37699
37700
37701             if (this.tags.covered === 'yes') return -1;
37702             if (this.tags.location === 'overground') return 1;
37703             if (this.tags.location === 'underground') return -1;
37704             if (this.tags.location === 'underwater') return -10;
37705             if (this.tags.power === 'line') return 10;
37706             if (this.tags.power === 'minor_line') return 10;
37707             if (this.tags.aerialway) return 10;
37708             if (this.tags.bridge) return 1;
37709             if (this.tags.cutting) return -1;
37710             if (this.tags.tunnel) return -1;
37711             if (this.tags.waterway) return -1;
37712             if (this.tags.man_made === 'pipeline') return -10;
37713             if (this.tags.boundary) return -10;
37714             return 0;
37715           },
37716           // the approximate width of the line based on its tags except its `width` tag
37717           impliedLineWidthMeters: function impliedLineWidthMeters() {
37718             var averageWidths = {
37719               highway: {
37720                 // width is for single lane
37721                 motorway: 5,
37722                 motorway_link: 5,
37723                 trunk: 4.5,
37724                 trunk_link: 4.5,
37725                 primary: 4,
37726                 secondary: 4,
37727                 tertiary: 4,
37728                 primary_link: 4,
37729                 secondary_link: 4,
37730                 tertiary_link: 4,
37731                 unclassified: 4,
37732                 road: 4,
37733                 living_street: 4,
37734                 bus_guideway: 4,
37735                 pedestrian: 4,
37736                 residential: 3.5,
37737                 service: 3.5,
37738                 track: 3,
37739                 cycleway: 2.5,
37740                 bridleway: 2,
37741                 corridor: 2,
37742                 steps: 2,
37743                 path: 1.5,
37744                 footway: 1.5
37745               },
37746               railway: {
37747                 // width includes ties and rail bed, not just track gauge
37748                 rail: 2.5,
37749                 light_rail: 2.5,
37750                 tram: 2.5,
37751                 subway: 2.5,
37752                 monorail: 2.5,
37753                 funicular: 2.5,
37754                 disused: 2.5,
37755                 preserved: 2.5,
37756                 miniature: 1.5,
37757                 narrow_gauge: 1.5
37758               },
37759               waterway: {
37760                 river: 50,
37761                 canal: 25,
37762                 stream: 5,
37763                 tidal_channel: 5,
37764                 fish_pass: 2.5,
37765                 drain: 2.5,
37766                 ditch: 1.5
37767               }
37768             };
37769
37770             for (var key in averageWidths) {
37771               if (this.tags[key] && averageWidths[key][this.tags[key]]) {
37772                 var width = averageWidths[key][this.tags[key]];
37773
37774                 if (key === 'highway') {
37775                   var laneCount = this.tags.lanes && parseInt(this.tags.lanes, 10);
37776                   if (!laneCount) laneCount = this.isOneWay() ? 1 : 2;
37777                   return width * laneCount;
37778                 }
37779
37780                 return width;
37781               }
37782             }
37783
37784             return null;
37785           },
37786           isOneWay: function isOneWay() {
37787             // explicit oneway tag..
37788             var values = {
37789               'yes': true,
37790               '1': true,
37791               '-1': true,
37792               'reversible': true,
37793               'alternating': true,
37794               'no': false,
37795               '0': false
37796             };
37797
37798             if (values[this.tags.oneway] !== undefined) {
37799               return values[this.tags.oneway];
37800             } // implied oneway tag..
37801
37802
37803             for (var key in this.tags) {
37804               if (key in osmOneWayTags && this.tags[key] in osmOneWayTags[key]) {
37805                 return true;
37806               }
37807             }
37808
37809             return false;
37810           },
37811           // Some identifier for tag that implies that this way is "sided",
37812           // i.e. the right side is the 'inside' (e.g. the right side of a
37813           // natural=cliff is lower).
37814           sidednessIdentifier: function sidednessIdentifier() {
37815             for (var key in this.tags) {
37816               var value = this.tags[key];
37817
37818               if (key in osmRightSideIsInsideTags && value in osmRightSideIsInsideTags[key]) {
37819                 if (osmRightSideIsInsideTags[key][value] === true) {
37820                   return key;
37821                 } else {
37822                   // if the map's value is something other than a
37823                   // literal true, we should use it so we can
37824                   // special case some keys (e.g. natural=coastline
37825                   // is handled differently to other naturals).
37826                   return osmRightSideIsInsideTags[key][value];
37827                 }
37828               }
37829             }
37830
37831             return null;
37832           },
37833           isSided: function isSided() {
37834             if (this.tags.two_sided === 'yes') {
37835               return false;
37836             }
37837
37838             return this.sidednessIdentifier() !== null;
37839           },
37840           lanes: function lanes() {
37841             return osmLanes(this);
37842           },
37843           isClosed: function isClosed() {
37844             return this.nodes.length > 1 && this.first() === this.last();
37845           },
37846           isConvex: function isConvex(resolver) {
37847             if (!this.isClosed() || this.isDegenerate()) return null;
37848             var nodes = utilArrayUniq(resolver.childNodes(this));
37849             var coords = nodes.map(function (n) {
37850               return n.loc;
37851             });
37852             var curr = 0;
37853             var prev = 0;
37854
37855             for (var i = 0; i < coords.length; i++) {
37856               var o = coords[(i + 1) % coords.length];
37857               var a = coords[i];
37858               var b = coords[(i + 2) % coords.length];
37859               var res = geoVecCross(a, b, o);
37860               curr = res > 0 ? 1 : res < 0 ? -1 : 0;
37861
37862               if (curr === 0) {
37863                 continue;
37864               } else if (prev && curr !== prev) {
37865                 return false;
37866               }
37867
37868               prev = curr;
37869             }
37870
37871             return true;
37872           },
37873           // returns an object with the tag that implies this is an area, if any
37874           tagSuggestingArea: function tagSuggestingArea() {
37875             return osmTagSuggestingArea(this.tags);
37876           },
37877           isArea: function isArea() {
37878             if (this.tags.area === 'yes') return true;
37879             if (!this.isClosed() || this.tags.area === 'no') return false;
37880             return this.tagSuggestingArea() !== null;
37881           },
37882           isDegenerate: function isDegenerate() {
37883             return new Set(this.nodes).size < (this.isArea() ? 3 : 2);
37884           },
37885           areAdjacent: function areAdjacent(n1, n2) {
37886             for (var i = 0; i < this.nodes.length; i++) {
37887               if (this.nodes[i] === n1) {
37888                 if (this.nodes[i - 1] === n2) return true;
37889                 if (this.nodes[i + 1] === n2) return true;
37890               }
37891             }
37892
37893             return false;
37894           },
37895           geometry: function geometry(graph) {
37896             return graph["transient"](this, 'geometry', function () {
37897               return this.isArea() ? 'area' : 'line';
37898             });
37899           },
37900           // returns an array of objects representing the segments between the nodes in this way
37901           segments: function segments(graph) {
37902             function segmentExtent(graph) {
37903               var n1 = graph.hasEntity(this.nodes[0]);
37904               var n2 = graph.hasEntity(this.nodes[1]);
37905               return n1 && n2 && geoExtent([[Math.min(n1.loc[0], n2.loc[0]), Math.min(n1.loc[1], n2.loc[1])], [Math.max(n1.loc[0], n2.loc[0]), Math.max(n1.loc[1], n2.loc[1])]]);
37906             }
37907
37908             return graph["transient"](this, 'segments', function () {
37909               var segments = [];
37910
37911               for (var i = 0; i < this.nodes.length - 1; i++) {
37912                 segments.push({
37913                   id: this.id + '-' + i,
37914                   wayId: this.id,
37915                   index: i,
37916                   nodes: [this.nodes[i], this.nodes[i + 1]],
37917                   extent: segmentExtent
37918                 });
37919               }
37920
37921               return segments;
37922             });
37923           },
37924           // If this way is not closed, append the beginning node to the end of the nodelist to close it.
37925           close: function close() {
37926             if (this.isClosed() || !this.nodes.length) return this;
37927             var nodes = this.nodes.slice();
37928             nodes = nodes.filter(noRepeatNodes);
37929             nodes.push(nodes[0]);
37930             return this.update({
37931               nodes: nodes
37932             });
37933           },
37934           // If this way is closed, remove any connector nodes from the end of the nodelist to unclose it.
37935           unclose: function unclose() {
37936             if (!this.isClosed()) return this;
37937             var nodes = this.nodes.slice();
37938             var connector = this.first();
37939             var i = nodes.length - 1; // remove trailing connectors..
37940
37941             while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
37942               nodes.splice(i, 1);
37943               i = nodes.length - 1;
37944             }
37945
37946             nodes = nodes.filter(noRepeatNodes);
37947             return this.update({
37948               nodes: nodes
37949             });
37950           },
37951           // Adds a node (id) in front of the node which is currently at position index.
37952           // If index is undefined, the node will be added to the end of the way for linear ways,
37953           //   or just before the final connecting node for circular ways.
37954           // Consecutive duplicates are eliminated including existing ones.
37955           // Circularity is always preserved when adding a node.
37956           addNode: function addNode(id, index) {
37957             var nodes = this.nodes.slice();
37958             var isClosed = this.isClosed();
37959             var max = isClosed ? nodes.length - 1 : nodes.length;
37960
37961             if (index === undefined) {
37962               index = max;
37963             }
37964
37965             if (index < 0 || index > max) {
37966               throw new RangeError('index ' + index + ' out of range 0..' + max);
37967             } // If this is a closed way, remove all connector nodes except the first one
37968             // (there may be duplicates) and adjust index if necessary..
37969
37970
37971             if (isClosed) {
37972               var connector = this.first(); // leading connectors..
37973
37974               var i = 1;
37975
37976               while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
37977                 nodes.splice(i, 1);
37978                 if (index > i) index--;
37979               } // trailing connectors..
37980
37981
37982               i = nodes.length - 1;
37983
37984               while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
37985                 nodes.splice(i, 1);
37986                 if (index > i) index--;
37987                 i = nodes.length - 1;
37988               }
37989             }
37990
37991             nodes.splice(index, 0, id);
37992             nodes = nodes.filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
37993
37994             if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
37995               nodes.push(nodes[0]);
37996             }
37997
37998             return this.update({
37999               nodes: nodes
38000             });
38001           },
38002           // Replaces the node which is currently at position index with the given node (id).
38003           // Consecutive duplicates are eliminated including existing ones.
38004           // Circularity is preserved when updating a node.
38005           updateNode: function updateNode(id, index) {
38006             var nodes = this.nodes.slice();
38007             var isClosed = this.isClosed();
38008             var max = nodes.length - 1;
38009
38010             if (index === undefined || index < 0 || index > max) {
38011               throw new RangeError('index ' + index + ' out of range 0..' + max);
38012             } // If this is a closed way, remove all connector nodes except the first one
38013             // (there may be duplicates) and adjust index if necessary..
38014
38015
38016             if (isClosed) {
38017               var connector = this.first(); // leading connectors..
38018
38019               var i = 1;
38020
38021               while (i < nodes.length && nodes.length > 2 && nodes[i] === connector) {
38022                 nodes.splice(i, 1);
38023                 if (index > i) index--;
38024               } // trailing connectors..
38025
38026
38027               i = nodes.length - 1;
38028
38029               while (i > 0 && nodes.length > 1 && nodes[i] === connector) {
38030                 nodes.splice(i, 1);
38031                 if (index === i) index = 0; // update leading connector instead
38032
38033                 i = nodes.length - 1;
38034               }
38035             }
38036
38037             nodes.splice(index, 1, id);
38038             nodes = nodes.filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
38039
38040             if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
38041               nodes.push(nodes[0]);
38042             }
38043
38044             return this.update({
38045               nodes: nodes
38046             });
38047           },
38048           // Replaces each occurrence of node id needle with replacement.
38049           // Consecutive duplicates are eliminated including existing ones.
38050           // Circularity is preserved.
38051           replaceNode: function replaceNode(needleID, replacementID) {
38052             var nodes = this.nodes.slice();
38053             var isClosed = this.isClosed();
38054
38055             for (var i = 0; i < nodes.length; i++) {
38056               if (nodes[i] === needleID) {
38057                 nodes[i] = replacementID;
38058               }
38059             }
38060
38061             nodes = nodes.filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
38062
38063             if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
38064               nodes.push(nodes[0]);
38065             }
38066
38067             return this.update({
38068               nodes: nodes
38069             });
38070           },
38071           // Removes each occurrence of node id.
38072           // Consecutive duplicates are eliminated including existing ones.
38073           // Circularity is preserved.
38074           removeNode: function removeNode(id) {
38075             var nodes = this.nodes.slice();
38076             var isClosed = this.isClosed();
38077             nodes = nodes.filter(function (node) {
38078               return node !== id;
38079             }).filter(noRepeatNodes); // If the way was closed before, append a connector node to keep it closed..
38080
38081             if (isClosed && (nodes.length === 1 || nodes[0] !== nodes[nodes.length - 1])) {
38082               nodes.push(nodes[0]);
38083             }
38084
38085             return this.update({
38086               nodes: nodes
38087             });
38088           },
38089           asJXON: function asJXON(changeset_id) {
38090             var r = {
38091               way: {
38092                 '@id': this.osmId(),
38093                 '@version': this.version || 0,
38094                 nd: this.nodes.map(function (id) {
38095                   return {
38096                     keyAttributes: {
38097                       ref: osmEntity.id.toOSM(id)
38098                     }
38099                   };
38100                 }, this),
38101                 tag: Object.keys(this.tags).map(function (k) {
38102                   return {
38103                     keyAttributes: {
38104                       k: k,
38105                       v: this.tags[k]
38106                     }
38107                   };
38108                 }, this)
38109               }
38110             };
38111
38112             if (changeset_id) {
38113               r.way['@changeset'] = changeset_id;
38114             }
38115
38116             return r;
38117           },
38118           asGeoJSON: function asGeoJSON(resolver) {
38119             return resolver["transient"](this, 'GeoJSON', function () {
38120               var coordinates = resolver.childNodes(this).map(function (n) {
38121                 return n.loc;
38122               });
38123
38124               if (this.isArea() && this.isClosed()) {
38125                 return {
38126                   type: 'Polygon',
38127                   coordinates: [coordinates]
38128                 };
38129               } else {
38130                 return {
38131                   type: 'LineString',
38132                   coordinates: coordinates
38133                 };
38134               }
38135             });
38136           },
38137           area: function area(resolver) {
38138             return resolver["transient"](this, 'area', function () {
38139               var nodes = resolver.childNodes(this);
38140               var json = {
38141                 type: 'Polygon',
38142                 coordinates: [nodes.map(function (n) {
38143                   return n.loc;
38144                 })]
38145               };
38146
38147               if (!this.isClosed() && nodes.length) {
38148                 json.coordinates[0].push(nodes[0].loc);
38149               }
38150
38151               var area = d3_geoArea(json); // Heuristic for detecting counterclockwise winding order. Assumes
38152               // that OpenStreetMap polygons are not hemisphere-spanning.
38153
38154               if (area > 2 * Math.PI) {
38155                 json.coordinates[0] = json.coordinates[0].reverse();
38156                 area = d3_geoArea(json);
38157               }
38158
38159               return isNaN(area) ? 0 : area;
38160             });
38161           }
38162         }); // Filter function to eliminate consecutive duplicates.
38163
38164         function noRepeatNodes(node, i, arr) {
38165           return i === 0 || node !== arr[i - 1];
38166         }
38167
38168         //
38169         // 1. Relation tagged with `type=multipolygon` and no interesting tags.
38170         // 2. One and only one member with the `outer` role. Must be a way with interesting tags.
38171         // 3. No members without a role.
38172         //
38173         // Old multipolygons are no longer recommended but are still rendered as areas by iD.
38174
38175         function osmOldMultipolygonOuterMemberOfRelation(entity, graph) {
38176           if (entity.type !== 'relation' || !entity.isMultipolygon() || Object.keys(entity.tags).filter(osmIsInterestingTag).length > 1) {
38177             return false;
38178           }
38179
38180           var outerMember;
38181
38182           for (var memberIndex in entity.members) {
38183             var member = entity.members[memberIndex];
38184
38185             if (!member.role || member.role === 'outer') {
38186               if (outerMember) return false;
38187               if (member.type !== 'way') return false;
38188               if (!graph.hasEntity(member.id)) return false;
38189               outerMember = graph.entity(member.id);
38190
38191               if (Object.keys(outerMember.tags).filter(osmIsInterestingTag).length === 0) {
38192                 return false;
38193               }
38194             }
38195           }
38196
38197           return outerMember;
38198         } // For fixing up rendering of multipolygons with tags on the outer member.
38199         // https://github.com/openstreetmap/iD/issues/613
38200
38201         function osmIsOldMultipolygonOuterMember(entity, graph) {
38202           if (entity.type !== 'way' || Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0) {
38203             return false;
38204           }
38205
38206           var parents = graph.parentRelations(entity);
38207           if (parents.length !== 1) return false;
38208           var parent = parents[0];
38209
38210           if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) {
38211             return false;
38212           }
38213
38214           var members = parent.members,
38215               member;
38216
38217           for (var i = 0; i < members.length; i++) {
38218             member = members[i];
38219
38220             if (member.id === entity.id && member.role && member.role !== 'outer') {
38221               // Not outer member
38222               return false;
38223             }
38224
38225             if (member.id !== entity.id && (!member.role || member.role === 'outer')) {
38226               // Not a simple multipolygon
38227               return false;
38228             }
38229           }
38230
38231           return parent;
38232         }
38233         function osmOldMultipolygonOuterMember(entity, graph) {
38234           if (entity.type !== 'way') return false;
38235           var parents = graph.parentRelations(entity);
38236           if (parents.length !== 1) return false;
38237           var parent = parents[0];
38238
38239           if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1) {
38240             return false;
38241           }
38242
38243           var members = parent.members,
38244               member,
38245               outerMember;
38246
38247           for (var i = 0; i < members.length; i++) {
38248             member = members[i];
38249
38250             if (!member.role || member.role === 'outer') {
38251               if (outerMember) return false; // Not a simple multipolygon
38252
38253               outerMember = member;
38254             }
38255           }
38256
38257           if (!outerMember) return false;
38258           var outerEntity = graph.hasEntity(outerMember.id);
38259
38260           if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length) {
38261             return false;
38262           }
38263
38264           return outerEntity;
38265         } // Join `toJoin` array into sequences of connecting ways.
38266         // Segments which share identical start/end nodes will, as much as possible,
38267         // be connected with each other.
38268         //
38269         // The return value is a nested array. Each constituent array contains elements
38270         // of `toJoin` which have been determined to connect.
38271         //
38272         // Each consitituent array also has a `nodes` property whose value is an
38273         // ordered array of member nodes, with appropriate order reversal and
38274         // start/end coordinate de-duplication.
38275         //
38276         // Members of `toJoin` must have, at minimum, `type` and `id` properties.
38277         // Thus either an array of `osmWay`s or a relation member array may be used.
38278         //
38279         // If an member is an `osmWay`, its tags and childnodes may be reversed via
38280         // `actionReverse` in the output.
38281         //
38282         // The returned sequences array also has an `actions` array property, containing
38283         // any reversal actions that should be applied to the graph, should the calling
38284         // code attempt to actually join the given ways.
38285         //
38286         // Incomplete members (those for which `graph.hasEntity(element.id)` returns
38287         // false) and non-way members are ignored.
38288         //
38289
38290         function osmJoinWays(toJoin, graph) {
38291           function resolve(member) {
38292             return graph.childNodes(graph.entity(member.id));
38293           }
38294
38295           function reverse(item) {
38296             var action = actionReverse(item.id, {
38297               reverseOneway: true
38298             });
38299             sequences.actions.push(action);
38300             return item instanceof osmWay ? action(graph).entity(item.id) : item;
38301           } // make a copy containing only the items to join
38302
38303
38304           toJoin = toJoin.filter(function (member) {
38305             return member.type === 'way' && graph.hasEntity(member.id);
38306           }); // Are the things we are joining relation members or `osmWays`?
38307           // If `osmWays`, skip the "prefer a forward path" code below (see #4872)
38308
38309           var i;
38310           var joinAsMembers = true;
38311
38312           for (i = 0; i < toJoin.length; i++) {
38313             if (toJoin[i] instanceof osmWay) {
38314               joinAsMembers = false;
38315               break;
38316             }
38317           }
38318
38319           var sequences = [];
38320           sequences.actions = [];
38321
38322           while (toJoin.length) {
38323             // start a new sequence
38324             var item = toJoin.shift();
38325             var currWays = [item];
38326             var currNodes = resolve(item).slice(); // add to it
38327
38328             while (toJoin.length) {
38329               var start = currNodes[0];
38330               var end = currNodes[currNodes.length - 1];
38331               var fn = null;
38332               var nodes = null; // Find the next way/member to join.
38333
38334               for (i = 0; i < toJoin.length; i++) {
38335                 item = toJoin[i];
38336                 nodes = resolve(item); // (for member ordering only, not way ordering - see #4872)
38337                 // Strongly prefer to generate a forward path that preserves the order
38338                 // of the members array. For multipolygons and most relations, member
38339                 // order does not matter - but for routes, it does. (see #4589)
38340                 // If we started this sequence backwards (i.e. next member way attaches to
38341                 // the start node and not the end node), reverse the initial way before continuing.
38342
38343                 if (joinAsMembers && currWays.length === 1 && nodes[0] !== end && nodes[nodes.length - 1] !== end && (nodes[nodes.length - 1] === start || nodes[0] === start)) {
38344                   currWays[0] = reverse(currWays[0]);
38345                   currNodes.reverse();
38346                   start = currNodes[0];
38347                   end = currNodes[currNodes.length - 1];
38348                 }
38349
38350                 if (nodes[0] === end) {
38351                   fn = currNodes.push; // join to end
38352
38353                   nodes = nodes.slice(1);
38354                   break;
38355                 } else if (nodes[nodes.length - 1] === end) {
38356                   fn = currNodes.push; // join to end
38357
38358                   nodes = nodes.slice(0, -1).reverse();
38359                   item = reverse(item);
38360                   break;
38361                 } else if (nodes[nodes.length - 1] === start) {
38362                   fn = currNodes.unshift; // join to beginning
38363
38364                   nodes = nodes.slice(0, -1);
38365                   break;
38366                 } else if (nodes[0] === start) {
38367                   fn = currNodes.unshift; // join to beginning
38368
38369                   nodes = nodes.slice(1).reverse();
38370                   item = reverse(item);
38371                   break;
38372                 } else {
38373                   fn = nodes = null;
38374                 }
38375               }
38376
38377               if (!nodes) {
38378                 // couldn't find a joinable way/member
38379                 break;
38380               }
38381
38382               fn.apply(currWays, [item]);
38383               fn.apply(currNodes, nodes);
38384               toJoin.splice(i, 1);
38385             }
38386
38387             currWays.nodes = currNodes;
38388             sequences.push(currWays);
38389           }
38390
38391           return sequences;
38392         }
38393
38394         function actionAddMember(relationId, member, memberIndex, insertPair) {
38395           return function action(graph) {
38396             var relation = graph.entity(relationId); // There are some special rules for Public Transport v2 routes.
38397
38398             var isPTv2 = /stop|platform/.test(member.role);
38399
38400             if ((isNaN(memberIndex) || insertPair) && member.type === 'way' && !isPTv2) {
38401               // Try to perform sensible inserts based on how the ways join together
38402               graph = addWayMember(relation, graph);
38403             } else {
38404               // see https://wiki.openstreetmap.org/wiki/Public_transport#Service_routes
38405               // Stops and Platforms for PTv2 should be ordered first.
38406               // hack: We do not currently have the ability to place them in the exactly correct order.
38407               if (isPTv2 && isNaN(memberIndex)) {
38408                 memberIndex = 0;
38409               }
38410
38411               graph = graph.replace(relation.addMember(member, memberIndex));
38412             }
38413
38414             return graph;
38415           }; // Add a way member into the relation "wherever it makes sense".
38416           // In this situation we were not supplied a memberIndex.
38417
38418           function addWayMember(relation, graph) {
38419             var groups, tempWay, insertPairIsReversed, item, i, j, k; // remove PTv2 stops and platforms before doing anything.
38420
38421             var PTv2members = [];
38422             var members = [];
38423
38424             for (i = 0; i < relation.members.length; i++) {
38425               var m = relation.members[i];
38426
38427               if (/stop|platform/.test(m.role)) {
38428                 PTv2members.push(m);
38429               } else {
38430                 members.push(m);
38431               }
38432             }
38433
38434             relation = relation.update({
38435               members: members
38436             });
38437
38438             if (insertPair) {
38439               // We're adding a member that must stay paired with an existing member.
38440               // (This feature is used by `actionSplit`)
38441               //
38442               // This is tricky because the members may exist multiple times in the
38443               // member list, and with different A-B/B-A ordering and different roles.
38444               // (e.g. a bus route that loops out and back - #4589).
38445               //
38446               // Replace the existing member with a temporary way,
38447               // so that `osmJoinWays` can treat the pair like a single way.
38448               tempWay = osmWay({
38449                 id: 'wTemp',
38450                 nodes: insertPair.nodes
38451               });
38452               graph = graph.replace(tempWay);
38453               var tempMember = {
38454                 id: tempWay.id,
38455                 type: 'way',
38456                 role: member.role
38457               };
38458               var tempRelation = relation.replaceMember({
38459                 id: insertPair.originalID
38460               }, tempMember, true);
38461               groups = utilArrayGroupBy(tempRelation.members, 'type');
38462               groups.way = groups.way || []; // Insert pair is reversed if the inserted way comes before the original one.
38463               // (Except when they form a loop.)
38464
38465               var originalWay = graph.entity(insertPair.originalID);
38466               var insertedWay = graph.entity(insertPair.insertedID);
38467               insertPairIsReversed = originalWay.nodes.length > 0 && insertedWay.nodes.length > 0 && insertedWay.nodes[insertedWay.nodes.length - 1] === originalWay.nodes[0] && originalWay.nodes[originalWay.nodes.length - 1] !== insertedWay.nodes[0];
38468             } else {
38469               // Add the member anywhere, one time. Just push and let `osmJoinWays` decide where to put it.
38470               groups = utilArrayGroupBy(relation.members, 'type');
38471               groups.way = groups.way || [];
38472               groups.way.push(member);
38473             }
38474
38475             members = withIndex(groups.way);
38476             var joined = osmJoinWays(members, graph); // `joined` might not contain all of the way members,
38477             // But will contain only the completed (downloaded) members
38478
38479             for (i = 0; i < joined.length; i++) {
38480               var segment = joined[i];
38481               var nodes = segment.nodes.slice();
38482               var startIndex = segment[0].index; // j = array index in `members` where this segment starts
38483
38484               for (j = 0; j < members.length; j++) {
38485                 if (members[j].index === startIndex) {
38486                   break;
38487                 }
38488               } // k = each member in segment
38489
38490
38491               for (k = 0; k < segment.length; k++) {
38492                 item = segment[k];
38493                 var way = graph.entity(item.id); // If this is a paired item, generate members in correct order and role
38494
38495                 if (tempWay && item.id === tempWay.id) {
38496                   var reverse = nodes[0].id !== insertPair.nodes[0] ^ insertPairIsReversed;
38497
38498                   if (reverse) {
38499                     item.pair = [{
38500                       id: insertPair.insertedID,
38501                       type: 'way',
38502                       role: item.role
38503                     }, {
38504                       id: insertPair.originalID,
38505                       type: 'way',
38506                       role: item.role
38507                     }];
38508                   } else {
38509                     item.pair = [{
38510                       id: insertPair.originalID,
38511                       type: 'way',
38512                       role: item.role
38513                     }, {
38514                       id: insertPair.insertedID,
38515                       type: 'way',
38516                       role: item.role
38517                     }];
38518                   }
38519                 } // reorder `members` if necessary
38520
38521
38522                 if (k > 0) {
38523                   if (j + k >= members.length || item.index !== members[j + k].index) {
38524                     moveMember(members, item.index, j + k);
38525                   }
38526                 }
38527
38528                 nodes.splice(0, way.nodes.length - 1);
38529               }
38530             }
38531
38532             if (tempWay) {
38533               graph = graph.remove(tempWay);
38534             } // Final pass: skip dead items, split pairs, remove index properties
38535
38536
38537             var wayMembers = [];
38538
38539             for (i = 0; i < members.length; i++) {
38540               item = members[i];
38541               if (item.index === -1) continue;
38542
38543               if (item.pair) {
38544                 wayMembers.push(item.pair[0]);
38545                 wayMembers.push(item.pair[1]);
38546               } else {
38547                 wayMembers.push(utilObjectOmit(item, ['index']));
38548               }
38549             } // Put stops and platforms first, then nodes, ways, relations
38550             // This is recommended for Public Transport v2 routes:
38551             // see https://wiki.openstreetmap.org/wiki/Public_transport#Service_routes
38552
38553
38554             var newMembers = PTv2members.concat(groups.node || [], wayMembers, groups.relation || []);
38555             return graph.replace(relation.update({
38556               members: newMembers
38557             })); // `moveMember()` changes the `members` array in place by splicing
38558             // the item with `.index = findIndex` to where it belongs,
38559             // and marking the old position as "dead" with `.index = -1`
38560             //
38561             // j=5, k=0                jk
38562             // segment                 5 4 7 6
38563             // members       0 1 2 3 4 5 6 7 8 9        keep 5 in j+k
38564             //
38565             // j=5, k=1                j k
38566             // segment                 5 4 7 6
38567             // members       0 1 2 3 4 5 6 7 8 9        move 4 to j+k
38568             // members       0 1 2 3 x 5 4 6 7 8 9      moved
38569             //
38570             // j=5, k=2                j   k
38571             // segment                 5 4 7 6
38572             // members       0 1 2 3 x 5 4 6 7 8 9      move 7 to j+k
38573             // members       0 1 2 3 x 5 4 7 6 x 8 9    moved
38574             //
38575             // j=5, k=3                j     k
38576             // segment                 5 4 7 6
38577             // members       0 1 2 3 x 5 4 7 6 x 8 9    keep 6 in j+k
38578             //
38579
38580             function moveMember(arr, findIndex, toIndex) {
38581               var i;
38582
38583               for (i = 0; i < arr.length; i++) {
38584                 if (arr[i].index === findIndex) {
38585                   break;
38586                 }
38587               }
38588
38589               var item = Object.assign({}, arr[i]); // shallow copy
38590
38591               arr[i].index = -1; // mark as dead
38592
38593               item.index = toIndex;
38594               arr.splice(toIndex, 0, item);
38595             } // This is the same as `Relation.indexedMembers`,
38596             // Except we don't want to index all the members, only the ways
38597
38598
38599             function withIndex(arr) {
38600               var result = new Array(arr.length);
38601
38602               for (var i = 0; i < arr.length; i++) {
38603                 result[i] = Object.assign({}, arr[i]); // shallow copy
38604
38605                 result[i].index = i;
38606               }
38607
38608               return result;
38609             }
38610           }
38611         }
38612
38613         function actionAddMidpoint(midpoint, node) {
38614           return function (graph) {
38615             graph = graph.replace(node.move(midpoint.loc));
38616             var parents = utilArrayIntersection(graph.parentWays(graph.entity(midpoint.edge[0])), graph.parentWays(graph.entity(midpoint.edge[1])));
38617             parents.forEach(function (way) {
38618               for (var i = 0; i < way.nodes.length - 1; i++) {
38619                 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
38620                   graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1)); // Add only one midpoint on doubled-back segments,
38621                   // turning them into self-intersections.
38622
38623                   return;
38624                 }
38625               }
38626             });
38627             return graph;
38628           };
38629         }
38630
38631         // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
38632         function actionAddVertex(wayId, nodeId, index) {
38633           return function (graph) {
38634             return graph.replace(graph.entity(wayId).addNode(nodeId, index));
38635           };
38636         }
38637
38638         function actionChangeMember(relationId, member, memberIndex) {
38639           return function (graph) {
38640             return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
38641           };
38642         }
38643
38644         function actionChangePreset(entityID, oldPreset, newPreset, skipFieldDefaults) {
38645           return function action(graph) {
38646             var entity = graph.entity(entityID);
38647             var geometry = entity.geometry(graph);
38648             var tags = entity.tags; // preserve tags that the new preset might care about, if any
38649
38650             if (oldPreset) tags = oldPreset.unsetTags(tags, geometry, newPreset && newPreset.addTags ? Object.keys(newPreset.addTags) : null);
38651             if (newPreset) tags = newPreset.setTags(tags, geometry, skipFieldDefaults);
38652             return graph.replace(entity.update({
38653               tags: tags
38654             }));
38655           };
38656         }
38657
38658         function actionChangeTags(entityId, tags) {
38659           return function (graph) {
38660             var entity = graph.entity(entityId);
38661             return graph.replace(entity.update({
38662               tags: tags
38663             }));
38664           };
38665         }
38666
38667         function osmNode() {
38668           if (!(this instanceof osmNode)) {
38669             return new osmNode().initialize(arguments);
38670           } else if (arguments.length) {
38671             this.initialize(arguments);
38672           }
38673         }
38674         osmEntity.node = osmNode;
38675         osmNode.prototype = Object.create(osmEntity.prototype);
38676         Object.assign(osmNode.prototype, {
38677           type: 'node',
38678           loc: [9999, 9999],
38679           extent: function extent() {
38680             return new geoExtent(this.loc);
38681           },
38682           geometry: function geometry(graph) {
38683             return graph["transient"](this, 'geometry', function () {
38684               return graph.isPoi(this) ? 'point' : 'vertex';
38685             });
38686           },
38687           move: function move(loc) {
38688             return this.update({
38689               loc: loc
38690             });
38691           },
38692           isDegenerate: function isDegenerate() {
38693             return !(Array.isArray(this.loc) && this.loc.length === 2 && this.loc[0] >= -180 && this.loc[0] <= 180 && this.loc[1] >= -90 && this.loc[1] <= 90);
38694           },
38695           // Inspect tags and geometry to determine which direction(s) this node/vertex points
38696           directions: function directions(resolver, projection) {
38697             var val;
38698             var i; // which tag to use?
38699
38700             if (this.isHighwayIntersection(resolver) && (this.tags.stop || '').toLowerCase() === 'all') {
38701               // all-way stop tag on a highway intersection
38702               val = 'all';
38703             } else {
38704               // generic direction tag
38705               val = (this.tags.direction || '').toLowerCase(); // better suffix-style direction tag
38706
38707               var re = /:direction$/i;
38708               var keys = Object.keys(this.tags);
38709
38710               for (i = 0; i < keys.length; i++) {
38711                 if (re.test(keys[i])) {
38712                   val = this.tags[keys[i]].toLowerCase();
38713                   break;
38714                 }
38715               }
38716             }
38717
38718             if (val === '') return [];
38719             var cardinal = {
38720               north: 0,
38721               n: 0,
38722               northnortheast: 22,
38723               nne: 22,
38724               northeast: 45,
38725               ne: 45,
38726               eastnortheast: 67,
38727               ene: 67,
38728               east: 90,
38729               e: 90,
38730               eastsoutheast: 112,
38731               ese: 112,
38732               southeast: 135,
38733               se: 135,
38734               southsoutheast: 157,
38735               sse: 157,
38736               south: 180,
38737               s: 180,
38738               southsouthwest: 202,
38739               ssw: 202,
38740               southwest: 225,
38741               sw: 225,
38742               westsouthwest: 247,
38743               wsw: 247,
38744               west: 270,
38745               w: 270,
38746               westnorthwest: 292,
38747               wnw: 292,
38748               northwest: 315,
38749               nw: 315,
38750               northnorthwest: 337,
38751               nnw: 337
38752             };
38753             var values = val.split(';');
38754             var results = [];
38755             values.forEach(function (v) {
38756               // swap cardinal for numeric directions
38757               if (cardinal[v] !== undefined) {
38758                 v = cardinal[v];
38759               } // numeric direction - just add to results
38760
38761
38762               if (v !== '' && !isNaN(+v)) {
38763                 results.push(+v);
38764                 return;
38765               } // string direction - inspect parent ways
38766
38767
38768               var lookBackward = this.tags['traffic_sign:backward'] || v === 'backward' || v === 'both' || v === 'all';
38769               var lookForward = this.tags['traffic_sign:forward'] || v === 'forward' || v === 'both' || v === 'all';
38770               if (!lookForward && !lookBackward) return;
38771               var nodeIds = {};
38772               resolver.parentWays(this).forEach(function (parent) {
38773                 var nodes = parent.nodes;
38774
38775                 for (i = 0; i < nodes.length; i++) {
38776                   if (nodes[i] === this.id) {
38777                     // match current entity
38778                     if (lookForward && i > 0) {
38779                       nodeIds[nodes[i - 1]] = true; // look back to prev node
38780                     }
38781
38782                     if (lookBackward && i < nodes.length - 1) {
38783                       nodeIds[nodes[i + 1]] = true; // look ahead to next node
38784                     }
38785                   }
38786                 }
38787               }, this);
38788               Object.keys(nodeIds).forEach(function (nodeId) {
38789                 // +90 because geoAngle returns angle from X axis, not Y (north)
38790                 results.push(geoAngle(this, resolver.entity(nodeId), projection) * (180 / Math.PI) + 90);
38791               }, this);
38792             }, this);
38793             return utilArrayUniq(results);
38794           },
38795           isCrossing: function isCrossing() {
38796             return this.tags.highway === 'crossing' || this.tags.railway && this.tags.railway.indexOf('crossing') !== -1;
38797           },
38798           isEndpoint: function isEndpoint(resolver) {
38799             return resolver["transient"](this, 'isEndpoint', function () {
38800               var id = this.id;
38801               return resolver.parentWays(this).filter(function (parent) {
38802                 return !parent.isClosed() && !!parent.affix(id);
38803               }).length > 0;
38804             });
38805           },
38806           isConnected: function isConnected(resolver) {
38807             return resolver["transient"](this, 'isConnected', function () {
38808               var parents = resolver.parentWays(this);
38809
38810               if (parents.length > 1) {
38811                 // vertex is connected to multiple parent ways
38812                 for (var i in parents) {
38813                   if (parents[i].geometry(resolver) === 'line' && parents[i].hasInterestingTags()) return true;
38814                 }
38815               } else if (parents.length === 1) {
38816                 var way = parents[0];
38817                 var nodes = way.nodes.slice();
38818
38819                 if (way.isClosed()) {
38820                   nodes.pop();
38821                 } // ignore connecting node if closed
38822                 // return true if vertex appears multiple times (way is self intersecting)
38823
38824
38825                 return nodes.indexOf(this.id) !== nodes.lastIndexOf(this.id);
38826               }
38827
38828               return false;
38829             });
38830           },
38831           parentIntersectionWays: function parentIntersectionWays(resolver) {
38832             return resolver["transient"](this, 'parentIntersectionWays', function () {
38833               return resolver.parentWays(this).filter(function (parent) {
38834                 return (parent.tags.highway || parent.tags.waterway || parent.tags.railway || parent.tags.aeroway) && parent.geometry(resolver) === 'line';
38835               });
38836             });
38837           },
38838           isIntersection: function isIntersection(resolver) {
38839             return this.parentIntersectionWays(resolver).length > 1;
38840           },
38841           isHighwayIntersection: function isHighwayIntersection(resolver) {
38842             return resolver["transient"](this, 'isHighwayIntersection', function () {
38843               return resolver.parentWays(this).filter(function (parent) {
38844                 return parent.tags.highway && parent.geometry(resolver) === 'line';
38845               }).length > 1;
38846             });
38847           },
38848           isOnAddressLine: function isOnAddressLine(resolver) {
38849             return resolver["transient"](this, 'isOnAddressLine', function () {
38850               return resolver.parentWays(this).filter(function (parent) {
38851                 return parent.tags.hasOwnProperty('addr:interpolation') && parent.geometry(resolver) === 'line';
38852               }).length > 0;
38853             });
38854           },
38855           asJXON: function asJXON(changeset_id) {
38856             var r = {
38857               node: {
38858                 '@id': this.osmId(),
38859                 '@lon': this.loc[0],
38860                 '@lat': this.loc[1],
38861                 '@version': this.version || 0,
38862                 tag: Object.keys(this.tags).map(function (k) {
38863                   return {
38864                     keyAttributes: {
38865                       k: k,
38866                       v: this.tags[k]
38867                     }
38868                   };
38869                 }, this)
38870               }
38871             };
38872             if (changeset_id) r.node['@changeset'] = changeset_id;
38873             return r;
38874           },
38875           asGeoJSON: function asGeoJSON() {
38876             return {
38877               type: 'Point',
38878               coordinates: this.loc
38879             };
38880           }
38881         });
38882
38883         function actionCircularize(wayId, projection, maxAngle) {
38884           maxAngle = (maxAngle || 20) * Math.PI / 180;
38885
38886           var action = function action(graph, t) {
38887             if (t === null || !isFinite(t)) t = 1;
38888             t = Math.min(Math.max(+t, 0), 1);
38889             var way = graph.entity(wayId);
38890             var origNodes = {};
38891             graph.childNodes(way).forEach(function (node) {
38892               if (!origNodes[node.id]) origNodes[node.id] = node;
38893             });
38894
38895             if (!way.isConvex(graph)) {
38896               graph = action.makeConvex(graph);
38897             }
38898
38899             var nodes = utilArrayUniq(graph.childNodes(way));
38900             var keyNodes = nodes.filter(function (n) {
38901               return graph.parentWays(n).length !== 1;
38902             });
38903             var points = nodes.map(function (n) {
38904               return projection(n.loc);
38905             });
38906             var keyPoints = keyNodes.map(function (n) {
38907               return projection(n.loc);
38908             });
38909             var centroid = points.length === 2 ? geoVecInterp(points[0], points[1], 0.5) : d3_polygonCentroid(points);
38910             var radius = d3_median(points, function (p) {
38911               return geoVecLength(centroid, p);
38912             });
38913             var sign = d3_polygonArea(points) > 0 ? 1 : -1;
38914             var ids, i, j, k; // we need at least two key nodes for the algorithm to work
38915
38916             if (!keyNodes.length) {
38917               keyNodes = [nodes[0]];
38918               keyPoints = [points[0]];
38919             }
38920
38921             if (keyNodes.length === 1) {
38922               var index = nodes.indexOf(keyNodes[0]);
38923               var oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
38924               keyNodes.push(nodes[oppositeIndex]);
38925               keyPoints.push(points[oppositeIndex]);
38926             } // key points and nodes are those connected to the ways,
38927             // they are projected onto the circle, in between nodes are moved
38928             // to constant intervals between key nodes, extra in between nodes are
38929             // added if necessary.
38930
38931
38932             for (i = 0; i < keyPoints.length; i++) {
38933               var nextKeyNodeIndex = (i + 1) % keyNodes.length;
38934               var startNode = keyNodes[i];
38935               var endNode = keyNodes[nextKeyNodeIndex];
38936               var startNodeIndex = nodes.indexOf(startNode);
38937               var endNodeIndex = nodes.indexOf(endNode);
38938               var numberNewPoints = -1;
38939               var indexRange = endNodeIndex - startNodeIndex;
38940               var nearNodes = {};
38941               var inBetweenNodes = [];
38942               var startAngle, endAngle, totalAngle, eachAngle;
38943               var angle, loc, node, origNode;
38944
38945               if (indexRange < 0) {
38946                 indexRange += nodes.length;
38947               } // position this key node
38948
38949
38950               var distance = geoVecLength(centroid, keyPoints[i]) || 1e-4;
38951               keyPoints[i] = [centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius, centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius];
38952               loc = projection.invert(keyPoints[i]);
38953               node = keyNodes[i];
38954               origNode = origNodes[node.id];
38955               node = node.move(geoVecInterp(origNode.loc, loc, t));
38956               graph = graph.replace(node); // figure out the between delta angle we want to match to
38957
38958               startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
38959               endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
38960               totalAngle = endAngle - startAngle; // detects looping around -pi/pi
38961
38962               if (totalAngle * sign > 0) {
38963                 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
38964               }
38965
38966               do {
38967                 numberNewPoints++;
38968                 eachAngle = totalAngle / (indexRange + numberNewPoints);
38969               } while (Math.abs(eachAngle) > maxAngle); // move existing nodes
38970
38971
38972               for (j = 1; j < indexRange; j++) {
38973                 angle = startAngle + j * eachAngle;
38974                 loc = projection.invert([centroid[0] + Math.cos(angle) * radius, centroid[1] + Math.sin(angle) * radius]);
38975                 node = nodes[(j + startNodeIndex) % nodes.length];
38976                 origNode = origNodes[node.id];
38977                 nearNodes[node.id] = angle;
38978                 node = node.move(geoVecInterp(origNode.loc, loc, t));
38979                 graph = graph.replace(node);
38980               } // add new in between nodes if necessary
38981
38982
38983               for (j = 0; j < numberNewPoints; j++) {
38984                 angle = startAngle + (indexRange + j) * eachAngle;
38985                 loc = projection.invert([centroid[0] + Math.cos(angle) * radius, centroid[1] + Math.sin(angle) * radius]); // choose a nearnode to use as the original
38986
38987                 var min = Infinity;
38988
38989                 for (var nodeId in nearNodes) {
38990                   var nearAngle = nearNodes[nodeId];
38991                   var dist = Math.abs(nearAngle - angle);
38992
38993                   if (dist < min) {
38994                     min = dist;
38995                     origNode = origNodes[nodeId];
38996                   }
38997                 }
38998
38999                 node = osmNode({
39000                   loc: geoVecInterp(origNode.loc, loc, t)
39001                 });
39002                 graph = graph.replace(node);
39003                 nodes.splice(endNodeIndex + j, 0, node);
39004                 inBetweenNodes.push(node.id);
39005               } // Check for other ways that share these keyNodes..
39006               // If keyNodes are adjacent in both ways,
39007               // we can add inBetweenNodes to that shared way too..
39008
39009
39010               if (indexRange === 1 && inBetweenNodes.length) {
39011                 var startIndex1 = way.nodes.lastIndexOf(startNode.id);
39012                 var endIndex1 = way.nodes.lastIndexOf(endNode.id);
39013                 var wayDirection1 = endIndex1 - startIndex1;
39014
39015                 if (wayDirection1 < -1) {
39016                   wayDirection1 = 1;
39017                 }
39018
39019                 var parentWays = graph.parentWays(keyNodes[i]);
39020
39021                 for (j = 0; j < parentWays.length; j++) {
39022                   var sharedWay = parentWays[j];
39023                   if (sharedWay === way) continue;
39024
39025                   if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
39026                     var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id);
39027                     var endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id);
39028                     var wayDirection2 = endIndex2 - startIndex2;
39029                     var insertAt = endIndex2;
39030
39031                     if (wayDirection2 < -1) {
39032                       wayDirection2 = 1;
39033                     }
39034
39035                     if (wayDirection1 !== wayDirection2) {
39036                       inBetweenNodes.reverse();
39037                       insertAt = startIndex2;
39038                     }
39039
39040                     for (k = 0; k < inBetweenNodes.length; k++) {
39041                       sharedWay = sharedWay.addNode(inBetweenNodes[k], insertAt + k);
39042                     }
39043
39044                     graph = graph.replace(sharedWay);
39045                   }
39046                 }
39047               }
39048             } // update the way to have all the new nodes
39049
39050
39051             ids = nodes.map(function (n) {
39052               return n.id;
39053             });
39054             ids.push(ids[0]);
39055             way = way.update({
39056               nodes: ids
39057             });
39058             graph = graph.replace(way);
39059             return graph;
39060           };
39061
39062           action.makeConvex = function (graph) {
39063             var way = graph.entity(wayId);
39064             var nodes = utilArrayUniq(graph.childNodes(way));
39065             var points = nodes.map(function (n) {
39066               return projection(n.loc);
39067             });
39068             var sign = d3_polygonArea(points) > 0 ? 1 : -1;
39069             var hull = d3_polygonHull(points);
39070             var i, j; // D3 convex hulls go counterclockwise..
39071
39072             if (sign === -1) {
39073               nodes.reverse();
39074               points.reverse();
39075             }
39076
39077             for (i = 0; i < hull.length - 1; i++) {
39078               var startIndex = points.indexOf(hull[i]);
39079               var endIndex = points.indexOf(hull[i + 1]);
39080               var indexRange = endIndex - startIndex;
39081
39082               if (indexRange < 0) {
39083                 indexRange += nodes.length;
39084               } // move interior nodes to the surface of the convex hull..
39085
39086
39087               for (j = 1; j < indexRange; j++) {
39088                 var point = geoVecInterp(hull[i], hull[i + 1], j / indexRange);
39089                 var node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
39090                 graph = graph.replace(node);
39091               }
39092             }
39093
39094             return graph;
39095           };
39096
39097           action.disabled = function (graph) {
39098             if (!graph.entity(wayId).isClosed()) {
39099               return 'not_closed';
39100             } //disable when already circular
39101
39102
39103             var way = graph.entity(wayId);
39104             var nodes = utilArrayUniq(graph.childNodes(way));
39105             var points = nodes.map(function (n) {
39106               return projection(n.loc);
39107             });
39108             var hull = d3_polygonHull(points);
39109             var epsilonAngle = Math.PI / 180;
39110
39111             if (hull.length !== points.length || hull.length < 3) {
39112               return false;
39113             }
39114
39115             var centroid = d3_polygonCentroid(points);
39116             var radius = geoVecLengthSquare(centroid, points[0]);
39117             var i, actualPoint; // compare distances between centroid and points
39118
39119             for (i = 0; i < hull.length; i++) {
39120               actualPoint = hull[i];
39121               var actualDist = geoVecLengthSquare(actualPoint, centroid);
39122               var diff = Math.abs(actualDist - radius); //compare distances with epsilon-error (5%)
39123
39124               if (diff > 0.05 * radius) {
39125                 return false;
39126               }
39127             } //check if central angles are smaller than maxAngle
39128
39129
39130             for (i = 0; i < hull.length; i++) {
39131               actualPoint = hull[i];
39132               var nextPoint = hull[(i + 1) % hull.length];
39133               var startAngle = Math.atan2(actualPoint[1] - centroid[1], actualPoint[0] - centroid[0]);
39134               var endAngle = Math.atan2(nextPoint[1] - centroid[1], nextPoint[0] - centroid[0]);
39135               var angle = endAngle - startAngle;
39136
39137               if (angle < 0) {
39138                 angle = -angle;
39139               }
39140
39141               if (angle > Math.PI) {
39142                 angle = 2 * Math.PI - angle;
39143               }
39144
39145               if (angle > maxAngle + epsilonAngle) {
39146                 return false;
39147               }
39148             }
39149
39150             return 'already_circular';
39151           };
39152
39153           action.transitionable = true;
39154           return action;
39155         }
39156
39157         function actionDeleteWay(wayID) {
39158           function canDeleteNode(node, graph) {
39159             // don't delete nodes still attached to ways or relations
39160             if (graph.parentWays(node).length || graph.parentRelations(node).length) return false;
39161             var geometries = osmNodeGeometriesForTags(node.tags); // don't delete if this node can be a standalone point
39162
39163             if (geometries.point) return false; // delete if this node only be a vertex
39164
39165             if (geometries.vertex) return true; // iD doesn't know if this should be a point or vertex,
39166             // so only delete if there are no interesting tags
39167
39168             return !node.hasInterestingTags();
39169           }
39170
39171           var action = function action(graph) {
39172             var way = graph.entity(wayID);
39173             graph.parentRelations(way).forEach(function (parent) {
39174               parent = parent.removeMembersWithID(wayID);
39175               graph = graph.replace(parent);
39176
39177               if (parent.isDegenerate()) {
39178                 graph = actionDeleteRelation(parent.id)(graph);
39179               }
39180             });
39181             new Set(way.nodes).forEach(function (nodeID) {
39182               graph = graph.replace(way.removeNode(nodeID));
39183               var node = graph.entity(nodeID);
39184
39185               if (canDeleteNode(node, graph)) {
39186                 graph = graph.remove(node);
39187               }
39188             });
39189             return graph.remove(way);
39190           };
39191
39192           return action;
39193         }
39194
39195         function actionDeleteMultiple(ids) {
39196           var actions = {
39197             way: actionDeleteWay,
39198             node: actionDeleteNode,
39199             relation: actionDeleteRelation
39200           };
39201
39202           var action = function action(graph) {
39203             ids.forEach(function (id) {
39204               if (graph.hasEntity(id)) {
39205                 // It may have been deleted already.
39206                 graph = actions[graph.entity(id).type](id)(graph);
39207               }
39208             });
39209             return graph;
39210           };
39211
39212           return action;
39213         }
39214
39215         function actionDeleteRelation(relationID, allowUntaggedMembers) {
39216           function canDeleteEntity(entity, graph) {
39217             return !graph.parentWays(entity).length && !graph.parentRelations(entity).length && !entity.hasInterestingTags() && !allowUntaggedMembers;
39218           }
39219
39220           var action = function action(graph) {
39221             var relation = graph.entity(relationID);
39222             graph.parentRelations(relation).forEach(function (parent) {
39223               parent = parent.removeMembersWithID(relationID);
39224               graph = graph.replace(parent);
39225
39226               if (parent.isDegenerate()) {
39227                 graph = actionDeleteRelation(parent.id)(graph);
39228               }
39229             });
39230             var memberIDs = utilArrayUniq(relation.members.map(function (m) {
39231               return m.id;
39232             }));
39233             memberIDs.forEach(function (memberID) {
39234               graph = graph.replace(relation.removeMembersWithID(memberID));
39235               var entity = graph.entity(memberID);
39236
39237               if (canDeleteEntity(entity, graph)) {
39238                 graph = actionDeleteMultiple([memberID])(graph);
39239               }
39240             });
39241             return graph.remove(relation);
39242           };
39243
39244           return action;
39245         }
39246
39247         function actionDeleteNode(nodeId) {
39248           var action = function action(graph) {
39249             var node = graph.entity(nodeId);
39250             graph.parentWays(node).forEach(function (parent) {
39251               parent = parent.removeNode(nodeId);
39252               graph = graph.replace(parent);
39253
39254               if (parent.isDegenerate()) {
39255                 graph = actionDeleteWay(parent.id)(graph);
39256               }
39257             });
39258             graph.parentRelations(node).forEach(function (parent) {
39259               parent = parent.removeMembersWithID(nodeId);
39260               graph = graph.replace(parent);
39261
39262               if (parent.isDegenerate()) {
39263                 graph = actionDeleteRelation(parent.id)(graph);
39264               }
39265             });
39266             return graph.remove(node);
39267           };
39268
39269           return action;
39270         }
39271
39272         //
39273         // First choose a node to be the survivor, with preference given
39274         // to the oldest existing (not new) and "interesting" node.
39275         //
39276         // Tags and relation memberships of of non-surviving nodes are merged
39277         // to the survivor.
39278         //
39279         // This is the inverse of `iD.actionDisconnect`.
39280         //
39281         // Reference:
39282         //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
39283         //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
39284         //
39285
39286         function actionConnect(nodeIDs) {
39287           var action = function action(graph) {
39288             var survivor;
39289             var node;
39290             var parents;
39291             var i, j; // Select the node with the ID passed as parameter if it is in the list,
39292             // otherwise select the node with the oldest ID as the survivor, or the
39293             // last one if there are only new nodes.
39294
39295             nodeIDs.reverse();
39296             var interestingIDs = [];
39297
39298             for (i = 0; i < nodeIDs.length; i++) {
39299               node = graph.entity(nodeIDs[i]);
39300
39301               if (node.hasInterestingTags()) {
39302                 if (!node.isNew()) {
39303                   interestingIDs.push(node.id);
39304                 }
39305               }
39306             }
39307
39308             survivor = graph.entity(utilOldestID(interestingIDs.length > 0 ? interestingIDs : nodeIDs)); // Replace all non-surviving nodes with the survivor and merge tags.
39309
39310             for (i = 0; i < nodeIDs.length; i++) {
39311               node = graph.entity(nodeIDs[i]);
39312               if (node.id === survivor.id) continue;
39313               parents = graph.parentWays(node);
39314
39315               for (j = 0; j < parents.length; j++) {
39316                 graph = graph.replace(parents[j].replaceNode(node.id, survivor.id));
39317               }
39318
39319               parents = graph.parentRelations(node);
39320
39321               for (j = 0; j < parents.length; j++) {
39322                 graph = graph.replace(parents[j].replaceMember(node, survivor));
39323               }
39324
39325               survivor = survivor.mergeTags(node.tags);
39326               graph = actionDeleteNode(node.id)(graph);
39327             }
39328
39329             graph = graph.replace(survivor); // find and delete any degenerate ways created by connecting adjacent vertices
39330
39331             parents = graph.parentWays(survivor);
39332
39333             for (i = 0; i < parents.length; i++) {
39334               if (parents[i].isDegenerate()) {
39335                 graph = actionDeleteWay(parents[i].id)(graph);
39336               }
39337             }
39338
39339             return graph;
39340           };
39341
39342           action.disabled = function (graph) {
39343             var seen = {};
39344             var restrictionIDs = [];
39345             var survivor;
39346             var node, way;
39347             var relations, relation, role;
39348             var i, j, k; // Select the node with the oldest ID as the survivor.
39349
39350             survivor = graph.entity(utilOldestID(nodeIDs)); // 1. disable if the nodes being connected have conflicting relation roles
39351
39352             for (i = 0; i < nodeIDs.length; i++) {
39353               node = graph.entity(nodeIDs[i]);
39354               relations = graph.parentRelations(node);
39355
39356               for (j = 0; j < relations.length; j++) {
39357                 relation = relations[j];
39358                 role = relation.memberById(node.id).role || ''; // if this node is a via node in a restriction, remember for later
39359
39360                 if (relation.hasFromViaTo()) {
39361                   restrictionIDs.push(relation.id);
39362                 }
39363
39364                 if (seen[relation.id] !== undefined && seen[relation.id] !== role) {
39365                   return 'relation';
39366                 } else {
39367                   seen[relation.id] = role;
39368                 }
39369               }
39370             } // gather restrictions for parent ways
39371
39372
39373             for (i = 0; i < nodeIDs.length; i++) {
39374               node = graph.entity(nodeIDs[i]);
39375               var parents = graph.parentWays(node);
39376
39377               for (j = 0; j < parents.length; j++) {
39378                 var parent = parents[j];
39379                 relations = graph.parentRelations(parent);
39380
39381                 for (k = 0; k < relations.length; k++) {
39382                   relation = relations[k];
39383
39384                   if (relation.hasFromViaTo()) {
39385                     restrictionIDs.push(relation.id);
39386                   }
39387                 }
39388               }
39389             } // test restrictions
39390
39391
39392             restrictionIDs = utilArrayUniq(restrictionIDs);
39393
39394             for (i = 0; i < restrictionIDs.length; i++) {
39395               relation = graph.entity(restrictionIDs[i]);
39396               if (!relation.isComplete(graph)) continue;
39397               var memberWays = relation.members.filter(function (m) {
39398                 return m.type === 'way';
39399               }).map(function (m) {
39400                 return graph.entity(m.id);
39401               });
39402               memberWays = utilArrayUniq(memberWays);
39403               var f = relation.memberByRole('from');
39404               var t = relation.memberByRole('to');
39405               var isUturn = f.id === t.id; // 2a. disable if connection would damage a restriction
39406               // (a key node is a node at the junction of ways)
39407
39408               var nodes = {
39409                 from: [],
39410                 via: [],
39411                 to: [],
39412                 keyfrom: [],
39413                 keyto: []
39414               };
39415
39416               for (j = 0; j < relation.members.length; j++) {
39417                 collectNodes(relation.members[j], nodes);
39418               }
39419
39420               nodes.keyfrom = utilArrayUniq(nodes.keyfrom.filter(hasDuplicates));
39421               nodes.keyto = utilArrayUniq(nodes.keyto.filter(hasDuplicates));
39422               var filter = keyNodeFilter(nodes.keyfrom, nodes.keyto);
39423               nodes.from = nodes.from.filter(filter);
39424               nodes.via = nodes.via.filter(filter);
39425               nodes.to = nodes.to.filter(filter);
39426               var connectFrom = false;
39427               var connectVia = false;
39428               var connectTo = false;
39429               var connectKeyFrom = false;
39430               var connectKeyTo = false;
39431
39432               for (j = 0; j < nodeIDs.length; j++) {
39433                 var n = nodeIDs[j];
39434
39435                 if (nodes.from.indexOf(n) !== -1) {
39436                   connectFrom = true;
39437                 }
39438
39439                 if (nodes.via.indexOf(n) !== -1) {
39440                   connectVia = true;
39441                 }
39442
39443                 if (nodes.to.indexOf(n) !== -1) {
39444                   connectTo = true;
39445                 }
39446
39447                 if (nodes.keyfrom.indexOf(n) !== -1) {
39448                   connectKeyFrom = true;
39449                 }
39450
39451                 if (nodes.keyto.indexOf(n) !== -1) {
39452                   connectKeyTo = true;
39453                 }
39454               }
39455
39456               if (connectFrom && connectTo && !isUturn) {
39457                 return 'restriction';
39458               }
39459
39460               if (connectFrom && connectVia) {
39461                 return 'restriction';
39462               }
39463
39464               if (connectTo && connectVia) {
39465                 return 'restriction';
39466               } // connecting to a key node -
39467               // if both nodes are on a member way (i.e. part of the turn restriction),
39468               // the connecting node must be adjacent to the key node.
39469
39470
39471               if (connectKeyFrom || connectKeyTo) {
39472                 if (nodeIDs.length !== 2) {
39473                   return 'restriction';
39474                 }
39475
39476                 var n0 = null;
39477                 var n1 = null;
39478
39479                 for (j = 0; j < memberWays.length; j++) {
39480                   way = memberWays[j];
39481
39482                   if (way.contains(nodeIDs[0])) {
39483                     n0 = nodeIDs[0];
39484                   }
39485
39486                   if (way.contains(nodeIDs[1])) {
39487                     n1 = nodeIDs[1];
39488                   }
39489                 }
39490
39491                 if (n0 && n1) {
39492                   // both nodes are part of the restriction
39493                   var ok = false;
39494
39495                   for (j = 0; j < memberWays.length; j++) {
39496                     way = memberWays[j];
39497
39498                     if (way.areAdjacent(n0, n1)) {
39499                       ok = true;
39500                       break;
39501                     }
39502                   }
39503
39504                   if (!ok) {
39505                     return 'restriction';
39506                   }
39507                 }
39508               } // 2b. disable if nodes being connected will destroy a member way in a restriction
39509               // (to test, make a copy and try actually connecting the nodes)
39510
39511
39512               for (j = 0; j < memberWays.length; j++) {
39513                 way = memberWays[j].update({}); // make copy
39514
39515                 for (k = 0; k < nodeIDs.length; k++) {
39516                   if (nodeIDs[k] === survivor.id) continue;
39517
39518                   if (way.areAdjacent(nodeIDs[k], survivor.id)) {
39519                     way = way.removeNode(nodeIDs[k]);
39520                   } else {
39521                     way = way.replaceNode(nodeIDs[k], survivor.id);
39522                   }
39523                 }
39524
39525                 if (way.isDegenerate()) {
39526                   return 'restriction';
39527                 }
39528               }
39529             }
39530
39531             return false; // if a key node appears multiple times (indexOf !== lastIndexOf) it's a FROM-VIA or TO-VIA junction
39532
39533             function hasDuplicates(n, i, arr) {
39534               return arr.indexOf(n) !== arr.lastIndexOf(n);
39535             }
39536
39537             function keyNodeFilter(froms, tos) {
39538               return function (n) {
39539                 return froms.indexOf(n) === -1 && tos.indexOf(n) === -1;
39540               };
39541             }
39542
39543             function collectNodes(member, collection) {
39544               var entity = graph.hasEntity(member.id);
39545               if (!entity) return;
39546               var role = member.role || '';
39547
39548               if (!collection[role]) {
39549                 collection[role] = [];
39550               }
39551
39552               if (member.type === 'node') {
39553                 collection[role].push(member.id);
39554
39555                 if (role === 'via') {
39556                   collection.keyfrom.push(member.id);
39557                   collection.keyto.push(member.id);
39558                 }
39559               } else if (member.type === 'way') {
39560                 collection[role].push.apply(collection[role], entity.nodes);
39561
39562                 if (role === 'from' || role === 'via') {
39563                   collection.keyfrom.push(entity.first());
39564                   collection.keyfrom.push(entity.last());
39565                 }
39566
39567                 if (role === 'to' || role === 'via') {
39568                   collection.keyto.push(entity.first());
39569                   collection.keyto.push(entity.last());
39570                 }
39571               }
39572             }
39573           };
39574
39575           return action;
39576         }
39577
39578         function actionCopyEntities(ids, fromGraph) {
39579           var _copies = {};
39580
39581           var action = function action(graph) {
39582             ids.forEach(function (id) {
39583               fromGraph.entity(id).copy(fromGraph, _copies);
39584             });
39585
39586             for (var id in _copies) {
39587               graph = graph.replace(_copies[id]);
39588             }
39589
39590             return graph;
39591           };
39592
39593           action.copies = function () {
39594             return _copies;
39595           };
39596
39597           return action;
39598         }
39599
39600         function actionDeleteMember(relationId, memberIndex) {
39601           return function (graph) {
39602             var relation = graph.entity(relationId).removeMember(memberIndex);
39603             graph = graph.replace(relation);
39604
39605             if (relation.isDegenerate()) {
39606               graph = actionDeleteRelation(relation.id)(graph);
39607             }
39608
39609             return graph;
39610           };
39611         }
39612
39613         function actionDiscardTags(difference, discardTags) {
39614           discardTags = discardTags || {};
39615           return function (graph) {
39616             difference.modified().forEach(checkTags);
39617             difference.created().forEach(checkTags);
39618             return graph;
39619
39620             function checkTags(entity) {
39621               var keys = Object.keys(entity.tags);
39622               var didDiscard = false;
39623               var tags = {};
39624
39625               for (var i = 0; i < keys.length; i++) {
39626                 var k = keys[i];
39627
39628                 if (discardTags[k] || !entity.tags[k]) {
39629                   didDiscard = true;
39630                 } else {
39631                   tags[k] = entity.tags[k];
39632                 }
39633               }
39634
39635               if (didDiscard) {
39636                 graph = graph.replace(entity.update({
39637                   tags: tags
39638                 }));
39639               }
39640             }
39641           };
39642         }
39643
39644         //
39645         // Optionally, disconnect only the given ways.
39646         //
39647         // For testing convenience, accepts an ID to assign to the (first) new node.
39648         // Normally, this will be undefined and the way will automatically
39649         // be assigned a new ID.
39650         //
39651         // This is the inverse of `iD.actionConnect`.
39652         //
39653         // Reference:
39654         //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
39655         //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
39656         //
39657
39658         function actionDisconnect(nodeId, newNodeId) {
39659           var wayIds;
39660           var disconnectableRelationTypes = {
39661             'associatedStreet': true,
39662             'enforcement': true,
39663             'site': true
39664           };
39665
39666           var action = function action(graph) {
39667             var node = graph.entity(nodeId);
39668             var connections = action.connections(graph);
39669             connections.forEach(function (connection) {
39670               var way = graph.entity(connection.wayID);
39671               var newNode = osmNode({
39672                 id: newNodeId,
39673                 loc: node.loc,
39674                 tags: node.tags
39675               });
39676               graph = graph.replace(newNode);
39677
39678               if (connection.index === 0 && way.isArea()) {
39679                 // replace shared node with shared node..
39680                 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
39681               } else if (way.isClosed() && connection.index === way.nodes.length - 1) {
39682                 // replace closing node with new new node..
39683                 graph = graph.replace(way.unclose().addNode(newNode.id));
39684               } else {
39685                 // replace shared node with multiple new nodes..
39686                 graph = graph.replace(way.updateNode(newNode.id, connection.index));
39687               }
39688             });
39689             return graph;
39690           };
39691
39692           action.connections = function (graph) {
39693             var candidates = [];
39694             var keeping = false;
39695             var parentWays = graph.parentWays(graph.entity(nodeId));
39696             var way, waynode;
39697
39698             for (var i = 0; i < parentWays.length; i++) {
39699               way = parentWays[i];
39700
39701               if (wayIds && wayIds.indexOf(way.id) === -1) {
39702                 keeping = true;
39703                 continue;
39704               }
39705
39706               if (way.isArea() && way.nodes[0] === nodeId) {
39707                 candidates.push({
39708                   wayID: way.id,
39709                   index: 0
39710                 });
39711               } else {
39712                 for (var j = 0; j < way.nodes.length; j++) {
39713                   waynode = way.nodes[j];
39714
39715                   if (waynode === nodeId) {
39716                     if (way.isClosed() && parentWays.length > 1 && wayIds && wayIds.indexOf(way.id) !== -1 && j === way.nodes.length - 1) {
39717                       continue;
39718                     }
39719
39720                     candidates.push({
39721                       wayID: way.id,
39722                       index: j
39723                     });
39724                   }
39725                 }
39726               }
39727             }
39728
39729             return keeping ? candidates : candidates.slice(1);
39730           };
39731
39732           action.disabled = function (graph) {
39733             var connections = action.connections(graph);
39734             if (connections.length === 0) return 'not_connected';
39735             var parentWays = graph.parentWays(graph.entity(nodeId));
39736             var seenRelationIds = {};
39737             var sharedRelation;
39738             parentWays.forEach(function (way) {
39739               var relations = graph.parentRelations(way);
39740               relations.filter(function (relation) {
39741                 return !disconnectableRelationTypes[relation.tags.type];
39742               }).forEach(function (relation) {
39743                 if (relation.id in seenRelationIds) {
39744                   if (wayIds) {
39745                     if (wayIds.indexOf(way.id) !== -1 || wayIds.indexOf(seenRelationIds[relation.id]) !== -1) {
39746                       sharedRelation = relation;
39747                     }
39748                   } else {
39749                     sharedRelation = relation;
39750                   }
39751                 } else {
39752                   seenRelationIds[relation.id] = way.id;
39753                 }
39754               });
39755             });
39756             if (sharedRelation) return 'relation';
39757           };
39758
39759           action.limitWays = function (val) {
39760             if (!arguments.length) return wayIds;
39761             wayIds = val;
39762             return action;
39763           };
39764
39765           return action;
39766         }
39767
39768         function actionExtract(entityID, projection) {
39769           var extractedNodeID;
39770
39771           var action = function action(graph) {
39772             var entity = graph.entity(entityID);
39773
39774             if (entity.type === 'node') {
39775               return extractFromNode(entity, graph);
39776             }
39777
39778             return extractFromWayOrRelation(entity, graph);
39779           };
39780
39781           function extractFromNode(node, graph) {
39782             extractedNodeID = node.id; // Create a new node to replace the one we will detach
39783
39784             var replacement = osmNode({
39785               loc: node.loc
39786             });
39787             graph = graph.replace(replacement); // Process each way in turn, updating the graph as we go
39788
39789             graph = graph.parentWays(node).reduce(function (accGraph, parentWay) {
39790               return accGraph.replace(parentWay.replaceNode(entityID, replacement.id));
39791             }, graph); // Process any relations too
39792
39793             return graph.parentRelations(node).reduce(function (accGraph, parentRel) {
39794               return accGraph.replace(parentRel.replaceMember(node, replacement));
39795             }, graph);
39796           }
39797
39798           function extractFromWayOrRelation(entity, graph) {
39799             var fromGeometry = entity.geometry(graph);
39800             var keysToCopyAndRetain = ['source', 'wheelchair'];
39801             var keysToRetain = ['area'];
39802             var buildingKeysToRetain = ['architect', 'building', 'height', 'layer'];
39803             var extractedLoc = d3_geoPath(projection).centroid(entity.asGeoJSON(graph));
39804             extractedLoc = extractedLoc && projection.invert(extractedLoc);
39805
39806             if (!extractedLoc || !isFinite(extractedLoc[0]) || !isFinite(extractedLoc[1])) {
39807               extractedLoc = entity.extent(graph).center();
39808             }
39809
39810             var indoorAreaValues = {
39811               area: true,
39812               corridor: true,
39813               elevator: true,
39814               level: true,
39815               room: true
39816             };
39817             var isBuilding = entity.tags.building && entity.tags.building !== 'no' || entity.tags['building:part'] && entity.tags['building:part'] !== 'no';
39818             var isIndoorArea = fromGeometry === 'area' && entity.tags.indoor && indoorAreaValues[entity.tags.indoor];
39819             var entityTags = Object.assign({}, entity.tags); // shallow copy
39820
39821             var pointTags = {};
39822
39823             for (var key in entityTags) {
39824               if (entity.type === 'relation' && key === 'type') {
39825                 continue;
39826               }
39827
39828               if (keysToRetain.indexOf(key) !== -1) {
39829                 continue;
39830               }
39831
39832               if (isBuilding) {
39833                 // don't transfer building-related tags
39834                 if (buildingKeysToRetain.indexOf(key) !== -1 || key.match(/^building:.{1,}/) || key.match(/^roof:.{1,}/)) continue;
39835               } // leave `indoor` tag on the area
39836
39837
39838               if (isIndoorArea && key === 'indoor') {
39839                 continue;
39840               } // copy the tag from the entity to the point
39841
39842
39843               pointTags[key] = entityTags[key]; // leave addresses and some other tags so they're on both features
39844
39845               if (keysToCopyAndRetain.indexOf(key) !== -1 || key.match(/^addr:.{1,}/)) {
39846                 continue;
39847               } else if (isIndoorArea && key === 'level') {
39848                 // leave `level` on both features
39849                 continue;
39850               } // remove the tag from the entity
39851
39852
39853               delete entityTags[key];
39854             }
39855
39856             if (!isBuilding && !isIndoorArea && fromGeometry === 'area') {
39857               // ensure that areas keep area geometry
39858               entityTags.area = 'yes';
39859             }
39860
39861             var replacement = osmNode({
39862               loc: extractedLoc,
39863               tags: pointTags
39864             });
39865             graph = graph.replace(replacement);
39866             extractedNodeID = replacement.id;
39867             return graph.replace(entity.update({
39868               tags: entityTags
39869             }));
39870           }
39871
39872           action.getExtractedNodeID = function () {
39873             return extractedNodeID;
39874           };
39875
39876           return action;
39877         }
39878
39879         //
39880         // This is the inverse of `iD.actionSplit`.
39881         //
39882         // Reference:
39883         //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
39884         //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
39885         //
39886
39887         function actionJoin(ids) {
39888           function groupEntitiesByGeometry(graph) {
39889             var entities = ids.map(function (id) {
39890               return graph.entity(id);
39891             });
39892             return Object.assign({
39893               line: []
39894             }, utilArrayGroupBy(entities, function (entity) {
39895               return entity.geometry(graph);
39896             }));
39897           }
39898
39899           var action = function action(graph) {
39900             var ways = ids.map(graph.entity, graph); // Prefer to keep an existing way.
39901             // if there are multiple existing ways, keep the oldest one
39902             // the oldest way is determined by the ID of the way.
39903
39904             var survivorID = utilOldestID(ways.map(function (way) {
39905               return way.id;
39906             })); // if any of the ways are sided (e.g. coastline, cliff, kerb)
39907             // sort them first so they establish the overall order - #6033
39908
39909             ways.sort(function (a, b) {
39910               var aSided = a.isSided();
39911               var bSided = b.isSided();
39912               return aSided && !bSided ? -1 : bSided && !aSided ? 1 : 0;
39913             });
39914             var sequences = osmJoinWays(ways, graph);
39915             var joined = sequences[0]; // We might need to reverse some of these ways before joining them.  #4688
39916             // `joined.actions` property will contain any actions we need to apply.
39917
39918             graph = sequences.actions.reduce(function (g, action) {
39919               return action(g);
39920             }, graph);
39921             var survivor = graph.entity(survivorID);
39922             survivor = survivor.update({
39923               nodes: joined.nodes.map(function (n) {
39924                 return n.id;
39925               })
39926             });
39927             graph = graph.replace(survivor);
39928             joined.forEach(function (way) {
39929               if (way.id === survivorID) return;
39930               graph.parentRelations(way).forEach(function (parent) {
39931                 graph = graph.replace(parent.replaceMember(way, survivor));
39932               });
39933               survivor = survivor.mergeTags(way.tags);
39934               graph = graph.replace(survivor);
39935               graph = actionDeleteWay(way.id)(graph);
39936             }); // Finds if the join created a single-member multipolygon,
39937             // and if so turns it into a basic area instead
39938
39939             function checkForSimpleMultipolygon() {
39940               if (!survivor.isClosed()) return;
39941               var multipolygons = graph.parentMultipolygons(survivor).filter(function (multipolygon) {
39942                 // find multipolygons where the survivor is the only member
39943                 return multipolygon.members.length === 1;
39944               }); // skip if this is the single member of multiple multipolygons
39945
39946               if (multipolygons.length !== 1) return;
39947               var multipolygon = multipolygons[0];
39948
39949               for (var key in survivor.tags) {
39950                 if (multipolygon.tags[key] && // don't collapse if tags cannot be cleanly merged
39951                 multipolygon.tags[key] !== survivor.tags[key]) return;
39952               }
39953
39954               survivor = survivor.mergeTags(multipolygon.tags);
39955               graph = graph.replace(survivor);
39956               graph = actionDeleteRelation(multipolygon.id, true
39957               /* allow untagged members */
39958               )(graph);
39959               var tags = Object.assign({}, survivor.tags);
39960
39961               if (survivor.geometry(graph) !== 'area') {
39962                 // ensure the feature persists as an area
39963                 tags.area = 'yes';
39964               }
39965
39966               delete tags.type; // remove type=multipolygon
39967
39968               survivor = survivor.update({
39969                 tags: tags
39970               });
39971               graph = graph.replace(survivor);
39972             }
39973
39974             checkForSimpleMultipolygon();
39975             return graph;
39976           }; // Returns the number of nodes the resultant way is expected to have
39977
39978
39979           action.resultingWayNodesLength = function (graph) {
39980             return ids.reduce(function (count, id) {
39981               return count + graph.entity(id).nodes.length;
39982             }, 0) - ids.length - 1;
39983           };
39984
39985           action.disabled = function (graph) {
39986             var geometries = groupEntitiesByGeometry(graph);
39987
39988             if (ids.length < 2 || ids.length !== geometries.line.length) {
39989               return 'not_eligible';
39990             }
39991
39992             var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
39993
39994             if (joined.length > 1) {
39995               return 'not_adjacent';
39996             }
39997
39998             var i; // All joined ways must belong to the same set of (non-restriction) relations.
39999             // Restriction relations have different logic, below, which allows some cases
40000             // this prohibits, and prohibits some cases this allows.
40001
40002             var sortedParentRelations = function sortedParentRelations(id) {
40003               return graph.parentRelations(graph.entity(id)).filter(function (rel) {
40004                 return !rel.isRestriction() && !rel.isConnectivity();
40005               }).sort(function (a, b) {
40006                 return a.id - b.id;
40007               });
40008             };
40009
40010             var relsA = sortedParentRelations(ids[0]);
40011
40012             for (i = 1; i < ids.length; i++) {
40013               var relsB = sortedParentRelations(ids[i]);
40014
40015               if (!utilArrayIdentical(relsA, relsB)) {
40016                 return 'conflicting_relations';
40017               }
40018             } // Loop through all combinations of path-pairs
40019             // to check potential intersections between all pairs
40020
40021
40022             for (i = 0; i < ids.length - 1; i++) {
40023               for (var j = i + 1; j < ids.length; j++) {
40024                 var path1 = graph.childNodes(graph.entity(ids[i])).map(function (e) {
40025                   return e.loc;
40026                 });
40027                 var path2 = graph.childNodes(graph.entity(ids[j])).map(function (e) {
40028                   return e.loc;
40029                 });
40030                 var intersections = geoPathIntersections(path1, path2); // Check if intersections are just nodes lying on top of
40031                 // each other/the line, as opposed to crossing it
40032
40033                 var common = utilArrayIntersection(joined[0].nodes.map(function (n) {
40034                   return n.loc.toString();
40035                 }), intersections.map(function (n) {
40036                   return n.toString();
40037                 }));
40038
40039                 if (common.length !== intersections.length) {
40040                   return 'paths_intersect';
40041                 }
40042               }
40043             }
40044
40045             var nodeIds = joined[0].nodes.map(function (n) {
40046               return n.id;
40047             }).slice(1, -1);
40048             var relation;
40049             var tags = {};
40050             var conflicting = false;
40051             joined[0].forEach(function (way) {
40052               var parents = graph.parentRelations(way);
40053               parents.forEach(function (parent) {
40054                 if ((parent.isRestriction() || parent.isConnectivity()) && parent.members.some(function (m) {
40055                   return nodeIds.indexOf(m.id) >= 0;
40056                 })) {
40057                   relation = parent;
40058                 }
40059               });
40060
40061               for (var k in way.tags) {
40062                 if (!(k in tags)) {
40063                   tags[k] = way.tags[k];
40064                 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
40065                   conflicting = true;
40066                 }
40067               }
40068             });
40069
40070             if (relation) {
40071               return relation.isRestriction() ? 'restriction' : 'connectivity';
40072             }
40073
40074             if (conflicting) {
40075               return 'conflicting_tags';
40076             }
40077           };
40078
40079           return action;
40080         }
40081
40082         function actionMerge(ids) {
40083           function groupEntitiesByGeometry(graph) {
40084             var entities = ids.map(function (id) {
40085               return graph.entity(id);
40086             });
40087             return Object.assign({
40088               point: [],
40089               area: [],
40090               line: [],
40091               relation: []
40092             }, utilArrayGroupBy(entities, function (entity) {
40093               return entity.geometry(graph);
40094             }));
40095           }
40096
40097           var action = function action(graph) {
40098             var geometries = groupEntitiesByGeometry(graph);
40099             var target = geometries.area[0] || geometries.line[0];
40100             var points = geometries.point;
40101             points.forEach(function (point) {
40102               target = target.mergeTags(point.tags);
40103               graph = graph.replace(target);
40104               graph.parentRelations(point).forEach(function (parent) {
40105                 graph = graph.replace(parent.replaceMember(point, target));
40106               });
40107               var nodes = utilArrayUniq(graph.childNodes(target));
40108               var removeNode = point;
40109
40110               if (!point.isNew()) {
40111                 // Try to preserve the original point if it already has
40112                 // an ID in the database.
40113                 var inserted = false;
40114
40115                 var canBeReplaced = function canBeReplaced(node) {
40116                   return !(graph.parentWays(node).length > 1 || graph.parentRelations(node).length);
40117                 };
40118
40119                 var replaceNode = function replaceNode(node) {
40120                   graph = graph.replace(point.update({
40121                     tags: node.tags,
40122                     loc: node.loc
40123                   }));
40124                   target = target.replaceNode(node.id, point.id);
40125                   graph = graph.replace(target);
40126                   removeNode = node;
40127                   inserted = true;
40128                 };
40129
40130                 var i;
40131                 var node; // First, try to replace a new child node on the target way.
40132
40133                 for (i = 0; i < nodes.length; i++) {
40134                   node = nodes[i];
40135
40136                   if (canBeReplaced(node) && node.isNew()) {
40137                     replaceNode(node);
40138                     break;
40139                   }
40140                 }
40141
40142                 if (!inserted && point.hasInterestingTags()) {
40143                   // No new child node found, try to find an existing, but
40144                   // uninteresting child node instead.
40145                   for (i = 0; i < nodes.length; i++) {
40146                     node = nodes[i];
40147
40148                     if (canBeReplaced(node) && !node.hasInterestingTags()) {
40149                       replaceNode(node);
40150                       break;
40151                     }
40152                   }
40153
40154                   if (!inserted) {
40155                     // Still not inserted, try to find an existing, interesting,
40156                     // but more recent child node.
40157                     for (i = 0; i < nodes.length; i++) {
40158                       node = nodes[i];
40159
40160                       if (canBeReplaced(node) && utilCompareIDs(point.id, node.id) < 0) {
40161                         replaceNode(node);
40162                         break;
40163                       }
40164                     }
40165                   } // If the point still hasn't been inserted, we give up.
40166                   // There are more interesting or older nodes on the way.
40167
40168                 }
40169               }
40170
40171               graph = graph.remove(removeNode);
40172             });
40173
40174             if (target.tags.area === 'yes') {
40175               var tags = Object.assign({}, target.tags); // shallow copy
40176
40177               delete tags.area;
40178
40179               if (osmTagSuggestingArea(tags)) {
40180                 // remove the `area` tag if area geometry is now implied - #3851
40181                 target = target.update({
40182                   tags: tags
40183                 });
40184                 graph = graph.replace(target);
40185               }
40186             }
40187
40188             return graph;
40189           };
40190
40191           action.disabled = function (graph) {
40192             var geometries = groupEntitiesByGeometry(graph);
40193
40194             if (geometries.point.length === 0 || geometries.area.length + geometries.line.length !== 1 || geometries.relation.length !== 0) {
40195               return 'not_eligible';
40196             }
40197           };
40198
40199           return action;
40200         }
40201
40202         //
40203         // 1. move all the nodes to a common location
40204         // 2. `actionConnect` them
40205
40206         function actionMergeNodes(nodeIDs, loc) {
40207           // If there is a single "interesting" node, use that as the location.
40208           // Otherwise return the average location of all the nodes.
40209           function chooseLoc(graph) {
40210             if (!nodeIDs.length) return null;
40211             var sum = [0, 0];
40212             var interestingCount = 0;
40213             var interestingLoc;
40214
40215             for (var i = 0; i < nodeIDs.length; i++) {
40216               var node = graph.entity(nodeIDs[i]);
40217
40218               if (node.hasInterestingTags()) {
40219                 interestingLoc = ++interestingCount === 1 ? node.loc : null;
40220               }
40221
40222               sum = geoVecAdd(sum, node.loc);
40223             }
40224
40225             return interestingLoc || geoVecScale(sum, 1 / nodeIDs.length);
40226           }
40227
40228           var action = function action(graph) {
40229             if (nodeIDs.length < 2) return graph;
40230             var toLoc = loc;
40231
40232             if (!toLoc) {
40233               toLoc = chooseLoc(graph);
40234             }
40235
40236             for (var i = 0; i < nodeIDs.length; i++) {
40237               var node = graph.entity(nodeIDs[i]);
40238
40239               if (node.loc !== toLoc) {
40240                 graph = graph.replace(node.move(toLoc));
40241               }
40242             }
40243
40244             return actionConnect(nodeIDs)(graph);
40245           };
40246
40247           action.disabled = function (graph) {
40248             if (nodeIDs.length < 2) return 'not_eligible';
40249
40250             for (var i = 0; i < nodeIDs.length; i++) {
40251               var entity = graph.entity(nodeIDs[i]);
40252               if (entity.type !== 'node') return 'not_eligible';
40253             }
40254
40255             return actionConnect(nodeIDs).disabled(graph);
40256           };
40257
40258           return action;
40259         }
40260
40261         function osmChangeset() {
40262           if (!(this instanceof osmChangeset)) {
40263             return new osmChangeset().initialize(arguments);
40264           } else if (arguments.length) {
40265             this.initialize(arguments);
40266           }
40267         }
40268         osmEntity.changeset = osmChangeset;
40269         osmChangeset.prototype = Object.create(osmEntity.prototype);
40270         Object.assign(osmChangeset.prototype, {
40271           type: 'changeset',
40272           extent: function extent() {
40273             return new geoExtent();
40274           },
40275           geometry: function geometry() {
40276             return 'changeset';
40277           },
40278           asJXON: function asJXON() {
40279             return {
40280               osm: {
40281                 changeset: {
40282                   tag: Object.keys(this.tags).map(function (k) {
40283                     return {
40284                       '@k': k,
40285                       '@v': this.tags[k]
40286                     };
40287                   }, this),
40288                   '@version': 0.6,
40289                   '@generator': 'iD'
40290                 }
40291               }
40292             };
40293           },
40294           // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
40295           // XML. Returns a string.
40296           osmChangeJXON: function osmChangeJXON(changes) {
40297             var changeset_id = this.id;
40298
40299             function nest(x, order) {
40300               var groups = {};
40301
40302               for (var i = 0; i < x.length; i++) {
40303                 var tagName = Object.keys(x[i])[0];
40304                 if (!groups[tagName]) groups[tagName] = [];
40305                 groups[tagName].push(x[i][tagName]);
40306               }
40307
40308               var ordered = {};
40309               order.forEach(function (o) {
40310                 if (groups[o]) ordered[o] = groups[o];
40311               });
40312               return ordered;
40313             } // sort relations in a changeset by dependencies
40314
40315
40316             function sort(changes) {
40317               // find a referenced relation in the current changeset
40318               function resolve(item) {
40319                 return relations.find(function (relation) {
40320                   return item.keyAttributes.type === 'relation' && item.keyAttributes.ref === relation['@id'];
40321                 });
40322               } // a new item is an item that has not been already processed
40323
40324
40325               function isNew(item) {
40326                 return !sorted[item['@id']] && !processing.find(function (proc) {
40327                   return proc['@id'] === item['@id'];
40328                 });
40329               }
40330
40331               var processing = [];
40332               var sorted = {};
40333               var relations = changes.relation;
40334               if (!relations) return changes;
40335
40336               for (var i = 0; i < relations.length; i++) {
40337                 var relation = relations[i]; // skip relation if already sorted
40338
40339                 if (!sorted[relation['@id']]) {
40340                   processing.push(relation);
40341                 }
40342
40343                 while (processing.length > 0) {
40344                   var next = processing[0],
40345                       deps = next.member.map(resolve).filter(Boolean).filter(isNew);
40346
40347                   if (deps.length === 0) {
40348                     sorted[next['@id']] = next;
40349                     processing.shift();
40350                   } else {
40351                     processing = deps.concat(processing);
40352                   }
40353                 }
40354               }
40355
40356               changes.relation = Object.values(sorted);
40357               return changes;
40358             }
40359
40360             function rep(entity) {
40361               return entity.asJXON(changeset_id);
40362             }
40363
40364             return {
40365               osmChange: {
40366                 '@version': 0.6,
40367                 '@generator': 'iD',
40368                 'create': sort(nest(changes.created.map(rep), ['node', 'way', 'relation'])),
40369                 'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']),
40370                 'delete': Object.assign(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), {
40371                   '@if-unused': true
40372                 })
40373               }
40374             };
40375           },
40376           asGeoJSON: function asGeoJSON() {
40377             return {};
40378           }
40379         });
40380
40381         function osmNote() {
40382           if (!(this instanceof osmNote)) {
40383             return new osmNote().initialize(arguments);
40384           } else if (arguments.length) {
40385             this.initialize(arguments);
40386           }
40387         }
40388
40389         osmNote.id = function () {
40390           return osmNote.id.next--;
40391         };
40392
40393         osmNote.id.next = -1;
40394         Object.assign(osmNote.prototype, {
40395           type: 'note',
40396           initialize: function initialize(sources) {
40397             for (var i = 0; i < sources.length; ++i) {
40398               var source = sources[i];
40399
40400               for (var prop in source) {
40401                 if (Object.prototype.hasOwnProperty.call(source, prop)) {
40402                   if (source[prop] === undefined) {
40403                     delete this[prop];
40404                   } else {
40405                     this[prop] = source[prop];
40406                   }
40407                 }
40408               }
40409             }
40410
40411             if (!this.id) {
40412               this.id = osmNote.id().toString();
40413             }
40414
40415             return this;
40416           },
40417           extent: function extent() {
40418             return new geoExtent(this.loc);
40419           },
40420           update: function update(attrs) {
40421             return osmNote(this, attrs); // {v: 1 + (this.v || 0)}
40422           },
40423           isNew: function isNew() {
40424             return this.id < 0;
40425           },
40426           move: function move(loc) {
40427             return this.update({
40428               loc: loc
40429             });
40430           }
40431         });
40432
40433         function osmRelation() {
40434           if (!(this instanceof osmRelation)) {
40435             return new osmRelation().initialize(arguments);
40436           } else if (arguments.length) {
40437             this.initialize(arguments);
40438           }
40439         }
40440         osmEntity.relation = osmRelation;
40441         osmRelation.prototype = Object.create(osmEntity.prototype);
40442
40443         osmRelation.creationOrder = function (a, b) {
40444           var aId = parseInt(osmEntity.id.toOSM(a.id), 10);
40445           var bId = parseInt(osmEntity.id.toOSM(b.id), 10);
40446           if (aId < 0 || bId < 0) return aId - bId;
40447           return bId - aId;
40448         };
40449
40450         Object.assign(osmRelation.prototype, {
40451           type: 'relation',
40452           members: [],
40453           copy: function copy(resolver, copies) {
40454             if (copies[this.id]) return copies[this.id];
40455             var copy = osmEntity.prototype.copy.call(this, resolver, copies);
40456             var members = this.members.map(function (member) {
40457               return Object.assign({}, member, {
40458                 id: resolver.entity(member.id).copy(resolver, copies).id
40459               });
40460             });
40461             copy = copy.update({
40462               members: members
40463             });
40464             copies[this.id] = copy;
40465             return copy;
40466           },
40467           extent: function extent(resolver, memo) {
40468             return resolver["transient"](this, 'extent', function () {
40469               if (memo && memo[this.id]) return geoExtent();
40470               memo = memo || {};
40471               memo[this.id] = true;
40472               var extent = geoExtent();
40473
40474               for (var i = 0; i < this.members.length; i++) {
40475                 var member = resolver.hasEntity(this.members[i].id);
40476
40477                 if (member) {
40478                   extent._extend(member.extent(resolver, memo));
40479                 }
40480               }
40481
40482               return extent;
40483             });
40484           },
40485           geometry: function geometry(graph) {
40486             return graph["transient"](this, 'geometry', function () {
40487               return this.isMultipolygon() ? 'area' : 'relation';
40488             });
40489           },
40490           isDegenerate: function isDegenerate() {
40491             return this.members.length === 0;
40492           },
40493           // Return an array of members, each extended with an 'index' property whose value
40494           // is the member index.
40495           indexedMembers: function indexedMembers() {
40496             var result = new Array(this.members.length);
40497
40498             for (var i = 0; i < this.members.length; i++) {
40499               result[i] = Object.assign({}, this.members[i], {
40500                 index: i
40501               });
40502             }
40503
40504             return result;
40505           },
40506           // Return the first member with the given role. A copy of the member object
40507           // is returned, extended with an 'index' property whose value is the member index.
40508           memberByRole: function memberByRole(role) {
40509             for (var i = 0; i < this.members.length; i++) {
40510               if (this.members[i].role === role) {
40511                 return Object.assign({}, this.members[i], {
40512                   index: i
40513                 });
40514               }
40515             }
40516           },
40517           // Same as memberByRole, but returns all members with the given role
40518           membersByRole: function membersByRole(role) {
40519             var result = [];
40520
40521             for (var i = 0; i < this.members.length; i++) {
40522               if (this.members[i].role === role) {
40523                 result.push(Object.assign({}, this.members[i], {
40524                   index: i
40525                 }));
40526               }
40527             }
40528
40529             return result;
40530           },
40531           // Return the first member with the given id. A copy of the member object
40532           // is returned, extended with an 'index' property whose value is the member index.
40533           memberById: function memberById(id) {
40534             for (var i = 0; i < this.members.length; i++) {
40535               if (this.members[i].id === id) {
40536                 return Object.assign({}, this.members[i], {
40537                   index: i
40538                 });
40539               }
40540             }
40541           },
40542           // Return the first member with the given id and role. A copy of the member object
40543           // is returned, extended with an 'index' property whose value is the member index.
40544           memberByIdAndRole: function memberByIdAndRole(id, role) {
40545             for (var i = 0; i < this.members.length; i++) {
40546               if (this.members[i].id === id && this.members[i].role === role) {
40547                 return Object.assign({}, this.members[i], {
40548                   index: i
40549                 });
40550               }
40551             }
40552           },
40553           addMember: function addMember(member, index) {
40554             var members = this.members.slice();
40555             members.splice(index === undefined ? members.length : index, 0, member);
40556             return this.update({
40557               members: members
40558             });
40559           },
40560           updateMember: function updateMember(member, index) {
40561             var members = this.members.slice();
40562             members.splice(index, 1, Object.assign({}, members[index], member));
40563             return this.update({
40564               members: members
40565             });
40566           },
40567           removeMember: function removeMember(index) {
40568             var members = this.members.slice();
40569             members.splice(index, 1);
40570             return this.update({
40571               members: members
40572             });
40573           },
40574           removeMembersWithID: function removeMembersWithID(id) {
40575             var members = this.members.filter(function (m) {
40576               return m.id !== id;
40577             });
40578             return this.update({
40579               members: members
40580             });
40581           },
40582           moveMember: function moveMember(fromIndex, toIndex) {
40583             var members = this.members.slice();
40584             members.splice(toIndex, 0, members.splice(fromIndex, 1)[0]);
40585             return this.update({
40586               members: members
40587             });
40588           },
40589           // Wherever a member appears with id `needle.id`, replace it with a member
40590           // with id `replacement.id`, type `replacement.type`, and the original role,
40591           // By default, adding a duplicate member (by id and role) is prevented.
40592           // Return an updated relation.
40593           replaceMember: function replaceMember(needle, replacement, keepDuplicates) {
40594             if (!this.memberById(needle.id)) return this;
40595             var members = [];
40596
40597             for (var i = 0; i < this.members.length; i++) {
40598               var member = this.members[i];
40599
40600               if (member.id !== needle.id) {
40601                 members.push(member);
40602               } else if (keepDuplicates || !this.memberByIdAndRole(replacement.id, member.role)) {
40603                 members.push({
40604                   id: replacement.id,
40605                   type: replacement.type,
40606                   role: member.role
40607                 });
40608               }
40609             }
40610
40611             return this.update({
40612               members: members
40613             });
40614           },
40615           asJXON: function asJXON(changeset_id) {
40616             var r = {
40617               relation: {
40618                 '@id': this.osmId(),
40619                 '@version': this.version || 0,
40620                 member: this.members.map(function (member) {
40621                   return {
40622                     keyAttributes: {
40623                       type: member.type,
40624                       role: member.role,
40625                       ref: osmEntity.id.toOSM(member.id)
40626                     }
40627                   };
40628                 }, this),
40629                 tag: Object.keys(this.tags).map(function (k) {
40630                   return {
40631                     keyAttributes: {
40632                       k: k,
40633                       v: this.tags[k]
40634                     }
40635                   };
40636                 }, this)
40637               }
40638             };
40639
40640             if (changeset_id) {
40641               r.relation['@changeset'] = changeset_id;
40642             }
40643
40644             return r;
40645           },
40646           asGeoJSON: function asGeoJSON(resolver) {
40647             return resolver["transient"](this, 'GeoJSON', function () {
40648               if (this.isMultipolygon()) {
40649                 return {
40650                   type: 'MultiPolygon',
40651                   coordinates: this.multipolygon(resolver)
40652                 };
40653               } else {
40654                 return {
40655                   type: 'FeatureCollection',
40656                   properties: this.tags,
40657                   features: this.members.map(function (member) {
40658                     return Object.assign({
40659                       role: member.role
40660                     }, resolver.entity(member.id).asGeoJSON(resolver));
40661                   })
40662                 };
40663               }
40664             });
40665           },
40666           area: function area(resolver) {
40667             return resolver["transient"](this, 'area', function () {
40668               return d3_geoArea(this.asGeoJSON(resolver));
40669             });
40670           },
40671           isMultipolygon: function isMultipolygon() {
40672             return this.tags.type === 'multipolygon';
40673           },
40674           isComplete: function isComplete(resolver) {
40675             for (var i = 0; i < this.members.length; i++) {
40676               if (!resolver.hasEntity(this.members[i].id)) {
40677                 return false;
40678               }
40679             }
40680
40681             return true;
40682           },
40683           hasFromViaTo: function hasFromViaTo() {
40684             return this.members.some(function (m) {
40685               return m.role === 'from';
40686             }) && this.members.some(function (m) {
40687               return m.role === 'via';
40688             }) && this.members.some(function (m) {
40689               return m.role === 'to';
40690             });
40691           },
40692           isRestriction: function isRestriction() {
40693             return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
40694           },
40695           isValidRestriction: function isValidRestriction() {
40696             if (!this.isRestriction()) return false;
40697             var froms = this.members.filter(function (m) {
40698               return m.role === 'from';
40699             });
40700             var vias = this.members.filter(function (m) {
40701               return m.role === 'via';
40702             });
40703             var tos = this.members.filter(function (m) {
40704               return m.role === 'to';
40705             });
40706             if (froms.length !== 1 && this.tags.restriction !== 'no_entry') return false;
40707             if (froms.some(function (m) {
40708               return m.type !== 'way';
40709             })) return false;
40710             if (tos.length !== 1 && this.tags.restriction !== 'no_exit') return false;
40711             if (tos.some(function (m) {
40712               return m.type !== 'way';
40713             })) return false;
40714             if (vias.length === 0) return false;
40715             if (vias.length > 1 && vias.some(function (m) {
40716               return m.type !== 'way';
40717             })) return false;
40718             return true;
40719           },
40720           isConnectivity: function isConnectivity() {
40721             return !!(this.tags.type && this.tags.type.match(/^connectivity:?/));
40722           },
40723           // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
40724           // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
40725           //
40726           // This corresponds to the structure needed for rendering a multipolygon path using a
40727           // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
40728           //
40729           // In the case of invalid geometries, this function will still return a result which
40730           // includes the nodes of all way members, but some Nds may be unclosed and some inner
40731           // rings not matched with the intended outer ring.
40732           //
40733           multipolygon: function multipolygon(resolver) {
40734             var outers = this.members.filter(function (m) {
40735               return 'outer' === (m.role || 'outer');
40736             });
40737             var inners = this.members.filter(function (m) {
40738               return 'inner' === m.role;
40739             });
40740             outers = osmJoinWays(outers, resolver);
40741             inners = osmJoinWays(inners, resolver);
40742
40743             var sequenceToLineString = function sequenceToLineString(sequence) {
40744               if (sequence.nodes.length > 2 && sequence.nodes[0] !== sequence.nodes[sequence.nodes.length - 1]) {
40745                 // close unclosed parts to ensure correct area rendering - #2945
40746                 sequence.nodes.push(sequence.nodes[0]);
40747               }
40748
40749               return sequence.nodes.map(function (node) {
40750                 return node.loc;
40751               });
40752             };
40753
40754             outers = outers.map(sequenceToLineString);
40755             inners = inners.map(sequenceToLineString);
40756             var result = outers.map(function (o) {
40757               // Heuristic for detecting counterclockwise winding order. Assumes
40758               // that OpenStreetMap polygons are not hemisphere-spanning.
40759               return [d3_geoArea({
40760                 type: 'Polygon',
40761                 coordinates: [o]
40762               }) > 2 * Math.PI ? o.reverse() : o];
40763             });
40764
40765             function findOuter(inner) {
40766               var o, outer;
40767
40768               for (o = 0; o < outers.length; o++) {
40769                 outer = outers[o];
40770
40771                 if (geoPolygonContainsPolygon(outer, inner)) {
40772                   return o;
40773                 }
40774               }
40775
40776               for (o = 0; o < outers.length; o++) {
40777                 outer = outers[o];
40778
40779                 if (geoPolygonIntersectsPolygon(outer, inner, false)) {
40780                   return o;
40781                 }
40782               }
40783             }
40784
40785             for (var i = 0; i < inners.length; i++) {
40786               var inner = inners[i];
40787
40788               if (d3_geoArea({
40789                 type: 'Polygon',
40790                 coordinates: [inner]
40791               }) < 2 * Math.PI) {
40792                 inner = inner.reverse();
40793               }
40794
40795               var o = findOuter(inners[i]);
40796
40797               if (o !== undefined) {
40798                 result[o].push(inners[i]);
40799               } else {
40800                 result.push([inners[i]]); // Invalid geometry
40801               }
40802             }
40803
40804             return result;
40805           }
40806         });
40807
40808         var QAItem = /*#__PURE__*/function () {
40809           function QAItem(loc, service, itemType, id, props) {
40810             _classCallCheck$1(this, QAItem);
40811
40812             // Store required properties
40813             this.loc = loc;
40814             this.service = service.title;
40815             this.itemType = itemType; // All issues must have an ID for selection, use generic if none specified
40816
40817             this.id = id ? id : "".concat(QAItem.id());
40818             this.update(props); // Some QA services have marker icons to differentiate issues
40819
40820             if (service && typeof service.getIcon === 'function') {
40821               this.icon = service.getIcon(itemType);
40822             }
40823           }
40824
40825           _createClass$1(QAItem, [{
40826             key: "update",
40827             value: function update(props) {
40828               var _this = this;
40829
40830               // You can't override this initial information
40831               var loc = this.loc,
40832                   service = this.service,
40833                   itemType = this.itemType,
40834                   id = this.id;
40835               Object.keys(props).forEach(function (prop) {
40836                 return _this[prop] = props[prop];
40837               });
40838               this.loc = loc;
40839               this.service = service;
40840               this.itemType = itemType;
40841               this.id = id;
40842               return this;
40843             } // Generic handling for newly created QAItems
40844
40845           }], [{
40846             key: "id",
40847             value: function id() {
40848               return this.nextId--;
40849             }
40850           }]);
40851
40852           return QAItem;
40853         }();
40854         QAItem.nextId = -1;
40855
40856         //
40857         // Optionally, split only the given ways, if multiple ways share
40858         // the given node.
40859         //
40860         // This is the inverse of `iD.actionJoin`.
40861         //
40862         // For testing convenience, accepts an ID to assign to the new way.
40863         // Normally, this will be undefined and the way will automatically
40864         // be assigned a new ID.
40865         //
40866         // Reference:
40867         //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
40868         //
40869
40870         function actionSplit(nodeIds, newWayIds) {
40871           // accept single ID for backwards-compatiblity
40872           if (typeof nodeIds === 'string') nodeIds = [nodeIds];
40873
40874           var _wayIDs; // the strategy for picking which way will have a new version and which way is newly created
40875
40876
40877           var _keepHistoryOn = 'longest'; // 'longest', 'first'
40878           // The IDs of the ways actually created by running this action
40879
40880           var _createdWayIDs = [];
40881
40882           function dist(graph, nA, nB) {
40883             var locA = graph.entity(nA).loc;
40884             var locB = graph.entity(nB).loc;
40885             var epsilon = 1e-6;
40886             return locA && locB ? geoSphericalDistance(locA, locB) : epsilon;
40887           } // If the way is closed, we need to search for a partner node
40888           // to split the way at.
40889           //
40890           // The following looks for a node that is both far away from
40891           // the initial node in terms of way segment length and nearby
40892           // in terms of beeline-distance. This assures that areas get
40893           // split on the most "natural" points (independent of the number
40894           // of nodes).
40895           // For example: bone-shaped areas get split across their waist
40896           // line, circles across the diameter.
40897
40898
40899           function splitArea(nodes, idxA, graph) {
40900             var lengths = new Array(nodes.length);
40901             var length;
40902             var i;
40903             var best = 0;
40904             var idxB;
40905
40906             function wrap(index) {
40907               return utilWrap(index, nodes.length);
40908             } // calculate lengths
40909
40910
40911             length = 0;
40912
40913             for (i = wrap(idxA + 1); i !== idxA; i = wrap(i + 1)) {
40914               length += dist(graph, nodes[i], nodes[wrap(i - 1)]);
40915               lengths[i] = length;
40916             }
40917
40918             length = 0;
40919
40920             for (i = wrap(idxA - 1); i !== idxA; i = wrap(i - 1)) {
40921               length += dist(graph, nodes[i], nodes[wrap(i + 1)]);
40922
40923               if (length < lengths[i]) {
40924                 lengths[i] = length;
40925               }
40926             } // determine best opposite node to split
40927
40928
40929             for (i = 0; i < nodes.length; i++) {
40930               var cost = lengths[i] / dist(graph, nodes[idxA], nodes[i]);
40931
40932               if (cost > best) {
40933                 idxB = i;
40934                 best = cost;
40935               }
40936             }
40937
40938             return idxB;
40939           }
40940
40941           function totalLengthBetweenNodes(graph, nodes) {
40942             var totalLength = 0;
40943
40944             for (var i = 0; i < nodes.length - 1; i++) {
40945               totalLength += dist(graph, nodes[i], nodes[i + 1]);
40946             }
40947
40948             return totalLength;
40949           }
40950
40951           function split(graph, nodeId, wayA, newWayId) {
40952             var wayB = osmWay({
40953               id: newWayId,
40954               tags: wayA.tags
40955             }); // `wayB` is the NEW way
40956
40957             var origNodes = wayA.nodes.slice();
40958             var nodesA;
40959             var nodesB;
40960             var isArea = wayA.isArea();
40961             var isOuter = osmIsOldMultipolygonOuterMember(wayA, graph);
40962
40963             if (wayA.isClosed()) {
40964               var nodes = wayA.nodes.slice(0, -1);
40965               var idxA = nodes.indexOf(nodeId);
40966               var idxB = splitArea(nodes, idxA, graph);
40967
40968               if (idxB < idxA) {
40969                 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
40970                 nodesB = nodes.slice(idxB, idxA + 1);
40971               } else {
40972                 nodesA = nodes.slice(idxA, idxB + 1);
40973                 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
40974               }
40975             } else {
40976               var idx = wayA.nodes.indexOf(nodeId, 1);
40977               nodesA = wayA.nodes.slice(0, idx + 1);
40978               nodesB = wayA.nodes.slice(idx);
40979             }
40980
40981             var lengthA = totalLengthBetweenNodes(graph, nodesA);
40982             var lengthB = totalLengthBetweenNodes(graph, nodesB);
40983
40984             if (_keepHistoryOn === 'longest' && lengthB > lengthA) {
40985               // keep the history on the longer way, regardless of the node count
40986               wayA = wayA.update({
40987                 nodes: nodesB
40988               });
40989               wayB = wayB.update({
40990                 nodes: nodesA
40991               });
40992               var temp = lengthA;
40993               lengthA = lengthB;
40994               lengthB = temp;
40995             } else {
40996               wayA = wayA.update({
40997                 nodes: nodesA
40998               });
40999               wayB = wayB.update({
41000                 nodes: nodesB
41001               });
41002             }
41003
41004             if (wayA.tags.step_count) {
41005               // divide up the the step count proportionally between the two ways
41006               var stepCount = parseFloat(wayA.tags.step_count);
41007
41008               if (stepCount && // ensure a number
41009               isFinite(stepCount) && // ensure positive
41010               stepCount > 0 && // ensure integer
41011               Math.round(stepCount) === stepCount) {
41012                 var tagsA = Object.assign({}, wayA.tags);
41013                 var tagsB = Object.assign({}, wayB.tags);
41014                 var ratioA = lengthA / (lengthA + lengthB);
41015                 var countA = Math.round(stepCount * ratioA);
41016                 tagsA.step_count = countA.toString();
41017                 tagsB.step_count = (stepCount - countA).toString();
41018                 wayA = wayA.update({
41019                   tags: tagsA
41020                 });
41021                 wayB = wayB.update({
41022                   tags: tagsB
41023                 });
41024               }
41025             }
41026
41027             graph = graph.replace(wayA);
41028             graph = graph.replace(wayB);
41029             graph.parentRelations(wayA).forEach(function (relation) {
41030               var member; // Turn restrictions - make sure:
41031               // 1. Splitting a FROM/TO way - only `wayA` OR `wayB` remains in relation
41032               //    (whichever one is connected to the VIA node/ways)
41033               // 2. Splitting a VIA way - `wayB` remains in relation as a VIA way
41034
41035               if (relation.hasFromViaTo()) {
41036                 var f = relation.memberByRole('from');
41037                 var v = relation.membersByRole('via');
41038                 var t = relation.memberByRole('to');
41039                 var i; // 1. split a FROM/TO
41040
41041                 if (f.id === wayA.id || t.id === wayA.id) {
41042                   var keepB = false;
41043
41044                   if (v.length === 1 && v[0].type === 'node') {
41045                     // check via node
41046                     keepB = wayB.contains(v[0].id);
41047                   } else {
41048                     // check via way(s)
41049                     for (i = 0; i < v.length; i++) {
41050                       if (v[i].type === 'way') {
41051                         var wayVia = graph.hasEntity(v[i].id);
41052
41053                         if (wayVia && utilArrayIntersection(wayB.nodes, wayVia.nodes).length) {
41054                           keepB = true;
41055                           break;
41056                         }
41057                       }
41058                     }
41059                   }
41060
41061                   if (keepB) {
41062                     relation = relation.replaceMember(wayA, wayB);
41063                     graph = graph.replace(relation);
41064                   } // 2. split a VIA
41065
41066                 } else {
41067                   for (i = 0; i < v.length; i++) {
41068                     if (v[i].type === 'way' && v[i].id === wayA.id) {
41069                       member = {
41070                         id: wayB.id,
41071                         type: 'way',
41072                         role: 'via'
41073                       };
41074                       graph = actionAddMember(relation.id, member, v[i].index + 1)(graph);
41075                       break;
41076                     }
41077                   }
41078                 } // All other relations (Routes, Multipolygons, etc):
41079                 // 1. Both `wayA` and `wayB` remain in the relation
41080                 // 2. But must be inserted as a pair (see `actionAddMember` for details)
41081
41082               } else {
41083                 if (relation === isOuter) {
41084                   graph = graph.replace(relation.mergeTags(wayA.tags));
41085                   graph = graph.replace(wayA.update({
41086                     tags: {}
41087                   }));
41088                   graph = graph.replace(wayB.update({
41089                     tags: {}
41090                   }));
41091                 }
41092
41093                 member = {
41094                   id: wayB.id,
41095                   type: 'way',
41096                   role: relation.memberById(wayA.id).role
41097                 };
41098                 var insertPair = {
41099                   originalID: wayA.id,
41100                   insertedID: wayB.id,
41101                   nodes: origNodes
41102                 };
41103                 graph = actionAddMember(relation.id, member, undefined, insertPair)(graph);
41104               }
41105             });
41106
41107             if (!isOuter && isArea) {
41108               var multipolygon = osmRelation({
41109                 tags: Object.assign({}, wayA.tags, {
41110                   type: 'multipolygon'
41111                 }),
41112                 members: [{
41113                   id: wayA.id,
41114                   role: 'outer',
41115                   type: 'way'
41116                 }, {
41117                   id: wayB.id,
41118                   role: 'outer',
41119                   type: 'way'
41120                 }]
41121               });
41122               graph = graph.replace(multipolygon);
41123               graph = graph.replace(wayA.update({
41124                 tags: {}
41125               }));
41126               graph = graph.replace(wayB.update({
41127                 tags: {}
41128               }));
41129             }
41130
41131             _createdWayIDs.push(wayB.id);
41132
41133             return graph;
41134           }
41135
41136           var action = function action(graph) {
41137             _createdWayIDs = [];
41138             var newWayIndex = 0;
41139
41140             for (var i = 0; i < nodeIds.length; i++) {
41141               var nodeId = nodeIds[i];
41142               var candidates = action.waysForNode(nodeId, graph);
41143
41144               for (var j = 0; j < candidates.length; j++) {
41145                 graph = split(graph, nodeId, candidates[j], newWayIds && newWayIds[newWayIndex]);
41146                 newWayIndex += 1;
41147               }
41148             }
41149
41150             return graph;
41151           };
41152
41153           action.getCreatedWayIDs = function () {
41154             return _createdWayIDs;
41155           };
41156
41157           action.waysForNode = function (nodeId, graph) {
41158             var node = graph.entity(nodeId);
41159             var splittableParents = graph.parentWays(node).filter(isSplittable);
41160
41161             if (!_wayIDs) {
41162               // If the ways to split aren't specified, only split the lines.
41163               // If there are no lines to split, split the areas.
41164               var hasLine = splittableParents.some(function (parent) {
41165                 return parent.geometry(graph) === 'line';
41166               });
41167
41168               if (hasLine) {
41169                 return splittableParents.filter(function (parent) {
41170                   return parent.geometry(graph) === 'line';
41171                 });
41172               }
41173             }
41174
41175             return splittableParents;
41176
41177             function isSplittable(parent) {
41178               // If the ways to split are specified, ignore everything else.
41179               if (_wayIDs && _wayIDs.indexOf(parent.id) === -1) return false; // We can fake splitting closed ways at their endpoints...
41180
41181               if (parent.isClosed()) return true; // otherwise, we can't split nodes at their endpoints.
41182
41183               for (var i = 1; i < parent.nodes.length - 1; i++) {
41184                 if (parent.nodes[i] === nodeId) return true;
41185               }
41186
41187               return false;
41188             }
41189           };
41190
41191           action.ways = function (graph) {
41192             return utilArrayUniq([].concat.apply([], nodeIds.map(function (nodeId) {
41193               return action.waysForNode(nodeId, graph);
41194             })));
41195           };
41196
41197           action.disabled = function (graph) {
41198             for (var i = 0; i < nodeIds.length; i++) {
41199               var nodeId = nodeIds[i];
41200               var candidates = action.waysForNode(nodeId, graph);
41201
41202               if (candidates.length === 0 || _wayIDs && _wayIDs.length !== candidates.length) {
41203                 return 'not_eligible';
41204               }
41205             }
41206           };
41207
41208           action.limitWays = function (val) {
41209             if (!arguments.length) return _wayIDs;
41210             _wayIDs = val;
41211             return action;
41212           };
41213
41214           action.keepHistoryOn = function (val) {
41215             if (!arguments.length) return _keepHistoryOn;
41216             _keepHistoryOn = val;
41217             return action;
41218           };
41219
41220           return action;
41221         }
41222
41223         function coreGraph(other, mutable) {
41224           if (!(this instanceof coreGraph)) return new coreGraph(other, mutable);
41225
41226           if (other instanceof coreGraph) {
41227             var base = other.base();
41228             this.entities = Object.assign(Object.create(base.entities), other.entities);
41229             this._parentWays = Object.assign(Object.create(base.parentWays), other._parentWays);
41230             this._parentRels = Object.assign(Object.create(base.parentRels), other._parentRels);
41231           } else {
41232             this.entities = Object.create({});
41233             this._parentWays = Object.create({});
41234             this._parentRels = Object.create({});
41235             this.rebase(other || [], [this]);
41236           }
41237
41238           this.transients = {};
41239           this._childNodes = {};
41240           this.frozen = !mutable;
41241         }
41242         coreGraph.prototype = {
41243           hasEntity: function hasEntity(id) {
41244             return this.entities[id];
41245           },
41246           entity: function entity(id) {
41247             var entity = this.entities[id]; //https://github.com/openstreetmap/iD/issues/3973#issuecomment-307052376
41248
41249             if (!entity) {
41250               entity = this.entities.__proto__[id]; // eslint-disable-line no-proto
41251             }
41252
41253             if (!entity) {
41254               throw new Error('entity ' + id + ' not found');
41255             }
41256
41257             return entity;
41258           },
41259           geometry: function geometry(id) {
41260             return this.entity(id).geometry(this);
41261           },
41262           "transient": function transient(entity, key, fn) {
41263             var id = entity.id;
41264             var transients = this.transients[id] || (this.transients[id] = {});
41265
41266             if (transients[key] !== undefined) {
41267               return transients[key];
41268             }
41269
41270             transients[key] = fn.call(entity);
41271             return transients[key];
41272           },
41273           parentWays: function parentWays(entity) {
41274             var parents = this._parentWays[entity.id];
41275             var result = [];
41276
41277             if (parents) {
41278               parents.forEach(function (id) {
41279                 result.push(this.entity(id));
41280               }, this);
41281             }
41282
41283             return result;
41284           },
41285           isPoi: function isPoi(entity) {
41286             var parents = this._parentWays[entity.id];
41287             return !parents || parents.size === 0;
41288           },
41289           isShared: function isShared(entity) {
41290             var parents = this._parentWays[entity.id];
41291             return parents && parents.size > 1;
41292           },
41293           parentRelations: function parentRelations(entity) {
41294             var parents = this._parentRels[entity.id];
41295             var result = [];
41296
41297             if (parents) {
41298               parents.forEach(function (id) {
41299                 result.push(this.entity(id));
41300               }, this);
41301             }
41302
41303             return result;
41304           },
41305           parentMultipolygons: function parentMultipolygons(entity) {
41306             return this.parentRelations(entity).filter(function (relation) {
41307               return relation.isMultipolygon();
41308             });
41309           },
41310           childNodes: function childNodes(entity) {
41311             if (this._childNodes[entity.id]) return this._childNodes[entity.id];
41312             if (!entity.nodes) return [];
41313             var nodes = [];
41314
41315             for (var i = 0; i < entity.nodes.length; i++) {
41316               nodes[i] = this.entity(entity.nodes[i]);
41317             }
41318             this._childNodes[entity.id] = nodes;
41319             return this._childNodes[entity.id];
41320           },
41321           base: function base() {
41322             return {
41323               'entities': Object.getPrototypeOf(this.entities),
41324               'parentWays': Object.getPrototypeOf(this._parentWays),
41325               'parentRels': Object.getPrototypeOf(this._parentRels)
41326             };
41327           },
41328           // Unlike other graph methods, rebase mutates in place. This is because it
41329           // is used only during the history operation that merges newly downloaded
41330           // data into each state. To external consumers, it should appear as if the
41331           // graph always contained the newly downloaded data.
41332           rebase: function rebase(entities, stack, force) {
41333             var base = this.base();
41334             var i, j, k, id;
41335
41336             for (i = 0; i < entities.length; i++) {
41337               var entity = entities[i];
41338               if (!entity.visible || !force && base.entities[entity.id]) continue; // Merging data into the base graph
41339
41340               base.entities[entity.id] = entity;
41341
41342               this._updateCalculated(undefined, entity, base.parentWays, base.parentRels); // Restore provisionally-deleted nodes that are discovered to have an extant parent
41343
41344
41345               if (entity.type === 'way') {
41346                 for (j = 0; j < entity.nodes.length; j++) {
41347                   id = entity.nodes[j];
41348
41349                   for (k = 1; k < stack.length; k++) {
41350                     var ents = stack[k].entities;
41351
41352                     if (ents.hasOwnProperty(id) && ents[id] === undefined) {
41353                       delete ents[id];
41354                     }
41355                   }
41356                 }
41357               }
41358             }
41359
41360             for (i = 0; i < stack.length; i++) {
41361               stack[i]._updateRebased();
41362             }
41363           },
41364           _updateRebased: function _updateRebased() {
41365             var base = this.base();
41366             Object.keys(this._parentWays).forEach(function (child) {
41367               if (base.parentWays[child]) {
41368                 base.parentWays[child].forEach(function (id) {
41369                   if (!this.entities.hasOwnProperty(id)) {
41370                     this._parentWays[child].add(id);
41371                   }
41372                 }, this);
41373               }
41374             }, this);
41375             Object.keys(this._parentRels).forEach(function (child) {
41376               if (base.parentRels[child]) {
41377                 base.parentRels[child].forEach(function (id) {
41378                   if (!this.entities.hasOwnProperty(id)) {
41379                     this._parentRels[child].add(id);
41380                   }
41381                 }, this);
41382               }
41383             }, this);
41384             this.transients = {}; // this._childNodes is not updated, under the assumption that
41385             // ways are always downloaded with their child nodes.
41386           },
41387           // Updates calculated properties (parentWays, parentRels) for the specified change
41388           _updateCalculated: function _updateCalculated(oldentity, entity, parentWays, parentRels) {
41389             parentWays = parentWays || this._parentWays;
41390             parentRels = parentRels || this._parentRels;
41391             var type = entity && entity.type || oldentity && oldentity.type;
41392             var removed, added, i;
41393
41394             if (type === 'way') {
41395               // Update parentWays
41396               if (oldentity && entity) {
41397                 removed = utilArrayDifference(oldentity.nodes, entity.nodes);
41398                 added = utilArrayDifference(entity.nodes, oldentity.nodes);
41399               } else if (oldentity) {
41400                 removed = oldentity.nodes;
41401                 added = [];
41402               } else if (entity) {
41403                 removed = [];
41404                 added = entity.nodes;
41405               }
41406
41407               for (i = 0; i < removed.length; i++) {
41408                 // make a copy of prototype property, store as own property, and update..
41409                 parentWays[removed[i]] = new Set(parentWays[removed[i]]);
41410                 parentWays[removed[i]]["delete"](oldentity.id);
41411               }
41412
41413               for (i = 0; i < added.length; i++) {
41414                 // make a copy of prototype property, store as own property, and update..
41415                 parentWays[added[i]] = new Set(parentWays[added[i]]);
41416                 parentWays[added[i]].add(entity.id);
41417               }
41418             } else if (type === 'relation') {
41419               // Update parentRels
41420               // diff only on the IDs since the same entity can be a member multiple times with different roles
41421               var oldentityMemberIDs = oldentity ? oldentity.members.map(function (m) {
41422                 return m.id;
41423               }) : [];
41424               var entityMemberIDs = entity ? entity.members.map(function (m) {
41425                 return m.id;
41426               }) : [];
41427
41428               if (oldentity && entity) {
41429                 removed = utilArrayDifference(oldentityMemberIDs, entityMemberIDs);
41430                 added = utilArrayDifference(entityMemberIDs, oldentityMemberIDs);
41431               } else if (oldentity) {
41432                 removed = oldentityMemberIDs;
41433                 added = [];
41434               } else if (entity) {
41435                 removed = [];
41436                 added = entityMemberIDs;
41437               }
41438
41439               for (i = 0; i < removed.length; i++) {
41440                 // make a copy of prototype property, store as own property, and update..
41441                 parentRels[removed[i]] = new Set(parentRels[removed[i]]);
41442                 parentRels[removed[i]]["delete"](oldentity.id);
41443               }
41444
41445               for (i = 0; i < added.length; i++) {
41446                 // make a copy of prototype property, store as own property, and update..
41447                 parentRels[added[i]] = new Set(parentRels[added[i]]);
41448                 parentRels[added[i]].add(entity.id);
41449               }
41450             }
41451           },
41452           replace: function replace(entity) {
41453             if (this.entities[entity.id] === entity) return this;
41454             return this.update(function () {
41455               this._updateCalculated(this.entities[entity.id], entity);
41456
41457               this.entities[entity.id] = entity;
41458             });
41459           },
41460           remove: function remove(entity) {
41461             return this.update(function () {
41462               this._updateCalculated(entity, undefined);
41463
41464               this.entities[entity.id] = undefined;
41465             });
41466           },
41467           revert: function revert(id) {
41468             var baseEntity = this.base().entities[id];
41469             var headEntity = this.entities[id];
41470             if (headEntity === baseEntity) return this;
41471             return this.update(function () {
41472               this._updateCalculated(headEntity, baseEntity);
41473
41474               delete this.entities[id];
41475             });
41476           },
41477           update: function update() {
41478             var graph = this.frozen ? coreGraph(this, true) : this;
41479
41480             for (var i = 0; i < arguments.length; i++) {
41481               arguments[i].call(graph, graph);
41482             }
41483
41484             if (this.frozen) graph.frozen = true;
41485             return graph;
41486           },
41487           // Obliterates any existing entities
41488           load: function load(entities) {
41489             var base = this.base();
41490             this.entities = Object.create(base.entities);
41491
41492             for (var i in entities) {
41493               this.entities[i] = entities[i];
41494
41495               this._updateCalculated(base.entities[i], this.entities[i]);
41496             }
41497
41498             return this;
41499           }
41500         };
41501
41502         function osmTurn(turn) {
41503           if (!(this instanceof osmTurn)) {
41504             return new osmTurn(turn);
41505           }
41506
41507           Object.assign(this, turn);
41508         }
41509         function osmIntersection(graph, startVertexId, maxDistance) {
41510           maxDistance = maxDistance || 30; // in meters
41511
41512           var vgraph = coreGraph(); // virtual graph
41513
41514           var i, j, k;
41515
41516           function memberOfRestriction(entity) {
41517             return graph.parentRelations(entity).some(function (r) {
41518               return r.isRestriction();
41519             });
41520           }
41521
41522           function isRoad(way) {
41523             if (way.isArea() || way.isDegenerate()) return false;
41524             var roads = {
41525               'motorway': true,
41526               'motorway_link': true,
41527               'trunk': true,
41528               'trunk_link': true,
41529               'primary': true,
41530               'primary_link': true,
41531               'secondary': true,
41532               'secondary_link': true,
41533               'tertiary': true,
41534               'tertiary_link': true,
41535               'residential': true,
41536               'unclassified': true,
41537               'living_street': true,
41538               'service': true,
41539               'road': true,
41540               'track': true
41541             };
41542             return roads[way.tags.highway];
41543           }
41544
41545           var startNode = graph.entity(startVertexId);
41546           var checkVertices = [startNode];
41547           var checkWays;
41548           var vertices = [];
41549           var vertexIds = [];
41550           var vertex;
41551           var ways = [];
41552           var wayIds = [];
41553           var way;
41554           var nodes = [];
41555           var node;
41556           var parents = [];
41557           var parent; // `actions` will store whatever actions must be performed to satisfy
41558           // preconditions for adding a turn restriction to this intersection.
41559           //  - Remove any existing degenerate turn restrictions (missing from/to, etc)
41560           //  - Reverse oneways so that they are drawn in the forward direction
41561           //  - Split ways on key vertices
41562
41563           var actions = []; // STEP 1:  walk the graph outwards from starting vertex to search
41564           //  for more key vertices and ways to include in the intersection..
41565
41566           while (checkVertices.length) {
41567             vertex = checkVertices.pop(); // check this vertex for parent ways that are roads
41568
41569             checkWays = graph.parentWays(vertex);
41570             var hasWays = false;
41571
41572             for (i = 0; i < checkWays.length; i++) {
41573               way = checkWays[i];
41574               if (!isRoad(way) && !memberOfRestriction(way)) continue;
41575               ways.push(way); // it's a road, or it's already in a turn restriction
41576
41577               hasWays = true; // check the way's children for more key vertices
41578
41579               nodes = utilArrayUniq(graph.childNodes(way));
41580
41581               for (j = 0; j < nodes.length; j++) {
41582                 node = nodes[j];
41583                 if (node === vertex) continue; // same thing
41584
41585                 if (vertices.indexOf(node) !== -1) continue; // seen it already
41586
41587                 if (geoSphericalDistance(node.loc, startNode.loc) > maxDistance) continue; // too far from start
41588                 // a key vertex will have parents that are also roads
41589
41590                 var hasParents = false;
41591                 parents = graph.parentWays(node);
41592
41593                 for (k = 0; k < parents.length; k++) {
41594                   parent = parents[k];
41595                   if (parent === way) continue; // same thing
41596
41597                   if (ways.indexOf(parent) !== -1) continue; // seen it already
41598
41599                   if (!isRoad(parent)) continue; // not a road
41600
41601                   hasParents = true;
41602                   break;
41603                 }
41604
41605                 if (hasParents) {
41606                   checkVertices.push(node);
41607                 }
41608               }
41609             }
41610
41611             if (hasWays) {
41612               vertices.push(vertex);
41613             }
41614           }
41615
41616           vertices = utilArrayUniq(vertices);
41617           ways = utilArrayUniq(ways); // STEP 2:  Build a virtual graph containing only the entities in the intersection..
41618           // Everything done after this step should act on the virtual graph
41619           // Any actions that must be performed later to the main graph go in `actions` array
41620
41621           ways.forEach(function (way) {
41622             graph.childNodes(way).forEach(function (node) {
41623               vgraph = vgraph.replace(node);
41624             });
41625             vgraph = vgraph.replace(way);
41626             graph.parentRelations(way).forEach(function (relation) {
41627               if (relation.isRestriction()) {
41628                 if (relation.isValidRestriction(graph)) {
41629                   vgraph = vgraph.replace(relation);
41630                 } else if (relation.isComplete(graph)) {
41631                   actions.push(actionDeleteRelation(relation.id));
41632                 }
41633               }
41634             });
41635           }); // STEP 3:  Force all oneways to be drawn in the forward direction
41636
41637           ways.forEach(function (w) {
41638             var way = vgraph.entity(w.id);
41639
41640             if (way.tags.oneway === '-1') {
41641               var action = actionReverse(way.id, {
41642                 reverseOneway: true
41643               });
41644               actions.push(action);
41645               vgraph = action(vgraph);
41646             }
41647           }); // STEP 4:  Split ways on key vertices
41648
41649           var origCount = osmEntity.id.next.way;
41650           vertices.forEach(function (v) {
41651             // This is an odd way to do it, but we need to find all the ways that
41652             // will be split here, then split them one at a time to ensure that these
41653             // actions can be replayed on the main graph exactly in the same order.
41654             // (It is unintuitive, but the order of ways returned from graph.parentWays()
41655             // is arbitrary, depending on how the main graph and vgraph were built)
41656             var splitAll = actionSplit([v.id]).keepHistoryOn('first');
41657
41658             if (!splitAll.disabled(vgraph)) {
41659               splitAll.ways(vgraph).forEach(function (way) {
41660                 var splitOne = actionSplit([v.id]).limitWays([way.id]).keepHistoryOn('first');
41661                 actions.push(splitOne);
41662                 vgraph = splitOne(vgraph);
41663               });
41664             }
41665           }); // In here is where we should also split the intersection at nearby junction.
41666           //   for https://github.com/mapbox/iD-internal/issues/31
41667           // nearbyVertices.forEach(function(v) {
41668           // });
41669           // Reasons why we reset the way id count here:
41670           //  1. Continuity with way ids created by the splits so that we can replay
41671           //     these actions later if the user decides to create a turn restriction
41672           //  2. Avoids churning way ids just by hovering over a vertex
41673           //     and displaying the turn restriction editor
41674
41675           osmEntity.id.next.way = origCount; // STEP 5:  Update arrays to point to vgraph entities
41676
41677           vertexIds = vertices.map(function (v) {
41678             return v.id;
41679           });
41680           vertices = [];
41681           ways = [];
41682           vertexIds.forEach(function (id) {
41683             var vertex = vgraph.entity(id);
41684             var parents = vgraph.parentWays(vertex);
41685             vertices.push(vertex);
41686             ways = ways.concat(parents);
41687           });
41688           vertices = utilArrayUniq(vertices);
41689           ways = utilArrayUniq(ways);
41690           vertexIds = vertices.map(function (v) {
41691             return v.id;
41692           });
41693           wayIds = ways.map(function (w) {
41694             return w.id;
41695           }); // STEP 6:  Update the ways with some metadata that will be useful for
41696           // walking the intersection graph later and rendering turn arrows.
41697
41698           function withMetadata(way, vertexIds) {
41699             var __oneWay = way.isOneWay(); // which affixes are key vertices?
41700
41701
41702             var __first = vertexIds.indexOf(way.first()) !== -1;
41703
41704             var __last = vertexIds.indexOf(way.last()) !== -1; // what roles is this way eligible for?
41705
41706
41707             var __via = __first && __last;
41708
41709             var __from = __first && !__oneWay || __last;
41710
41711             var __to = __first || __last && !__oneWay;
41712
41713             return way.update({
41714               __first: __first,
41715               __last: __last,
41716               __from: __from,
41717               __via: __via,
41718               __to: __to,
41719               __oneWay: __oneWay
41720             });
41721           }
41722
41723           ways = [];
41724           wayIds.forEach(function (id) {
41725             var way = withMetadata(vgraph.entity(id), vertexIds);
41726             vgraph = vgraph.replace(way);
41727             ways.push(way);
41728           }); // STEP 7:  Simplify - This is an iterative process where we:
41729           //  1. Find trivial vertices with only 2 parents
41730           //  2. trim off the leaf way from those vertices and remove from vgraph
41731
41732           var keepGoing;
41733           var removeWayIds = [];
41734           var removeVertexIds = [];
41735
41736           do {
41737             keepGoing = false;
41738             checkVertices = vertexIds.slice();
41739
41740             for (i = 0; i < checkVertices.length; i++) {
41741               var vertexId = checkVertices[i];
41742               vertex = vgraph.hasEntity(vertexId);
41743
41744               if (!vertex) {
41745                 if (vertexIds.indexOf(vertexId) !== -1) {
41746                   vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one
41747                 }
41748
41749                 removeVertexIds.push(vertexId);
41750                 continue;
41751               }
41752
41753               parents = vgraph.parentWays(vertex);
41754
41755               if (parents.length < 3) {
41756                 if (vertexIds.indexOf(vertexId) !== -1) {
41757                   vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one
41758                 }
41759               }
41760
41761               if (parents.length === 2) {
41762                 // vertex with 2 parents is trivial
41763                 var a = parents[0];
41764                 var b = parents[1];
41765                 var aIsLeaf = a && !a.__via;
41766                 var bIsLeaf = b && !b.__via;
41767                 var leaf, survivor;
41768
41769                 if (aIsLeaf && !bIsLeaf) {
41770                   leaf = a;
41771                   survivor = b;
41772                 } else if (!aIsLeaf && bIsLeaf) {
41773                   leaf = b;
41774                   survivor = a;
41775                 }
41776
41777                 if (leaf && survivor) {
41778                   survivor = withMetadata(survivor, vertexIds); // update survivor way
41779
41780                   vgraph = vgraph.replace(survivor).remove(leaf); // update graph
41781
41782                   removeWayIds.push(leaf.id);
41783                   keepGoing = true;
41784                 }
41785               }
41786
41787               parents = vgraph.parentWays(vertex);
41788
41789               if (parents.length < 2) {
41790                 // vertex is no longer a key vertex
41791                 if (vertexIds.indexOf(vertexId) !== -1) {
41792                   vertexIds.splice(vertexIds.indexOf(vertexId), 1); // stop checking this one
41793                 }
41794
41795                 removeVertexIds.push(vertexId);
41796                 keepGoing = true;
41797               }
41798
41799               if (parents.length < 1) {
41800                 // vertex is no longer attached to anything
41801                 vgraph = vgraph.remove(vertex);
41802               }
41803             }
41804           } while (keepGoing);
41805
41806           vertices = vertices.filter(function (vertex) {
41807             return removeVertexIds.indexOf(vertex.id) === -1;
41808           }).map(function (vertex) {
41809             return vgraph.entity(vertex.id);
41810           });
41811           ways = ways.filter(function (way) {
41812             return removeWayIds.indexOf(way.id) === -1;
41813           }).map(function (way) {
41814             return vgraph.entity(way.id);
41815           }); // OK!  Here is our intersection..
41816
41817           var intersection = {
41818             graph: vgraph,
41819             actions: actions,
41820             vertices: vertices,
41821             ways: ways
41822           }; // Get all the valid turns through this intersection given a starting way id.
41823           // This operates on the virtual graph for everything.
41824           //
41825           // Basically, walk through all possible paths from starting way,
41826           //   honoring the existing turn restrictions as we go (watch out for loops!)
41827           //
41828           // For each path found, generate and return a `osmTurn` datastructure.
41829           //
41830
41831           intersection.turns = function (fromWayId, maxViaWay) {
41832             if (!fromWayId) return [];
41833             if (!maxViaWay) maxViaWay = 0;
41834             var vgraph = intersection.graph;
41835             var keyVertexIds = intersection.vertices.map(function (v) {
41836               return v.id;
41837             });
41838             var start = vgraph.entity(fromWayId);
41839             if (!start || !(start.__from || start.__via)) return []; // maxViaWay=0   from-*-to              (0 vias)
41840             // maxViaWay=1   from-*-via-*-to        (1 via max)
41841             // maxViaWay=2   from-*-via-*-via-*-to  (2 vias max)
41842
41843             var maxPathLength = maxViaWay * 2 + 3;
41844             var turns = [];
41845             step(start);
41846             return turns; // traverse the intersection graph and find all the valid paths
41847
41848             function step(entity, currPath, currRestrictions, matchedRestriction) {
41849               currPath = (currPath || []).slice(); // shallow copy
41850
41851               if (currPath.length >= maxPathLength) return;
41852               currPath.push(entity.id);
41853               currRestrictions = (currRestrictions || []).slice(); // shallow copy
41854
41855               var i, j;
41856
41857               if (entity.type === 'node') {
41858                 var parents = vgraph.parentWays(entity);
41859                 var nextWays = []; // which ways can we step into?
41860
41861                 for (i = 0; i < parents.length; i++) {
41862                   var way = parents[i]; // if next way is a oneway incoming to this vertex, skip
41863
41864                   if (way.__oneWay && way.nodes[0] !== entity.id) continue; // if we have seen it before (allowing for an initial u-turn), skip
41865
41866                   if (currPath.indexOf(way.id) !== -1 && currPath.length >= 3) continue; // Check all "current" restrictions (where we've already walked the `FROM`)
41867
41868                   var restrict = null;
41869
41870                   for (j = 0; j < currRestrictions.length; j++) {
41871                     var restriction = currRestrictions[j];
41872                     var f = restriction.memberByRole('from');
41873                     var v = restriction.membersByRole('via');
41874                     var t = restriction.memberByRole('to');
41875                     var isOnly = /^only_/.test(restriction.tags.restriction); // Does the current path match this turn restriction?
41876
41877                     var matchesFrom = f.id === fromWayId;
41878                     var matchesViaTo = false;
41879                     var isAlongOnlyPath = false;
41880
41881                     if (t.id === way.id) {
41882                       // match TO
41883                       if (v.length === 1 && v[0].type === 'node') {
41884                         // match VIA node
41885                         matchesViaTo = v[0].id === entity.id && (matchesFrom && currPath.length === 2 || !matchesFrom && currPath.length > 2);
41886                       } else {
41887                         // match all VIA ways
41888                         var pathVias = [];
41889
41890                         for (k = 2; k < currPath.length; k += 2) {
41891                           // k = 2 skips FROM
41892                           pathVias.push(currPath[k]); // (path goes way-node-way...)
41893                         }
41894
41895                         var restrictionVias = [];
41896
41897                         for (k = 0; k < v.length; k++) {
41898                           if (v[k].type === 'way') {
41899                             restrictionVias.push(v[k].id);
41900                           }
41901                         }
41902
41903                         var diff = utilArrayDifference(pathVias, restrictionVias);
41904                         matchesViaTo = !diff.length;
41905                       }
41906                     } else if (isOnly) {
41907                       for (k = 0; k < v.length; k++) {
41908                         // way doesn't match TO, but is one of the via ways along the path of an "only"
41909                         if (v[k].type === 'way' && v[k].id === way.id) {
41910                           isAlongOnlyPath = true;
41911                           break;
41912                         }
41913                       }
41914                     }
41915
41916                     if (matchesViaTo) {
41917                       if (isOnly) {
41918                         restrict = {
41919                           id: restriction.id,
41920                           direct: matchesFrom,
41921                           from: f.id,
41922                           only: true,
41923                           end: true
41924                         };
41925                       } else {
41926                         restrict = {
41927                           id: restriction.id,
41928                           direct: matchesFrom,
41929                           from: f.id,
41930                           no: true,
41931                           end: true
41932                         };
41933                       }
41934                     } else {
41935                       // indirect - caused by a different nearby restriction
41936                       if (isAlongOnlyPath) {
41937                         restrict = {
41938                           id: restriction.id,
41939                           direct: false,
41940                           from: f.id,
41941                           only: true,
41942                           end: false
41943                         };
41944                       } else if (isOnly) {
41945                         restrict = {
41946                           id: restriction.id,
41947                           direct: false,
41948                           from: f.id,
41949                           no: true,
41950                           end: true
41951                         };
41952                       }
41953                     } // stop looking if we find a "direct" restriction (matching FROM, VIA, TO)
41954
41955
41956                     if (restrict && restrict.direct) break;
41957                   }
41958
41959                   nextWays.push({
41960                     way: way,
41961                     restrict: restrict
41962                   });
41963                 }
41964
41965                 nextWays.forEach(function (nextWay) {
41966                   step(nextWay.way, currPath, currRestrictions, nextWay.restrict);
41967                 });
41968               } else {
41969                 // entity.type === 'way'
41970                 if (currPath.length >= 3) {
41971                   // this is a "complete" path..
41972                   var turnPath = currPath.slice(); // shallow copy
41973                   // an indirect restriction - only include the partial path (starting at FROM)
41974
41975                   if (matchedRestriction && matchedRestriction.direct === false) {
41976                     for (i = 0; i < turnPath.length; i++) {
41977                       if (turnPath[i] === matchedRestriction.from) {
41978                         turnPath = turnPath.slice(i);
41979                         break;
41980                       }
41981                     }
41982                   }
41983
41984                   var turn = pathToTurn(turnPath);
41985
41986                   if (turn) {
41987                     if (matchedRestriction) {
41988                       turn.restrictionID = matchedRestriction.id;
41989                       turn.no = matchedRestriction.no;
41990                       turn.only = matchedRestriction.only;
41991                       turn.direct = matchedRestriction.direct;
41992                     }
41993
41994                     turns.push(osmTurn(turn));
41995                   }
41996
41997                   if (currPath[0] === currPath[2]) return; // if we made a u-turn - stop here
41998                 }
41999
42000                 if (matchedRestriction && matchedRestriction.end) return; // don't advance any further
42001                 // which nodes can we step into?
42002
42003                 var n1 = vgraph.entity(entity.first());
42004                 var n2 = vgraph.entity(entity.last());
42005                 var dist = geoSphericalDistance(n1.loc, n2.loc);
42006                 var nextNodes = [];
42007
42008                 if (currPath.length > 1) {
42009                   if (dist > maxDistance) return; // the next node is too far
42010
42011                   if (!entity.__via) return; // this way is a leaf / can't be a via
42012                 }
42013
42014                 if (!entity.__oneWay && // bidirectional..
42015                 keyVertexIds.indexOf(n1.id) !== -1 && // key vertex..
42016                 currPath.indexOf(n1.id) === -1) {
42017                   // haven't seen it yet..
42018                   nextNodes.push(n1); // can advance to first node
42019                 }
42020
42021                 if (keyVertexIds.indexOf(n2.id) !== -1 && // key vertex..
42022                 currPath.indexOf(n2.id) === -1) {
42023                   // haven't seen it yet..
42024                   nextNodes.push(n2); // can advance to last node
42025                 }
42026
42027                 nextNodes.forEach(function (nextNode) {
42028                   // gather restrictions FROM this way
42029                   var fromRestrictions = vgraph.parentRelations(entity).filter(function (r) {
42030                     if (!r.isRestriction()) return false;
42031                     var f = r.memberByRole('from');
42032                     if (!f || f.id !== entity.id) return false;
42033                     var isOnly = /^only_/.test(r.tags.restriction);
42034                     if (!isOnly) return true; // `only_` restrictions only matter along the direction of the VIA - #4849
42035
42036                     var isOnlyVia = false;
42037                     var v = r.membersByRole('via');
42038
42039                     if (v.length === 1 && v[0].type === 'node') {
42040                       // via node
42041                       isOnlyVia = v[0].id === nextNode.id;
42042                     } else {
42043                       // via way(s)
42044                       for (var i = 0; i < v.length; i++) {
42045                         if (v[i].type !== 'way') continue;
42046                         var viaWay = vgraph.entity(v[i].id);
42047
42048                         if (viaWay.first() === nextNode.id || viaWay.last() === nextNode.id) {
42049                           isOnlyVia = true;
42050                           break;
42051                         }
42052                       }
42053                     }
42054
42055                     return isOnlyVia;
42056                   });
42057                   step(nextNode, currPath, currRestrictions.concat(fromRestrictions), false);
42058                 });
42059               }
42060             } // assumes path is alternating way-node-way of odd length
42061
42062
42063             function pathToTurn(path) {
42064               if (path.length < 3) return;
42065               var fromWayId, fromNodeId, fromVertexId;
42066               var toWayId, toNodeId, toVertexId;
42067               var viaWayIds, viaNodeId, isUturn;
42068               fromWayId = path[0];
42069               toWayId = path[path.length - 1];
42070
42071               if (path.length === 3 && fromWayId === toWayId) {
42072                 // u turn
42073                 var way = vgraph.entity(fromWayId);
42074                 if (way.__oneWay) return null;
42075                 isUturn = true;
42076                 viaNodeId = fromVertexId = toVertexId = path[1];
42077                 fromNodeId = toNodeId = adjacentNode(fromWayId, viaNodeId);
42078               } else {
42079                 isUturn = false;
42080                 fromVertexId = path[1];
42081                 fromNodeId = adjacentNode(fromWayId, fromVertexId);
42082                 toVertexId = path[path.length - 2];
42083                 toNodeId = adjacentNode(toWayId, toVertexId);
42084
42085                 if (path.length === 3) {
42086                   viaNodeId = path[1];
42087                 } else {
42088                   viaWayIds = path.filter(function (entityId) {
42089                     return entityId[0] === 'w';
42090                   });
42091                   viaWayIds = viaWayIds.slice(1, viaWayIds.length - 1); // remove first, last
42092                 }
42093               }
42094
42095               return {
42096                 key: path.join('_'),
42097                 path: path,
42098                 from: {
42099                   node: fromNodeId,
42100                   way: fromWayId,
42101                   vertex: fromVertexId
42102                 },
42103                 via: {
42104                   node: viaNodeId,
42105                   ways: viaWayIds
42106                 },
42107                 to: {
42108                   node: toNodeId,
42109                   way: toWayId,
42110                   vertex: toVertexId
42111                 },
42112                 u: isUturn
42113               };
42114
42115               function adjacentNode(wayId, affixId) {
42116                 var nodes = vgraph.entity(wayId).nodes;
42117                 return affixId === nodes[0] ? nodes[1] : nodes[nodes.length - 2];
42118               }
42119             }
42120           };
42121
42122           return intersection;
42123         }
42124         function osmInferRestriction(graph, turn, projection) {
42125           var fromWay = graph.entity(turn.from.way);
42126           var fromNode = graph.entity(turn.from.node);
42127           var fromVertex = graph.entity(turn.from.vertex);
42128           var toWay = graph.entity(turn.to.way);
42129           var toNode = graph.entity(turn.to.node);
42130           var toVertex = graph.entity(turn.to.vertex);
42131           var fromOneWay = fromWay.tags.oneway === 'yes';
42132           var toOneWay = toWay.tags.oneway === 'yes';
42133           var angle = (geoAngle(fromVertex, fromNode, projection) - geoAngle(toVertex, toNode, projection)) * 180 / Math.PI;
42134
42135           while (angle < 0) {
42136             angle += 360;
42137           }
42138
42139           if (fromNode === toNode) {
42140             return 'no_u_turn';
42141           }
42142
42143           if ((angle < 23 || angle > 336) && fromOneWay && toOneWay) {
42144             return 'no_u_turn'; // wider tolerance for u-turn if both ways are oneway
42145           }
42146
42147           if ((angle < 40 || angle > 319) && fromOneWay && toOneWay && turn.from.vertex !== turn.to.vertex) {
42148             return 'no_u_turn'; // even wider tolerance for u-turn if there is a via way (from !== to)
42149           }
42150
42151           if (angle < 158) {
42152             return 'no_right_turn';
42153           }
42154
42155           if (angle > 202) {
42156             return 'no_left_turn';
42157           }
42158
42159           return 'no_straight_on';
42160         }
42161
42162         function actionMergePolygon(ids, newRelationId) {
42163           function groupEntities(graph) {
42164             var entities = ids.map(function (id) {
42165               return graph.entity(id);
42166             });
42167             var geometryGroups = utilArrayGroupBy(entities, function (entity) {
42168               if (entity.type === 'way' && entity.isClosed()) {
42169                 return 'closedWay';
42170               } else if (entity.type === 'relation' && entity.isMultipolygon()) {
42171                 return 'multipolygon';
42172               } else {
42173                 return 'other';
42174               }
42175             });
42176             return Object.assign({
42177               closedWay: [],
42178               multipolygon: [],
42179               other: []
42180             }, geometryGroups);
42181           }
42182
42183           var action = function action(graph) {
42184             var entities = groupEntities(graph); // An array representing all the polygons that are part of the multipolygon.
42185             //
42186             // Each element is itself an array of objects with an id property, and has a
42187             // locs property which is an array of the locations forming the polygon.
42188
42189             var polygons = entities.multipolygon.reduce(function (polygons, m) {
42190               return polygons.concat(osmJoinWays(m.members, graph));
42191             }, []).concat(entities.closedWay.map(function (d) {
42192               var member = [{
42193                 id: d.id
42194               }];
42195               member.nodes = graph.childNodes(d);
42196               return member;
42197             })); // contained is an array of arrays of boolean values,
42198             // where contained[j][k] is true iff the jth way is
42199             // contained by the kth way.
42200
42201             var contained = polygons.map(function (w, i) {
42202               return polygons.map(function (d, n) {
42203                 if (i === n) return null;
42204                 return geoPolygonContainsPolygon(d.nodes.map(function (n) {
42205                   return n.loc;
42206                 }), w.nodes.map(function (n) {
42207                   return n.loc;
42208                 }));
42209               });
42210             }); // Sort all polygons as either outer or inner ways
42211
42212             var members = [];
42213             var outer = true;
42214
42215             while (polygons.length) {
42216               extractUncontained(polygons);
42217               polygons = polygons.filter(isContained);
42218               contained = contained.filter(isContained).map(filterContained);
42219             }
42220
42221             function isContained(d, i) {
42222               return contained[i].some(function (val) {
42223                 return val;
42224               });
42225             }
42226
42227             function filterContained(d) {
42228               return d.filter(isContained);
42229             }
42230
42231             function extractUncontained(polygons) {
42232               polygons.forEach(function (d, i) {
42233                 if (!isContained(d, i)) {
42234                   d.forEach(function (member) {
42235                     members.push({
42236                       type: 'way',
42237                       id: member.id,
42238                       role: outer ? 'outer' : 'inner'
42239                     });
42240                   });
42241                 }
42242               });
42243               outer = !outer;
42244             } // Move all tags to one relation.
42245             // Keep the oldest multipolygon alive if it exists.
42246
42247
42248             var relation;
42249
42250             if (entities.multipolygon.length > 0) {
42251               var oldestID = utilOldestID(entities.multipolygon.map(function (entity) {
42252                 return entity.id;
42253               }));
42254               relation = entities.multipolygon.find(function (entity) {
42255                 return entity.id === oldestID;
42256               });
42257             } else {
42258               relation = osmRelation({
42259                 id: newRelationId,
42260                 tags: {
42261                   type: 'multipolygon'
42262                 }
42263               });
42264             }
42265
42266             entities.multipolygon.forEach(function (m) {
42267               if (m.id !== relation.id) {
42268                 relation = relation.mergeTags(m.tags);
42269                 graph = graph.remove(m);
42270               }
42271             });
42272             entities.closedWay.forEach(function (way) {
42273               function isThisOuter(m) {
42274                 return m.id === way.id && m.role !== 'inner';
42275               }
42276
42277               if (members.some(isThisOuter)) {
42278                 relation = relation.mergeTags(way.tags);
42279                 graph = graph.replace(way.update({
42280                   tags: {}
42281                 }));
42282               }
42283             });
42284             return graph.replace(relation.update({
42285               members: members,
42286               tags: utilObjectOmit(relation.tags, ['area'])
42287             }));
42288           };
42289
42290           action.disabled = function (graph) {
42291             var entities = groupEntities(graph);
42292
42293             if (entities.other.length > 0 || entities.closedWay.length + entities.multipolygon.length < 2) {
42294               return 'not_eligible';
42295             }
42296
42297             if (!entities.multipolygon.every(function (r) {
42298               return r.isComplete(graph);
42299             })) {
42300               return 'incomplete_relation';
42301             }
42302
42303             if (!entities.multipolygon.length) {
42304               var sharedMultipolygons = [];
42305               entities.closedWay.forEach(function (way, i) {
42306                 if (i === 0) {
42307                   sharedMultipolygons = graph.parentMultipolygons(way);
42308                 } else {
42309                   sharedMultipolygons = utilArrayIntersection(sharedMultipolygons, graph.parentMultipolygons(way));
42310                 }
42311               });
42312               sharedMultipolygons = sharedMultipolygons.filter(function (relation) {
42313                 return relation.members.length === entities.closedWay.length;
42314               });
42315
42316               if (sharedMultipolygons.length) {
42317                 // don't create a new multipolygon if it'd be redundant
42318                 return 'not_eligible';
42319               }
42320             } else if (entities.closedWay.some(function (way) {
42321               return utilArrayIntersection(graph.parentMultipolygons(way), entities.multipolygon).length;
42322             })) {
42323               // don't add a way to a multipolygon again if it's already a member
42324               return 'not_eligible';
42325             }
42326           };
42327
42328           return action;
42329         }
42330
42331         var DESCRIPTORS$1 = descriptors;
42332         var objectDefinePropertyModule = objectDefineProperty;
42333         var regExpFlags = regexpFlags$1;
42334         var fails$4 = fails$V;
42335
42336         var RegExpPrototype = RegExp.prototype;
42337
42338         var FORCED$2 = DESCRIPTORS$1 && fails$4(function () {
42339           // eslint-disable-next-line es/no-object-getownpropertydescriptor -- safe
42340           return Object.getOwnPropertyDescriptor(RegExpPrototype, 'flags').get.call({ dotAll: true, sticky: true }) !== 'sy';
42341         });
42342
42343         // `RegExp.prototype.flags` getter
42344         // https://tc39.es/ecma262/#sec-get-regexp.prototype.flags
42345         if (FORCED$2) objectDefinePropertyModule.f(RegExpPrototype, 'flags', {
42346           configurable: true,
42347           get: regExpFlags
42348         });
42349
42350         var fastDeepEqual = function equal(a, b) {
42351           if (a === b) return true;
42352
42353           if (a && b && _typeof(a) == 'object' && _typeof(b) == 'object') {
42354             if (a.constructor !== b.constructor) return false;
42355             var length, i, keys;
42356
42357             if (Array.isArray(a)) {
42358               length = a.length;
42359               if (length != b.length) return false;
42360
42361               for (i = length; i-- !== 0;) {
42362                 if (!equal(a[i], b[i])) return false;
42363               }
42364
42365               return true;
42366             }
42367
42368             if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
42369             if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
42370             if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
42371             keys = Object.keys(a);
42372             length = keys.length;
42373             if (length !== Object.keys(b).length) return false;
42374
42375             for (i = length; i-- !== 0;) {
42376               if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
42377             }
42378
42379             for (i = length; i-- !== 0;) {
42380               var key = keys[i];
42381               if (!equal(a[key], b[key])) return false;
42382             }
42383
42384             return true;
42385           } // true if both NaN, false otherwise
42386
42387
42388           return a !== a && b !== b;
42389         };
42390
42391         // J. W. Hunt and M. D. McIlroy, An algorithm for differential buffer
42392         // comparison, Bell Telephone Laboratories CSTR #41 (1976)
42393         // http://www.cs.dartmouth.edu/~doug/
42394         // https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
42395         //
42396         // Expects two arrays, finds longest common sequence
42397
42398         function LCS(buffer1, buffer2) {
42399           var equivalenceClasses = {};
42400
42401           for (var j = 0; j < buffer2.length; j++) {
42402             var item = buffer2[j];
42403
42404             if (equivalenceClasses[item]) {
42405               equivalenceClasses[item].push(j);
42406             } else {
42407               equivalenceClasses[item] = [j];
42408             }
42409           }
42410
42411           var NULLRESULT = {
42412             buffer1index: -1,
42413             buffer2index: -1,
42414             chain: null
42415           };
42416           var candidates = [NULLRESULT];
42417
42418           for (var i = 0; i < buffer1.length; i++) {
42419             var _item = buffer1[i];
42420             var buffer2indices = equivalenceClasses[_item] || [];
42421             var r = 0;
42422             var c = candidates[0];
42423
42424             for (var jx = 0; jx < buffer2indices.length; jx++) {
42425               var _j = buffer2indices[jx];
42426               var s = void 0;
42427
42428               for (s = r; s < candidates.length; s++) {
42429                 if (candidates[s].buffer2index < _j && (s === candidates.length - 1 || candidates[s + 1].buffer2index > _j)) {
42430                   break;
42431                 }
42432               }
42433
42434               if (s < candidates.length) {
42435                 var newCandidate = {
42436                   buffer1index: i,
42437                   buffer2index: _j,
42438                   chain: candidates[s]
42439                 };
42440
42441                 if (r === candidates.length) {
42442                   candidates.push(c);
42443                 } else {
42444                   candidates[r] = c;
42445                 }
42446
42447                 r = s + 1;
42448                 c = newCandidate;
42449
42450                 if (r === candidates.length) {
42451                   break; // no point in examining further (j)s
42452                 }
42453               }
42454             }
42455
42456             candidates[r] = c;
42457           } // At this point, we know the LCS: it's in the reverse of the
42458           // linked-list through .chain of candidates[candidates.length - 1].
42459
42460
42461           return candidates[candidates.length - 1];
42462         } // We apply the LCS to build a 'comm'-style picture of the
42463         // offsets and lengths of mismatched chunks in the input
42464         // buffers. This is used by diff3MergeRegions.
42465
42466
42467         function diffIndices(buffer1, buffer2) {
42468           var lcs = LCS(buffer1, buffer2);
42469           var result = [];
42470           var tail1 = buffer1.length;
42471           var tail2 = buffer2.length;
42472
42473           for (var candidate = lcs; candidate !== null; candidate = candidate.chain) {
42474             var mismatchLength1 = tail1 - candidate.buffer1index - 1;
42475             var mismatchLength2 = tail2 - candidate.buffer2index - 1;
42476             tail1 = candidate.buffer1index;
42477             tail2 = candidate.buffer2index;
42478
42479             if (mismatchLength1 || mismatchLength2) {
42480               result.push({
42481                 buffer1: [tail1 + 1, mismatchLength1],
42482                 buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1),
42483                 buffer2: [tail2 + 1, mismatchLength2],
42484                 buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2)
42485               });
42486             }
42487           }
42488
42489           result.reverse();
42490           return result;
42491         } // We apply the LCS to build a JSON representation of a
42492         // independently derived from O, returns a fairly complicated
42493         // internal representation of merge decisions it's taken. The
42494         // interested reader may wish to consult
42495         //
42496         // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce.
42497         // 'A Formal Investigation of ' In Arvind and Prasad,
42498         // editors, Foundations of Software Technology and Theoretical
42499         // Computer Science (FSTTCS), December 2007.
42500         //
42501         // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
42502         //
42503
42504
42505         function diff3MergeRegions(a, o, b) {
42506           // "hunks" are array subsets where `a` or `b` are different from `o`
42507           // https://www.gnu.org/software/diffutils/manual/html_node/diff3-Hunks.html
42508           var hunks = [];
42509
42510           function addHunk(h, ab) {
42511             hunks.push({
42512               ab: ab,
42513               oStart: h.buffer1[0],
42514               oLength: h.buffer1[1],
42515               // length of o to remove
42516               abStart: h.buffer2[0],
42517               abLength: h.buffer2[1] // length of a/b to insert
42518               // abContent: (ab === 'a' ? a : b).slice(h.buffer2[0], h.buffer2[0] + h.buffer2[1])
42519
42520             });
42521           }
42522
42523           diffIndices(o, a).forEach(function (item) {
42524             return addHunk(item, 'a');
42525           });
42526           diffIndices(o, b).forEach(function (item) {
42527             return addHunk(item, 'b');
42528           });
42529           hunks.sort(function (x, y) {
42530             return x.oStart - y.oStart;
42531           });
42532           var results = [];
42533           var currOffset = 0;
42534
42535           function advanceTo(endOffset) {
42536             if (endOffset > currOffset) {
42537               results.push({
42538                 stable: true,
42539                 buffer: 'o',
42540                 bufferStart: currOffset,
42541                 bufferLength: endOffset - currOffset,
42542                 bufferContent: o.slice(currOffset, endOffset)
42543               });
42544               currOffset = endOffset;
42545             }
42546           }
42547
42548           while (hunks.length) {
42549             var hunk = hunks.shift();
42550             var regionStart = hunk.oStart;
42551             var regionEnd = hunk.oStart + hunk.oLength;
42552             var regionHunks = [hunk];
42553             advanceTo(regionStart); // Try to pull next overlapping hunk into this region
42554
42555             while (hunks.length) {
42556               var nextHunk = hunks[0];
42557               var nextHunkStart = nextHunk.oStart;
42558               if (nextHunkStart > regionEnd) break; // no overlap
42559
42560               regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength);
42561               regionHunks.push(hunks.shift());
42562             }
42563
42564             if (regionHunks.length === 1) {
42565               // Only one hunk touches this region, meaning that there is no conflict here.
42566               // Either `a` or `b` is inserting into a region of `o` unchanged by the other.
42567               if (hunk.abLength > 0) {
42568                 var buffer = hunk.ab === 'a' ? a : b;
42569                 results.push({
42570                   stable: true,
42571                   buffer: hunk.ab,
42572                   bufferStart: hunk.abStart,
42573                   bufferLength: hunk.abLength,
42574                   bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength)
42575                 });
42576               }
42577             } else {
42578               // A true a/b conflict. Determine the bounds involved from `a`, `o`, and `b`.
42579               // Effectively merge all the `a` hunks into one giant hunk, then do the
42580               // same for the `b` hunks; then, correct for skew in the regions of `o`
42581               // that each side changed, and report appropriate spans for the three sides.
42582               var bounds = {
42583                 a: [a.length, -1, o.length, -1],
42584                 b: [b.length, -1, o.length, -1]
42585               };
42586
42587               while (regionHunks.length) {
42588                 hunk = regionHunks.shift();
42589                 var oStart = hunk.oStart;
42590                 var oEnd = oStart + hunk.oLength;
42591                 var abStart = hunk.abStart;
42592                 var abEnd = abStart + hunk.abLength;
42593                 var _b = bounds[hunk.ab];
42594                 _b[0] = Math.min(abStart, _b[0]);
42595                 _b[1] = Math.max(abEnd, _b[1]);
42596                 _b[2] = Math.min(oStart, _b[2]);
42597                 _b[3] = Math.max(oEnd, _b[3]);
42598               }
42599
42600               var aStart = bounds.a[0] + (regionStart - bounds.a[2]);
42601               var aEnd = bounds.a[1] + (regionEnd - bounds.a[3]);
42602               var bStart = bounds.b[0] + (regionStart - bounds.b[2]);
42603               var bEnd = bounds.b[1] + (regionEnd - bounds.b[3]);
42604               var result = {
42605                 stable: false,
42606                 aStart: aStart,
42607                 aLength: aEnd - aStart,
42608                 aContent: a.slice(aStart, aEnd),
42609                 oStart: regionStart,
42610                 oLength: regionEnd - regionStart,
42611                 oContent: o.slice(regionStart, regionEnd),
42612                 bStart: bStart,
42613                 bLength: bEnd - bStart,
42614                 bContent: b.slice(bStart, bEnd)
42615               };
42616               results.push(result);
42617             }
42618
42619             currOffset = regionEnd;
42620           }
42621
42622           advanceTo(o.length);
42623           return results;
42624         } // Applies the output of diff3MergeRegions to actually
42625         // construct the merged buffer; the returned result alternates
42626         // between 'ok' and 'conflict' blocks.
42627         // A "false conflict" is where `a` and `b` both change the same from `o`
42628
42629
42630         function diff3Merge(a, o, b, options) {
42631           var defaults = {
42632             excludeFalseConflicts: true,
42633             stringSeparator: /\s+/
42634           };
42635           options = Object.assign(defaults, options);
42636           var aString = typeof a === 'string';
42637           var oString = typeof o === 'string';
42638           var bString = typeof b === 'string';
42639           if (aString) a = a.split(options.stringSeparator);
42640           if (oString) o = o.split(options.stringSeparator);
42641           if (bString) b = b.split(options.stringSeparator);
42642           var results = [];
42643           var regions = diff3MergeRegions(a, o, b);
42644           var okBuffer = [];
42645
42646           function flushOk() {
42647             if (okBuffer.length) {
42648               results.push({
42649                 ok: okBuffer
42650               });
42651             }
42652
42653             okBuffer = [];
42654           }
42655
42656           function isFalseConflict(a, b) {
42657             if (a.length !== b.length) return false;
42658
42659             for (var i = 0; i < a.length; i++) {
42660               if (a[i] !== b[i]) return false;
42661             }
42662
42663             return true;
42664           }
42665
42666           regions.forEach(function (region) {
42667             if (region.stable) {
42668               var _okBuffer;
42669
42670               (_okBuffer = okBuffer).push.apply(_okBuffer, _toConsumableArray(region.bufferContent));
42671             } else {
42672               if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) {
42673                 var _okBuffer2;
42674
42675                 (_okBuffer2 = okBuffer).push.apply(_okBuffer2, _toConsumableArray(region.aContent));
42676               } else {
42677                 flushOk();
42678                 results.push({
42679                   conflict: {
42680                     a: region.aContent,
42681                     aIndex: region.aStart,
42682                     o: region.oContent,
42683                     oIndex: region.oStart,
42684                     b: region.bContent,
42685                     bIndex: region.bStart
42686                   }
42687                 });
42688               }
42689             }
42690           });
42691           flushOk();
42692           return results;
42693         }
42694
42695         var lodash = {exports: {}};
42696
42697         (function (module, exports) {
42698           (function () {
42699             /** Used as a safe reference for `undefined` in pre-ES5 environments. */
42700             var undefined$1;
42701             /** Used as the semantic version number. */
42702
42703             var VERSION = '4.17.21';
42704             /** Used as the size to enable large array optimizations. */
42705
42706             var LARGE_ARRAY_SIZE = 200;
42707             /** Error message constants. */
42708
42709             var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
42710                 FUNC_ERROR_TEXT = 'Expected a function',
42711                 INVALID_TEMPL_VAR_ERROR_TEXT = 'Invalid `variable` option passed into `_.template`';
42712             /** Used to stand-in for `undefined` hash values. */
42713
42714             var HASH_UNDEFINED = '__lodash_hash_undefined__';
42715             /** Used as the maximum memoize cache size. */
42716
42717             var MAX_MEMOIZE_SIZE = 500;
42718             /** Used as the internal argument placeholder. */
42719
42720             var PLACEHOLDER = '__lodash_placeholder__';
42721             /** Used to compose bitmasks for cloning. */
42722
42723             var CLONE_DEEP_FLAG = 1,
42724                 CLONE_FLAT_FLAG = 2,
42725                 CLONE_SYMBOLS_FLAG = 4;
42726             /** Used to compose bitmasks for value comparisons. */
42727
42728             var COMPARE_PARTIAL_FLAG = 1,
42729                 COMPARE_UNORDERED_FLAG = 2;
42730             /** Used to compose bitmasks for function metadata. */
42731
42732             var WRAP_BIND_FLAG = 1,
42733                 WRAP_BIND_KEY_FLAG = 2,
42734                 WRAP_CURRY_BOUND_FLAG = 4,
42735                 WRAP_CURRY_FLAG = 8,
42736                 WRAP_CURRY_RIGHT_FLAG = 16,
42737                 WRAP_PARTIAL_FLAG = 32,
42738                 WRAP_PARTIAL_RIGHT_FLAG = 64,
42739                 WRAP_ARY_FLAG = 128,
42740                 WRAP_REARG_FLAG = 256,
42741                 WRAP_FLIP_FLAG = 512;
42742             /** Used as default options for `_.truncate`. */
42743
42744             var DEFAULT_TRUNC_LENGTH = 30,
42745                 DEFAULT_TRUNC_OMISSION = '...';
42746             /** Used to detect hot functions by number of calls within a span of milliseconds. */
42747
42748             var HOT_COUNT = 800,
42749                 HOT_SPAN = 16;
42750             /** Used to indicate the type of lazy iteratees. */
42751
42752             var LAZY_FILTER_FLAG = 1,
42753                 LAZY_MAP_FLAG = 2,
42754                 LAZY_WHILE_FLAG = 3;
42755             /** Used as references for various `Number` constants. */
42756
42757             var INFINITY = 1 / 0,
42758                 MAX_SAFE_INTEGER = 9007199254740991,
42759                 MAX_INTEGER = 1.7976931348623157e+308,
42760                 NAN = 0 / 0;
42761             /** Used as references for the maximum length and index of an array. */
42762
42763             var MAX_ARRAY_LENGTH = 4294967295,
42764                 MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
42765                 HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
42766             /** Used to associate wrap methods with their bit flags. */
42767
42768             var wrapFlags = [['ary', WRAP_ARY_FLAG], ['bind', WRAP_BIND_FLAG], ['bindKey', WRAP_BIND_KEY_FLAG], ['curry', WRAP_CURRY_FLAG], ['curryRight', WRAP_CURRY_RIGHT_FLAG], ['flip', WRAP_FLIP_FLAG], ['partial', WRAP_PARTIAL_FLAG], ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], ['rearg', WRAP_REARG_FLAG]];
42769             /** `Object#toString` result references. */
42770
42771             var argsTag = '[object Arguments]',
42772                 arrayTag = '[object Array]',
42773                 asyncTag = '[object AsyncFunction]',
42774                 boolTag = '[object Boolean]',
42775                 dateTag = '[object Date]',
42776                 domExcTag = '[object DOMException]',
42777                 errorTag = '[object Error]',
42778                 funcTag = '[object Function]',
42779                 genTag = '[object GeneratorFunction]',
42780                 mapTag = '[object Map]',
42781                 numberTag = '[object Number]',
42782                 nullTag = '[object Null]',
42783                 objectTag = '[object Object]',
42784                 promiseTag = '[object Promise]',
42785                 proxyTag = '[object Proxy]',
42786                 regexpTag = '[object RegExp]',
42787                 setTag = '[object Set]',
42788                 stringTag = '[object String]',
42789                 symbolTag = '[object Symbol]',
42790                 undefinedTag = '[object Undefined]',
42791                 weakMapTag = '[object WeakMap]',
42792                 weakSetTag = '[object WeakSet]';
42793             var arrayBufferTag = '[object ArrayBuffer]',
42794                 dataViewTag = '[object DataView]',
42795                 float32Tag = '[object Float32Array]',
42796                 float64Tag = '[object Float64Array]',
42797                 int8Tag = '[object Int8Array]',
42798                 int16Tag = '[object Int16Array]',
42799                 int32Tag = '[object Int32Array]',
42800                 uint8Tag = '[object Uint8Array]',
42801                 uint8ClampedTag = '[object Uint8ClampedArray]',
42802                 uint16Tag = '[object Uint16Array]',
42803                 uint32Tag = '[object Uint32Array]';
42804             /** Used to match empty string literals in compiled template source. */
42805
42806             var reEmptyStringLeading = /\b__p \+= '';/g,
42807                 reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
42808                 reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
42809             /** Used to match HTML entities and HTML characters. */
42810
42811             var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
42812                 reUnescapedHtml = /[&<>"']/g,
42813                 reHasEscapedHtml = RegExp(reEscapedHtml.source),
42814                 reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
42815             /** Used to match template delimiters. */
42816
42817             var reEscape = /<%-([\s\S]+?)%>/g,
42818                 reEvaluate = /<%([\s\S]+?)%>/g,
42819                 reInterpolate = /<%=([\s\S]+?)%>/g;
42820             /** Used to match property names within property paths. */
42821
42822             var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
42823                 reIsPlainProp = /^\w*$/,
42824                 rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
42825             /**
42826              * Used to match `RegExp`
42827              * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
42828              */
42829
42830             var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
42831                 reHasRegExpChar = RegExp(reRegExpChar.source);
42832             /** Used to match leading whitespace. */
42833
42834             var reTrimStart = /^\s+/;
42835             /** Used to match a single whitespace character. */
42836
42837             var reWhitespace = /\s/;
42838             /** Used to match wrap detail comments. */
42839
42840             var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
42841                 reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
42842                 reSplitDetails = /,? & /;
42843             /** Used to match words composed of alphanumeric characters. */
42844
42845             var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
42846             /**
42847              * Used to validate the `validate` option in `_.template` variable.
42848              *
42849              * Forbids characters which could potentially change the meaning of the function argument definition:
42850              * - "()," (modification of function parameters)
42851              * - "=" (default value)
42852              * - "[]{}" (destructuring of function parameters)
42853              * - "/" (beginning of a comment)
42854              * - whitespace
42855              */
42856
42857             var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
42858             /** Used to match backslashes in property paths. */
42859
42860             var reEscapeChar = /\\(\\)?/g;
42861             /**
42862              * Used to match
42863              * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
42864              */
42865
42866             var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
42867             /** Used to match `RegExp` flags from their coerced string values. */
42868
42869             var reFlags = /\w*$/;
42870             /** Used to detect bad signed hexadecimal string values. */
42871
42872             var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
42873             /** Used to detect binary string values. */
42874
42875             var reIsBinary = /^0b[01]+$/i;
42876             /** Used to detect host constructors (Safari). */
42877
42878             var reIsHostCtor = /^\[object .+?Constructor\]$/;
42879             /** Used to detect octal string values. */
42880
42881             var reIsOctal = /^0o[0-7]+$/i;
42882             /** Used to detect unsigned integer values. */
42883
42884             var reIsUint = /^(?:0|[1-9]\d*)$/;
42885             /** Used to match Latin Unicode letters (excluding mathematical operators). */
42886
42887             var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
42888             /** Used to ensure capturing order of template delimiters. */
42889
42890             var reNoMatch = /($^)/;
42891             /** Used to match unescaped characters in compiled string literals. */
42892
42893             var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
42894             /** Used to compose unicode character classes. */
42895
42896             var rsAstralRange = "\\ud800-\\udfff",
42897                 rsComboMarksRange = "\\u0300-\\u036f",
42898                 reComboHalfMarksRange = "\\ufe20-\\ufe2f",
42899                 rsComboSymbolsRange = "\\u20d0-\\u20ff",
42900                 rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
42901                 rsDingbatRange = "\\u2700-\\u27bf",
42902                 rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
42903                 rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
42904                 rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
42905                 rsPunctuationRange = "\\u2000-\\u206f",
42906                 rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",
42907                 rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
42908                 rsVarRange = "\\ufe0e\\ufe0f",
42909                 rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
42910             /** Used to compose unicode capture groups. */
42911
42912             var rsApos = "['\u2019]",
42913                 rsAstral = '[' + rsAstralRange + ']',
42914                 rsBreak = '[' + rsBreakRange + ']',
42915                 rsCombo = '[' + rsComboRange + ']',
42916                 rsDigits = '\\d+',
42917                 rsDingbat = '[' + rsDingbatRange + ']',
42918                 rsLower = '[' + rsLowerRange + ']',
42919                 rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
42920                 rsFitz = "\\ud83c[\\udffb-\\udfff]",
42921                 rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
42922                 rsNonAstral = '[^' + rsAstralRange + ']',
42923                 rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}",
42924                 rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]",
42925                 rsUpper = '[' + rsUpperRange + ']',
42926                 rsZWJ = "\\u200d";
42927             /** Used to compose unicode regexes. */
42928
42929             var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
42930                 rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
42931                 rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
42932                 rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
42933                 reOptMod = rsModifier + '?',
42934                 rsOptVar = '[' + rsVarRange + ']?',
42935                 rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
42936                 rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])',
42937                 rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])',
42938                 rsSeq = rsOptVar + reOptMod + rsOptJoin,
42939                 rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
42940                 rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
42941             /** Used to match apostrophes. */
42942
42943             var reApos = RegExp(rsApos, 'g');
42944             /**
42945              * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
42946              * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
42947              */
42948
42949             var reComboMark = RegExp(rsCombo, 'g');
42950             /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
42951
42952             var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
42953             /** Used to match complex or compound words. */
42954
42955             var reUnicodeWord = RegExp([rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')', rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower, rsUpper + '+' + rsOptContrUpper, rsOrdUpper, rsOrdLower, rsDigits, rsEmoji].join('|'), 'g');
42956             /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
42957
42958             var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']');
42959             /** Used to detect strings that need a more robust regexp to match words. */
42960
42961             var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
42962             /** Used to assign default `context` object properties. */
42963
42964             var contextProps = ['Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'];
42965             /** Used to make template sourceURLs easier to identify. */
42966
42967             var templateCounter = -1;
42968             /** Used to identify `toStringTag` values of typed arrays. */
42969
42970             var typedArrayTags = {};
42971             typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
42972             typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
42973             /** Used to identify `toStringTag` values supported by `_.clone`. */
42974
42975             var cloneableTags = {};
42976             cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
42977             cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false;
42978             /** Used to map Latin Unicode letters to basic Latin letters. */
42979
42980             var deburredLetters = {
42981               // Latin-1 Supplement block.
42982               '\xc0': 'A',
42983               '\xc1': 'A',
42984               '\xc2': 'A',
42985               '\xc3': 'A',
42986               '\xc4': 'A',
42987               '\xc5': 'A',
42988               '\xe0': 'a',
42989               '\xe1': 'a',
42990               '\xe2': 'a',
42991               '\xe3': 'a',
42992               '\xe4': 'a',
42993               '\xe5': 'a',
42994               '\xc7': 'C',
42995               '\xe7': 'c',
42996               '\xd0': 'D',
42997               '\xf0': 'd',
42998               '\xc8': 'E',
42999               '\xc9': 'E',
43000               '\xca': 'E',
43001               '\xcb': 'E',
43002               '\xe8': 'e',
43003               '\xe9': 'e',
43004               '\xea': 'e',
43005               '\xeb': 'e',
43006               '\xcc': 'I',
43007               '\xcd': 'I',
43008               '\xce': 'I',
43009               '\xcf': 'I',
43010               '\xec': 'i',
43011               '\xed': 'i',
43012               '\xee': 'i',
43013               '\xef': 'i',
43014               '\xd1': 'N',
43015               '\xf1': 'n',
43016               '\xd2': 'O',
43017               '\xd3': 'O',
43018               '\xd4': 'O',
43019               '\xd5': 'O',
43020               '\xd6': 'O',
43021               '\xd8': 'O',
43022               '\xf2': 'o',
43023               '\xf3': 'o',
43024               '\xf4': 'o',
43025               '\xf5': 'o',
43026               '\xf6': 'o',
43027               '\xf8': 'o',
43028               '\xd9': 'U',
43029               '\xda': 'U',
43030               '\xdb': 'U',
43031               '\xdc': 'U',
43032               '\xf9': 'u',
43033               '\xfa': 'u',
43034               '\xfb': 'u',
43035               '\xfc': 'u',
43036               '\xdd': 'Y',
43037               '\xfd': 'y',
43038               '\xff': 'y',
43039               '\xc6': 'Ae',
43040               '\xe6': 'ae',
43041               '\xde': 'Th',
43042               '\xfe': 'th',
43043               '\xdf': 'ss',
43044               // Latin Extended-A block.
43045               "\u0100": 'A',
43046               "\u0102": 'A',
43047               "\u0104": 'A',
43048               "\u0101": 'a',
43049               "\u0103": 'a',
43050               "\u0105": 'a',
43051               "\u0106": 'C',
43052               "\u0108": 'C',
43053               "\u010A": 'C',
43054               "\u010C": 'C',
43055               "\u0107": 'c',
43056               "\u0109": 'c',
43057               "\u010B": 'c',
43058               "\u010D": 'c',
43059               "\u010E": 'D',
43060               "\u0110": 'D',
43061               "\u010F": 'd',
43062               "\u0111": 'd',
43063               "\u0112": 'E',
43064               "\u0114": 'E',
43065               "\u0116": 'E',
43066               "\u0118": 'E',
43067               "\u011A": 'E',
43068               "\u0113": 'e',
43069               "\u0115": 'e',
43070               "\u0117": 'e',
43071               "\u0119": 'e',
43072               "\u011B": 'e',
43073               "\u011C": 'G',
43074               "\u011E": 'G',
43075               "\u0120": 'G',
43076               "\u0122": 'G',
43077               "\u011D": 'g',
43078               "\u011F": 'g',
43079               "\u0121": 'g',
43080               "\u0123": 'g',
43081               "\u0124": 'H',
43082               "\u0126": 'H',
43083               "\u0125": 'h',
43084               "\u0127": 'h',
43085               "\u0128": 'I',
43086               "\u012A": 'I',
43087               "\u012C": 'I',
43088               "\u012E": 'I',
43089               "\u0130": 'I',
43090               "\u0129": 'i',
43091               "\u012B": 'i',
43092               "\u012D": 'i',
43093               "\u012F": 'i',
43094               "\u0131": 'i',
43095               "\u0134": 'J',
43096               "\u0135": 'j',
43097               "\u0136": 'K',
43098               "\u0137": 'k',
43099               "\u0138": 'k',
43100               "\u0139": 'L',
43101               "\u013B": 'L',
43102               "\u013D": 'L',
43103               "\u013F": 'L',
43104               "\u0141": 'L',
43105               "\u013A": 'l',
43106               "\u013C": 'l',
43107               "\u013E": 'l',
43108               "\u0140": 'l',
43109               "\u0142": 'l',
43110               "\u0143": 'N',
43111               "\u0145": 'N',
43112               "\u0147": 'N',
43113               "\u014A": 'N',
43114               "\u0144": 'n',
43115               "\u0146": 'n',
43116               "\u0148": 'n',
43117               "\u014B": 'n',
43118               "\u014C": 'O',
43119               "\u014E": 'O',
43120               "\u0150": 'O',
43121               "\u014D": 'o',
43122               "\u014F": 'o',
43123               "\u0151": 'o',
43124               "\u0154": 'R',
43125               "\u0156": 'R',
43126               "\u0158": 'R',
43127               "\u0155": 'r',
43128               "\u0157": 'r',
43129               "\u0159": 'r',
43130               "\u015A": 'S',
43131               "\u015C": 'S',
43132               "\u015E": 'S',
43133               "\u0160": 'S',
43134               "\u015B": 's',
43135               "\u015D": 's',
43136               "\u015F": 's',
43137               "\u0161": 's',
43138               "\u0162": 'T',
43139               "\u0164": 'T',
43140               "\u0166": 'T',
43141               "\u0163": 't',
43142               "\u0165": 't',
43143               "\u0167": 't',
43144               "\u0168": 'U',
43145               "\u016A": 'U',
43146               "\u016C": 'U',
43147               "\u016E": 'U',
43148               "\u0170": 'U',
43149               "\u0172": 'U',
43150               "\u0169": 'u',
43151               "\u016B": 'u',
43152               "\u016D": 'u',
43153               "\u016F": 'u',
43154               "\u0171": 'u',
43155               "\u0173": 'u',
43156               "\u0174": 'W',
43157               "\u0175": 'w',
43158               "\u0176": 'Y',
43159               "\u0177": 'y',
43160               "\u0178": 'Y',
43161               "\u0179": 'Z',
43162               "\u017B": 'Z',
43163               "\u017D": 'Z',
43164               "\u017A": 'z',
43165               "\u017C": 'z',
43166               "\u017E": 'z',
43167               "\u0132": 'IJ',
43168               "\u0133": 'ij',
43169               "\u0152": 'Oe',
43170               "\u0153": 'oe',
43171               "\u0149": "'n",
43172               "\u017F": 's'
43173             };
43174             /** Used to map characters to HTML entities. */
43175
43176             var htmlEscapes = {
43177               '&': '&amp;',
43178               '<': '&lt;',
43179               '>': '&gt;',
43180               '"': '&quot;',
43181               "'": '&#39;'
43182             };
43183             /** Used to map HTML entities to characters. */
43184
43185             var htmlUnescapes = {
43186               '&amp;': '&',
43187               '&lt;': '<',
43188               '&gt;': '>',
43189               '&quot;': '"',
43190               '&#39;': "'"
43191             };
43192             /** Used to escape characters for inclusion in compiled string literals. */
43193
43194             var stringEscapes = {
43195               '\\': '\\',
43196               "'": "'",
43197               '\n': 'n',
43198               '\r': 'r',
43199               "\u2028": 'u2028',
43200               "\u2029": 'u2029'
43201             };
43202             /** Built-in method references without a dependency on `root`. */
43203
43204             var freeParseFloat = parseFloat,
43205                 freeParseInt = parseInt;
43206             /** Detect free variable `global` from Node.js. */
43207
43208             var freeGlobal = _typeof(commonjsGlobal) == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
43209             /** Detect free variable `self`. */
43210
43211             var freeSelf = (typeof self === "undefined" ? "undefined" : _typeof(self)) == 'object' && self && self.Object === Object && self;
43212             /** Used as a reference to the global object. */
43213
43214             var root = freeGlobal || freeSelf || Function('return this')();
43215             /** Detect free variable `exports`. */
43216
43217             var freeExports = exports && !exports.nodeType && exports;
43218             /** Detect free variable `module`. */
43219
43220             var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
43221             /** Detect the popular CommonJS extension `module.exports`. */
43222
43223             var moduleExports = freeModule && freeModule.exports === freeExports;
43224             /** Detect free variable `process` from Node.js. */
43225
43226             var freeProcess = moduleExports && freeGlobal.process;
43227             /** Used to access faster Node.js helpers. */
43228
43229             var nodeUtil = function () {
43230               try {
43231                 // Use `util.types` for Node.js 10+.
43232                 var types = freeModule && freeModule.require && freeModule.require('util').types;
43233
43234                 if (types) {
43235                   return types;
43236                 } // Legacy `process.binding('util')` for Node.js < 10.
43237
43238
43239                 return freeProcess && freeProcess.binding && freeProcess.binding('util');
43240               } catch (e) {}
43241             }();
43242             /* Node.js helper references. */
43243
43244
43245             var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
43246                 nodeIsDate = nodeUtil && nodeUtil.isDate,
43247                 nodeIsMap = nodeUtil && nodeUtil.isMap,
43248                 nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
43249                 nodeIsSet = nodeUtil && nodeUtil.isSet,
43250                 nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
43251             /*--------------------------------------------------------------------------*/
43252
43253             /**
43254              * A faster alternative to `Function#apply`, this function invokes `func`
43255              * with the `this` binding of `thisArg` and the arguments of `args`.
43256              *
43257              * @private
43258              * @param {Function} func The function to invoke.
43259              * @param {*} thisArg The `this` binding of `func`.
43260              * @param {Array} args The arguments to invoke `func` with.
43261              * @returns {*} Returns the result of `func`.
43262              */
43263
43264             function apply(func, thisArg, args) {
43265               switch (args.length) {
43266                 case 0:
43267                   return func.call(thisArg);
43268
43269                 case 1:
43270                   return func.call(thisArg, args[0]);
43271
43272                 case 2:
43273                   return func.call(thisArg, args[0], args[1]);
43274
43275                 case 3:
43276                   return func.call(thisArg, args[0], args[1], args[2]);
43277               }
43278
43279               return func.apply(thisArg, args);
43280             }
43281             /**
43282              * A specialized version of `baseAggregator` for arrays.
43283              *
43284              * @private
43285              * @param {Array} [array] The array to iterate over.
43286              * @param {Function} setter The function to set `accumulator` values.
43287              * @param {Function} iteratee The iteratee to transform keys.
43288              * @param {Object} accumulator The initial aggregated object.
43289              * @returns {Function} Returns `accumulator`.
43290              */
43291
43292
43293             function arrayAggregator(array, setter, iteratee, accumulator) {
43294               var index = -1,
43295                   length = array == null ? 0 : array.length;
43296
43297               while (++index < length) {
43298                 var value = array[index];
43299                 setter(accumulator, value, iteratee(value), array);
43300               }
43301
43302               return accumulator;
43303             }
43304             /**
43305              * A specialized version of `_.forEach` for arrays without support for
43306              * iteratee shorthands.
43307              *
43308              * @private
43309              * @param {Array} [array] The array to iterate over.
43310              * @param {Function} iteratee The function invoked per iteration.
43311              * @returns {Array} Returns `array`.
43312              */
43313
43314
43315             function arrayEach(array, iteratee) {
43316               var index = -1,
43317                   length = array == null ? 0 : array.length;
43318
43319               while (++index < length) {
43320                 if (iteratee(array[index], index, array) === false) {
43321                   break;
43322                 }
43323               }
43324
43325               return array;
43326             }
43327             /**
43328              * A specialized version of `_.forEachRight` for arrays without support for
43329              * iteratee shorthands.
43330              *
43331              * @private
43332              * @param {Array} [array] The array to iterate over.
43333              * @param {Function} iteratee The function invoked per iteration.
43334              * @returns {Array} Returns `array`.
43335              */
43336
43337
43338             function arrayEachRight(array, iteratee) {
43339               var length = array == null ? 0 : array.length;
43340
43341               while (length--) {
43342                 if (iteratee(array[length], length, array) === false) {
43343                   break;
43344                 }
43345               }
43346
43347               return array;
43348             }
43349             /**
43350              * A specialized version of `_.every` for arrays without support for
43351              * iteratee shorthands.
43352              *
43353              * @private
43354              * @param {Array} [array] The array to iterate over.
43355              * @param {Function} predicate The function invoked per iteration.
43356              * @returns {boolean} Returns `true` if all elements pass the predicate check,
43357              *  else `false`.
43358              */
43359
43360
43361             function arrayEvery(array, predicate) {
43362               var index = -1,
43363                   length = array == null ? 0 : array.length;
43364
43365               while (++index < length) {
43366                 if (!predicate(array[index], index, array)) {
43367                   return false;
43368                 }
43369               }
43370
43371               return true;
43372             }
43373             /**
43374              * A specialized version of `_.filter` for arrays without support for
43375              * iteratee shorthands.
43376              *
43377              * @private
43378              * @param {Array} [array] The array to iterate over.
43379              * @param {Function} predicate The function invoked per iteration.
43380              * @returns {Array} Returns the new filtered array.
43381              */
43382
43383
43384             function arrayFilter(array, predicate) {
43385               var index = -1,
43386                   length = array == null ? 0 : array.length,
43387                   resIndex = 0,
43388                   result = [];
43389
43390               while (++index < length) {
43391                 var value = array[index];
43392
43393                 if (predicate(value, index, array)) {
43394                   result[resIndex++] = value;
43395                 }
43396               }
43397
43398               return result;
43399             }
43400             /**
43401              * A specialized version of `_.includes` for arrays without support for
43402              * specifying an index to search from.
43403              *
43404              * @private
43405              * @param {Array} [array] The array to inspect.
43406              * @param {*} target The value to search for.
43407              * @returns {boolean} Returns `true` if `target` is found, else `false`.
43408              */
43409
43410
43411             function arrayIncludes(array, value) {
43412               var length = array == null ? 0 : array.length;
43413               return !!length && baseIndexOf(array, value, 0) > -1;
43414             }
43415             /**
43416              * This function is like `arrayIncludes` except that it accepts a comparator.
43417              *
43418              * @private
43419              * @param {Array} [array] The array to inspect.
43420              * @param {*} target The value to search for.
43421              * @param {Function} comparator The comparator invoked per element.
43422              * @returns {boolean} Returns `true` if `target` is found, else `false`.
43423              */
43424
43425
43426             function arrayIncludesWith(array, value, comparator) {
43427               var index = -1,
43428                   length = array == null ? 0 : array.length;
43429
43430               while (++index < length) {
43431                 if (comparator(value, array[index])) {
43432                   return true;
43433                 }
43434               }
43435
43436               return false;
43437             }
43438             /**
43439              * A specialized version of `_.map` for arrays without support for iteratee
43440              * shorthands.
43441              *
43442              * @private
43443              * @param {Array} [array] The array to iterate over.
43444              * @param {Function} iteratee The function invoked per iteration.
43445              * @returns {Array} Returns the new mapped array.
43446              */
43447
43448
43449             function arrayMap(array, iteratee) {
43450               var index = -1,
43451                   length = array == null ? 0 : array.length,
43452                   result = Array(length);
43453
43454               while (++index < length) {
43455                 result[index] = iteratee(array[index], index, array);
43456               }
43457
43458               return result;
43459             }
43460             /**
43461              * Appends the elements of `values` to `array`.
43462              *
43463              * @private
43464              * @param {Array} array The array to modify.
43465              * @param {Array} values The values to append.
43466              * @returns {Array} Returns `array`.
43467              */
43468
43469
43470             function arrayPush(array, values) {
43471               var index = -1,
43472                   length = values.length,
43473                   offset = array.length;
43474
43475               while (++index < length) {
43476                 array[offset + index] = values[index];
43477               }
43478
43479               return array;
43480             }
43481             /**
43482              * A specialized version of `_.reduce` for arrays without support for
43483              * iteratee shorthands.
43484              *
43485              * @private
43486              * @param {Array} [array] The array to iterate over.
43487              * @param {Function} iteratee The function invoked per iteration.
43488              * @param {*} [accumulator] The initial value.
43489              * @param {boolean} [initAccum] Specify using the first element of `array` as
43490              *  the initial value.
43491              * @returns {*} Returns the accumulated value.
43492              */
43493
43494
43495             function arrayReduce(array, iteratee, accumulator, initAccum) {
43496               var index = -1,
43497                   length = array == null ? 0 : array.length;
43498
43499               if (initAccum && length) {
43500                 accumulator = array[++index];
43501               }
43502
43503               while (++index < length) {
43504                 accumulator = iteratee(accumulator, array[index], index, array);
43505               }
43506
43507               return accumulator;
43508             }
43509             /**
43510              * A specialized version of `_.reduceRight` for arrays without support for
43511              * iteratee shorthands.
43512              *
43513              * @private
43514              * @param {Array} [array] The array to iterate over.
43515              * @param {Function} iteratee The function invoked per iteration.
43516              * @param {*} [accumulator] The initial value.
43517              * @param {boolean} [initAccum] Specify using the last element of `array` as
43518              *  the initial value.
43519              * @returns {*} Returns the accumulated value.
43520              */
43521
43522
43523             function arrayReduceRight(array, iteratee, accumulator, initAccum) {
43524               var length = array == null ? 0 : array.length;
43525
43526               if (initAccum && length) {
43527                 accumulator = array[--length];
43528               }
43529
43530               while (length--) {
43531                 accumulator = iteratee(accumulator, array[length], length, array);
43532               }
43533
43534               return accumulator;
43535             }
43536             /**
43537              * A specialized version of `_.some` for arrays without support for iteratee
43538              * shorthands.
43539              *
43540              * @private
43541              * @param {Array} [array] The array to iterate over.
43542              * @param {Function} predicate The function invoked per iteration.
43543              * @returns {boolean} Returns `true` if any element passes the predicate check,
43544              *  else `false`.
43545              */
43546
43547
43548             function arraySome(array, predicate) {
43549               var index = -1,
43550                   length = array == null ? 0 : array.length;
43551
43552               while (++index < length) {
43553                 if (predicate(array[index], index, array)) {
43554                   return true;
43555                 }
43556               }
43557
43558               return false;
43559             }
43560             /**
43561              * Gets the size of an ASCII `string`.
43562              *
43563              * @private
43564              * @param {string} string The string inspect.
43565              * @returns {number} Returns the string size.
43566              */
43567
43568
43569             var asciiSize = baseProperty('length');
43570             /**
43571              * Converts an ASCII `string` to an array.
43572              *
43573              * @private
43574              * @param {string} string The string to convert.
43575              * @returns {Array} Returns the converted array.
43576              */
43577
43578             function asciiToArray(string) {
43579               return string.split('');
43580             }
43581             /**
43582              * Splits an ASCII `string` into an array of its words.
43583              *
43584              * @private
43585              * @param {string} The string to inspect.
43586              * @returns {Array} Returns the words of `string`.
43587              */
43588
43589
43590             function asciiWords(string) {
43591               return string.match(reAsciiWord) || [];
43592             }
43593             /**
43594              * The base implementation of methods like `_.findKey` and `_.findLastKey`,
43595              * without support for iteratee shorthands, which iterates over `collection`
43596              * using `eachFunc`.
43597              *
43598              * @private
43599              * @param {Array|Object} collection The collection to inspect.
43600              * @param {Function} predicate The function invoked per iteration.
43601              * @param {Function} eachFunc The function to iterate over `collection`.
43602              * @returns {*} Returns the found element or its key, else `undefined`.
43603              */
43604
43605
43606             function baseFindKey(collection, predicate, eachFunc) {
43607               var result;
43608               eachFunc(collection, function (value, key, collection) {
43609                 if (predicate(value, key, collection)) {
43610                   result = key;
43611                   return false;
43612                 }
43613               });
43614               return result;
43615             }
43616             /**
43617              * The base implementation of `_.findIndex` and `_.findLastIndex` without
43618              * support for iteratee shorthands.
43619              *
43620              * @private
43621              * @param {Array} array The array to inspect.
43622              * @param {Function} predicate The function invoked per iteration.
43623              * @param {number} fromIndex The index to search from.
43624              * @param {boolean} [fromRight] Specify iterating from right to left.
43625              * @returns {number} Returns the index of the matched value, else `-1`.
43626              */
43627
43628
43629             function baseFindIndex(array, predicate, fromIndex, fromRight) {
43630               var length = array.length,
43631                   index = fromIndex + (fromRight ? 1 : -1);
43632
43633               while (fromRight ? index-- : ++index < length) {
43634                 if (predicate(array[index], index, array)) {
43635                   return index;
43636                 }
43637               }
43638
43639               return -1;
43640             }
43641             /**
43642              * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
43643              *
43644              * @private
43645              * @param {Array} array The array to inspect.
43646              * @param {*} value The value to search for.
43647              * @param {number} fromIndex The index to search from.
43648              * @returns {number} Returns the index of the matched value, else `-1`.
43649              */
43650
43651
43652             function baseIndexOf(array, value, fromIndex) {
43653               return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex);
43654             }
43655             /**
43656              * This function is like `baseIndexOf` except that it accepts a comparator.
43657              *
43658              * @private
43659              * @param {Array} array The array to inspect.
43660              * @param {*} value The value to search for.
43661              * @param {number} fromIndex The index to search from.
43662              * @param {Function} comparator The comparator invoked per element.
43663              * @returns {number} Returns the index of the matched value, else `-1`.
43664              */
43665
43666
43667             function baseIndexOfWith(array, value, fromIndex, comparator) {
43668               var index = fromIndex - 1,
43669                   length = array.length;
43670
43671               while (++index < length) {
43672                 if (comparator(array[index], value)) {
43673                   return index;
43674                 }
43675               }
43676
43677               return -1;
43678             }
43679             /**
43680              * The base implementation of `_.isNaN` without support for number objects.
43681              *
43682              * @private
43683              * @param {*} value The value to check.
43684              * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
43685              */
43686
43687
43688             function baseIsNaN(value) {
43689               return value !== value;
43690             }
43691             /**
43692              * The base implementation of `_.mean` and `_.meanBy` without support for
43693              * iteratee shorthands.
43694              *
43695              * @private
43696              * @param {Array} array The array to iterate over.
43697              * @param {Function} iteratee The function invoked per iteration.
43698              * @returns {number} Returns the mean.
43699              */
43700
43701
43702             function baseMean(array, iteratee) {
43703               var length = array == null ? 0 : array.length;
43704               return length ? baseSum(array, iteratee) / length : NAN;
43705             }
43706             /**
43707              * The base implementation of `_.property` without support for deep paths.
43708              *
43709              * @private
43710              * @param {string} key The key of the property to get.
43711              * @returns {Function} Returns the new accessor function.
43712              */
43713
43714
43715             function baseProperty(key) {
43716               return function (object) {
43717                 return object == null ? undefined$1 : object[key];
43718               };
43719             }
43720             /**
43721              * The base implementation of `_.propertyOf` without support for deep paths.
43722              *
43723              * @private
43724              * @param {Object} object The object to query.
43725              * @returns {Function} Returns the new accessor function.
43726              */
43727
43728
43729             function basePropertyOf(object) {
43730               return function (key) {
43731                 return object == null ? undefined$1 : object[key];
43732               };
43733             }
43734             /**
43735              * The base implementation of `_.reduce` and `_.reduceRight`, without support
43736              * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
43737              *
43738              * @private
43739              * @param {Array|Object} collection The collection to iterate over.
43740              * @param {Function} iteratee The function invoked per iteration.
43741              * @param {*} accumulator The initial value.
43742              * @param {boolean} initAccum Specify using the first or last element of
43743              *  `collection` as the initial value.
43744              * @param {Function} eachFunc The function to iterate over `collection`.
43745              * @returns {*} Returns the accumulated value.
43746              */
43747
43748
43749             function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
43750               eachFunc(collection, function (value, index, collection) {
43751                 accumulator = initAccum ? (initAccum = false, value) : iteratee(accumulator, value, index, collection);
43752               });
43753               return accumulator;
43754             }
43755             /**
43756              * The base implementation of `_.sortBy` which uses `comparer` to define the
43757              * sort order of `array` and replaces criteria objects with their corresponding
43758              * values.
43759              *
43760              * @private
43761              * @param {Array} array The array to sort.
43762              * @param {Function} comparer The function to define sort order.
43763              * @returns {Array} Returns `array`.
43764              */
43765
43766
43767             function baseSortBy(array, comparer) {
43768               var length = array.length;
43769               array.sort(comparer);
43770
43771               while (length--) {
43772                 array[length] = array[length].value;
43773               }
43774
43775               return array;
43776             }
43777             /**
43778              * The base implementation of `_.sum` and `_.sumBy` without support for
43779              * iteratee shorthands.
43780              *
43781              * @private
43782              * @param {Array} array The array to iterate over.
43783              * @param {Function} iteratee The function invoked per iteration.
43784              * @returns {number} Returns the sum.
43785              */
43786
43787
43788             function baseSum(array, iteratee) {
43789               var result,
43790                   index = -1,
43791                   length = array.length;
43792
43793               while (++index < length) {
43794                 var current = iteratee(array[index]);
43795
43796                 if (current !== undefined$1) {
43797                   result = result === undefined$1 ? current : result + current;
43798                 }
43799               }
43800
43801               return result;
43802             }
43803             /**
43804              * The base implementation of `_.times` without support for iteratee shorthands
43805              * or max array length checks.
43806              *
43807              * @private
43808              * @param {number} n The number of times to invoke `iteratee`.
43809              * @param {Function} iteratee The function invoked per iteration.
43810              * @returns {Array} Returns the array of results.
43811              */
43812
43813
43814             function baseTimes(n, iteratee) {
43815               var index = -1,
43816                   result = Array(n);
43817
43818               while (++index < n) {
43819                 result[index] = iteratee(index);
43820               }
43821
43822               return result;
43823             }
43824             /**
43825              * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
43826              * of key-value pairs for `object` corresponding to the property names of `props`.
43827              *
43828              * @private
43829              * @param {Object} object The object to query.
43830              * @param {Array} props The property names to get values for.
43831              * @returns {Object} Returns the key-value pairs.
43832              */
43833
43834
43835             function baseToPairs(object, props) {
43836               return arrayMap(props, function (key) {
43837                 return [key, object[key]];
43838               });
43839             }
43840             /**
43841              * The base implementation of `_.trim`.
43842              *
43843              * @private
43844              * @param {string} string The string to trim.
43845              * @returns {string} Returns the trimmed string.
43846              */
43847
43848
43849             function baseTrim(string) {
43850               return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') : string;
43851             }
43852             /**
43853              * The base implementation of `_.unary` without support for storing metadata.
43854              *
43855              * @private
43856              * @param {Function} func The function to cap arguments for.
43857              * @returns {Function} Returns the new capped function.
43858              */
43859
43860
43861             function baseUnary(func) {
43862               return function (value) {
43863                 return func(value);
43864               };
43865             }
43866             /**
43867              * The base implementation of `_.values` and `_.valuesIn` which creates an
43868              * array of `object` property values corresponding to the property names
43869              * of `props`.
43870              *
43871              * @private
43872              * @param {Object} object The object to query.
43873              * @param {Array} props The property names to get values for.
43874              * @returns {Object} Returns the array of property values.
43875              */
43876
43877
43878             function baseValues(object, props) {
43879               return arrayMap(props, function (key) {
43880                 return object[key];
43881               });
43882             }
43883             /**
43884              * Checks if a `cache` value for `key` exists.
43885              *
43886              * @private
43887              * @param {Object} cache The cache to query.
43888              * @param {string} key The key of the entry to check.
43889              * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
43890              */
43891
43892
43893             function cacheHas(cache, key) {
43894               return cache.has(key);
43895             }
43896             /**
43897              * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
43898              * that is not found in the character symbols.
43899              *
43900              * @private
43901              * @param {Array} strSymbols The string symbols to inspect.
43902              * @param {Array} chrSymbols The character symbols to find.
43903              * @returns {number} Returns the index of the first unmatched string symbol.
43904              */
43905
43906
43907             function charsStartIndex(strSymbols, chrSymbols) {
43908               var index = -1,
43909                   length = strSymbols.length;
43910
43911               while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
43912
43913               return index;
43914             }
43915             /**
43916              * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
43917              * that is not found in the character symbols.
43918              *
43919              * @private
43920              * @param {Array} strSymbols The string symbols to inspect.
43921              * @param {Array} chrSymbols The character symbols to find.
43922              * @returns {number} Returns the index of the last unmatched string symbol.
43923              */
43924
43925
43926             function charsEndIndex(strSymbols, chrSymbols) {
43927               var index = strSymbols.length;
43928
43929               while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
43930
43931               return index;
43932             }
43933             /**
43934              * Gets the number of `placeholder` occurrences in `array`.
43935              *
43936              * @private
43937              * @param {Array} array The array to inspect.
43938              * @param {*} placeholder The placeholder to search for.
43939              * @returns {number} Returns the placeholder count.
43940              */
43941
43942
43943             function countHolders(array, placeholder) {
43944               var length = array.length,
43945                   result = 0;
43946
43947               while (length--) {
43948                 if (array[length] === placeholder) {
43949                   ++result;
43950                 }
43951               }
43952
43953               return result;
43954             }
43955             /**
43956              * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
43957              * letters to basic Latin letters.
43958              *
43959              * @private
43960              * @param {string} letter The matched letter to deburr.
43961              * @returns {string} Returns the deburred letter.
43962              */
43963
43964
43965             var deburrLetter = basePropertyOf(deburredLetters);
43966             /**
43967              * Used by `_.escape` to convert characters to HTML entities.
43968              *
43969              * @private
43970              * @param {string} chr The matched character to escape.
43971              * @returns {string} Returns the escaped character.
43972              */
43973
43974             var escapeHtmlChar = basePropertyOf(htmlEscapes);
43975             /**
43976              * Used by `_.template` to escape characters for inclusion in compiled string literals.
43977              *
43978              * @private
43979              * @param {string} chr The matched character to escape.
43980              * @returns {string} Returns the escaped character.
43981              */
43982
43983             function escapeStringChar(chr) {
43984               return '\\' + stringEscapes[chr];
43985             }
43986             /**
43987              * Gets the value at `key` of `object`.
43988              *
43989              * @private
43990              * @param {Object} [object] The object to query.
43991              * @param {string} key The key of the property to get.
43992              * @returns {*} Returns the property value.
43993              */
43994
43995
43996             function getValue(object, key) {
43997               return object == null ? undefined$1 : object[key];
43998             }
43999             /**
44000              * Checks if `string` contains Unicode symbols.
44001              *
44002              * @private
44003              * @param {string} string The string to inspect.
44004              * @returns {boolean} Returns `true` if a symbol is found, else `false`.
44005              */
44006
44007
44008             function hasUnicode(string) {
44009               return reHasUnicode.test(string);
44010             }
44011             /**
44012              * Checks if `string` contains a word composed of Unicode symbols.
44013              *
44014              * @private
44015              * @param {string} string The string to inspect.
44016              * @returns {boolean} Returns `true` if a word is found, else `false`.
44017              */
44018
44019
44020             function hasUnicodeWord(string) {
44021               return reHasUnicodeWord.test(string);
44022             }
44023             /**
44024              * Converts `iterator` to an array.
44025              *
44026              * @private
44027              * @param {Object} iterator The iterator to convert.
44028              * @returns {Array} Returns the converted array.
44029              */
44030
44031
44032             function iteratorToArray(iterator) {
44033               var data,
44034                   result = [];
44035
44036               while (!(data = iterator.next()).done) {
44037                 result.push(data.value);
44038               }
44039
44040               return result;
44041             }
44042             /**
44043              * Converts `map` to its key-value pairs.
44044              *
44045              * @private
44046              * @param {Object} map The map to convert.
44047              * @returns {Array} Returns the key-value pairs.
44048              */
44049
44050
44051             function mapToArray(map) {
44052               var index = -1,
44053                   result = Array(map.size);
44054               map.forEach(function (value, key) {
44055                 result[++index] = [key, value];
44056               });
44057               return result;
44058             }
44059             /**
44060              * Creates a unary function that invokes `func` with its argument transformed.
44061              *
44062              * @private
44063              * @param {Function} func The function to wrap.
44064              * @param {Function} transform The argument transform.
44065              * @returns {Function} Returns the new function.
44066              */
44067
44068
44069             function overArg(func, transform) {
44070               return function (arg) {
44071                 return func(transform(arg));
44072               };
44073             }
44074             /**
44075              * Replaces all `placeholder` elements in `array` with an internal placeholder
44076              * and returns an array of their indexes.
44077              *
44078              * @private
44079              * @param {Array} array The array to modify.
44080              * @param {*} placeholder The placeholder to replace.
44081              * @returns {Array} Returns the new array of placeholder indexes.
44082              */
44083
44084
44085             function replaceHolders(array, placeholder) {
44086               var index = -1,
44087                   length = array.length,
44088                   resIndex = 0,
44089                   result = [];
44090
44091               while (++index < length) {
44092                 var value = array[index];
44093
44094                 if (value === placeholder || value === PLACEHOLDER) {
44095                   array[index] = PLACEHOLDER;
44096                   result[resIndex++] = index;
44097                 }
44098               }
44099
44100               return result;
44101             }
44102             /**
44103              * Converts `set` to an array of its values.
44104              *
44105              * @private
44106              * @param {Object} set The set to convert.
44107              * @returns {Array} Returns the values.
44108              */
44109
44110
44111             function setToArray(set) {
44112               var index = -1,
44113                   result = Array(set.size);
44114               set.forEach(function (value) {
44115                 result[++index] = value;
44116               });
44117               return result;
44118             }
44119             /**
44120              * Converts `set` to its value-value pairs.
44121              *
44122              * @private
44123              * @param {Object} set The set to convert.
44124              * @returns {Array} Returns the value-value pairs.
44125              */
44126
44127
44128             function setToPairs(set) {
44129               var index = -1,
44130                   result = Array(set.size);
44131               set.forEach(function (value) {
44132                 result[++index] = [value, value];
44133               });
44134               return result;
44135             }
44136             /**
44137              * A specialized version of `_.indexOf` which performs strict equality
44138              * comparisons of values, i.e. `===`.
44139              *
44140              * @private
44141              * @param {Array} array The array to inspect.
44142              * @param {*} value The value to search for.
44143              * @param {number} fromIndex The index to search from.
44144              * @returns {number} Returns the index of the matched value, else `-1`.
44145              */
44146
44147
44148             function strictIndexOf(array, value, fromIndex) {
44149               var index = fromIndex - 1,
44150                   length = array.length;
44151
44152               while (++index < length) {
44153                 if (array[index] === value) {
44154                   return index;
44155                 }
44156               }
44157
44158               return -1;
44159             }
44160             /**
44161              * A specialized version of `_.lastIndexOf` which performs strict equality
44162              * comparisons of values, i.e. `===`.
44163              *
44164              * @private
44165              * @param {Array} array The array to inspect.
44166              * @param {*} value The value to search for.
44167              * @param {number} fromIndex The index to search from.
44168              * @returns {number} Returns the index of the matched value, else `-1`.
44169              */
44170
44171
44172             function strictLastIndexOf(array, value, fromIndex) {
44173               var index = fromIndex + 1;
44174
44175               while (index--) {
44176                 if (array[index] === value) {
44177                   return index;
44178                 }
44179               }
44180
44181               return index;
44182             }
44183             /**
44184              * Gets the number of symbols in `string`.
44185              *
44186              * @private
44187              * @param {string} string The string to inspect.
44188              * @returns {number} Returns the string size.
44189              */
44190
44191
44192             function stringSize(string) {
44193               return hasUnicode(string) ? unicodeSize(string) : asciiSize(string);
44194             }
44195             /**
44196              * Converts `string` to an array.
44197              *
44198              * @private
44199              * @param {string} string The string to convert.
44200              * @returns {Array} Returns the converted array.
44201              */
44202
44203
44204             function stringToArray(string) {
44205               return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);
44206             }
44207             /**
44208              * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
44209              * character of `string`.
44210              *
44211              * @private
44212              * @param {string} string The string to inspect.
44213              * @returns {number} Returns the index of the last non-whitespace character.
44214              */
44215
44216
44217             function trimmedEndIndex(string) {
44218               var index = string.length;
44219
44220               while (index-- && reWhitespace.test(string.charAt(index))) {}
44221
44222               return index;
44223             }
44224             /**
44225              * Used by `_.unescape` to convert HTML entities to characters.
44226              *
44227              * @private
44228              * @param {string} chr The matched character to unescape.
44229              * @returns {string} Returns the unescaped character.
44230              */
44231
44232
44233             var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
44234             /**
44235              * Gets the size of a Unicode `string`.
44236              *
44237              * @private
44238              * @param {string} string The string inspect.
44239              * @returns {number} Returns the string size.
44240              */
44241
44242             function unicodeSize(string) {
44243               var result = reUnicode.lastIndex = 0;
44244
44245               while (reUnicode.test(string)) {
44246                 ++result;
44247               }
44248
44249               return result;
44250             }
44251             /**
44252              * Converts a Unicode `string` to an array.
44253              *
44254              * @private
44255              * @param {string} string The string to convert.
44256              * @returns {Array} Returns the converted array.
44257              */
44258
44259
44260             function unicodeToArray(string) {
44261               return string.match(reUnicode) || [];
44262             }
44263             /**
44264              * Splits a Unicode `string` into an array of its words.
44265              *
44266              * @private
44267              * @param {string} The string to inspect.
44268              * @returns {Array} Returns the words of `string`.
44269              */
44270
44271
44272             function unicodeWords(string) {
44273               return string.match(reUnicodeWord) || [];
44274             }
44275             /*--------------------------------------------------------------------------*/
44276
44277             /**
44278              * Create a new pristine `lodash` function using the `context` object.
44279              *
44280              * @static
44281              * @memberOf _
44282              * @since 1.1.0
44283              * @category Util
44284              * @param {Object} [context=root] The context object.
44285              * @returns {Function} Returns a new `lodash` function.
44286              * @example
44287              *
44288              * _.mixin({ 'foo': _.constant('foo') });
44289              *
44290              * var lodash = _.runInContext();
44291              * lodash.mixin({ 'bar': lodash.constant('bar') });
44292              *
44293              * _.isFunction(_.foo);
44294              * // => true
44295              * _.isFunction(_.bar);
44296              * // => false
44297              *
44298              * lodash.isFunction(lodash.foo);
44299              * // => false
44300              * lodash.isFunction(lodash.bar);
44301              * // => true
44302              *
44303              * // Create a suped-up `defer` in Node.js.
44304              * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
44305              */
44306
44307
44308             var runInContext = function runInContext(context) {
44309               context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
44310               /** Built-in constructor references. */
44311
44312               var Array = context.Array,
44313                   Date = context.Date,
44314                   Error = context.Error,
44315                   Function = context.Function,
44316                   Math = context.Math,
44317                   Object = context.Object,
44318                   RegExp = context.RegExp,
44319                   String = context.String,
44320                   TypeError = context.TypeError;
44321               /** Used for built-in method references. */
44322
44323               var arrayProto = Array.prototype,
44324                   funcProto = Function.prototype,
44325                   objectProto = Object.prototype;
44326               /** Used to detect overreaching core-js shims. */
44327
44328               var coreJsData = context['__core-js_shared__'];
44329               /** Used to resolve the decompiled source of functions. */
44330
44331               var funcToString = funcProto.toString;
44332               /** Used to check objects for own properties. */
44333
44334               var hasOwnProperty = objectProto.hasOwnProperty;
44335               /** Used to generate unique IDs. */
44336
44337               var idCounter = 0;
44338               /** Used to detect methods masquerading as native. */
44339
44340               var maskSrcKey = function () {
44341                 var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
44342                 return uid ? 'Symbol(src)_1.' + uid : '';
44343               }();
44344               /**
44345                * Used to resolve the
44346                * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
44347                * of values.
44348                */
44349
44350
44351               var nativeObjectToString = objectProto.toString;
44352               /** Used to infer the `Object` constructor. */
44353
44354               var objectCtorString = funcToString.call(Object);
44355               /** Used to restore the original `_` reference in `_.noConflict`. */
44356
44357               var oldDash = root._;
44358               /** Used to detect if a method is native. */
44359
44360               var reIsNative = RegExp('^' + funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$');
44361               /** Built-in value references. */
44362
44363               var Buffer = moduleExports ? context.Buffer : undefined$1,
44364                   _Symbol = context.Symbol,
44365                   Uint8Array = context.Uint8Array,
44366                   allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined$1,
44367                   getPrototype = overArg(Object.getPrototypeOf, Object),
44368                   objectCreate = Object.create,
44369                   propertyIsEnumerable = objectProto.propertyIsEnumerable,
44370                   splice = arrayProto.splice,
44371                   spreadableSymbol = _Symbol ? _Symbol.isConcatSpreadable : undefined$1,
44372                   symIterator = _Symbol ? _Symbol.iterator : undefined$1,
44373                   symToStringTag = _Symbol ? _Symbol.toStringTag : undefined$1;
44374
44375               var defineProperty = function () {
44376                 try {
44377                   var func = getNative(Object, 'defineProperty');
44378                   func({}, '', {});
44379                   return func;
44380                 } catch (e) {}
44381               }();
44382               /** Mocked built-ins. */
44383
44384
44385               var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
44386                   ctxNow = Date && Date.now !== root.Date.now && Date.now,
44387                   ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
44388               /* Built-in method references for those with the same name as other `lodash` methods. */
44389
44390               var nativeCeil = Math.ceil,
44391                   nativeFloor = Math.floor,
44392                   nativeGetSymbols = Object.getOwnPropertySymbols,
44393                   nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined$1,
44394                   nativeIsFinite = context.isFinite,
44395                   nativeJoin = arrayProto.join,
44396                   nativeKeys = overArg(Object.keys, Object),
44397                   nativeMax = Math.max,
44398                   nativeMin = Math.min,
44399                   nativeNow = Date.now,
44400                   nativeParseInt = context.parseInt,
44401                   nativeRandom = Math.random,
44402                   nativeReverse = arrayProto.reverse;
44403               /* Built-in method references that are verified to be native. */
44404
44405               var DataView = getNative(context, 'DataView'),
44406                   Map = getNative(context, 'Map'),
44407                   Promise = getNative(context, 'Promise'),
44408                   Set = getNative(context, 'Set'),
44409                   WeakMap = getNative(context, 'WeakMap'),
44410                   nativeCreate = getNative(Object, 'create');
44411               /** Used to store function metadata. */
44412
44413               var metaMap = WeakMap && new WeakMap();
44414               /** Used to lookup unminified function names. */
44415
44416               var realNames = {};
44417               /** Used to detect maps, sets, and weakmaps. */
44418
44419               var dataViewCtorString = toSource(DataView),
44420                   mapCtorString = toSource(Map),
44421                   promiseCtorString = toSource(Promise),
44422                   setCtorString = toSource(Set),
44423                   weakMapCtorString = toSource(WeakMap);
44424               /** Used to convert symbols to primitives and strings. */
44425
44426               var symbolProto = _Symbol ? _Symbol.prototype : undefined$1,
44427                   symbolValueOf = symbolProto ? symbolProto.valueOf : undefined$1,
44428                   symbolToString = symbolProto ? symbolProto.toString : undefined$1;
44429               /*------------------------------------------------------------------------*/
44430
44431               /**
44432                * Creates a `lodash` object which wraps `value` to enable implicit method
44433                * chain sequences. Methods that operate on and return arrays, collections,
44434                * and functions can be chained together. Methods that retrieve a single value
44435                * or may return a primitive value will automatically end the chain sequence
44436                * and return the unwrapped value. Otherwise, the value must be unwrapped
44437                * with `_#value`.
44438                *
44439                * Explicit chain sequences, which must be unwrapped with `_#value`, may be
44440                * enabled using `_.chain`.
44441                *
44442                * The execution of chained methods is lazy, that is, it's deferred until
44443                * `_#value` is implicitly or explicitly called.
44444                *
44445                * Lazy evaluation allows several methods to support shortcut fusion.
44446                * Shortcut fusion is an optimization to merge iteratee calls; this avoids
44447                * the creation of intermediate arrays and can greatly reduce the number of
44448                * iteratee executions. Sections of a chain sequence qualify for shortcut
44449                * fusion if the section is applied to an array and iteratees accept only
44450                * one argument. The heuristic for whether a section qualifies for shortcut
44451                * fusion is subject to change.
44452                *
44453                * Chaining is supported in custom builds as long as the `_#value` method is
44454                * directly or indirectly included in the build.
44455                *
44456                * In addition to lodash methods, wrappers have `Array` and `String` methods.
44457                *
44458                * The wrapper `Array` methods are:
44459                * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
44460                *
44461                * The wrapper `String` methods are:
44462                * `replace` and `split`
44463                *
44464                * The wrapper methods that support shortcut fusion are:
44465                * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
44466                * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
44467                * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
44468                *
44469                * The chainable wrapper methods are:
44470                * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
44471                * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
44472                * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
44473                * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
44474                * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
44475                * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
44476                * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
44477                * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
44478                * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
44479                * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
44480                * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
44481                * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
44482                * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
44483                * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
44484                * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
44485                * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
44486                * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
44487                * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
44488                * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
44489                * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
44490                * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
44491                * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
44492                * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
44493                * `zipObject`, `zipObjectDeep`, and `zipWith`
44494                *
44495                * The wrapper methods that are **not** chainable by default are:
44496                * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
44497                * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
44498                * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
44499                * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
44500                * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
44501                * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
44502                * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
44503                * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
44504                * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
44505                * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
44506                * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
44507                * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
44508                * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
44509                * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
44510                * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
44511                * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
44512                * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
44513                * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
44514                * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
44515                * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
44516                * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
44517                * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
44518                * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
44519                * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
44520                * `upperFirst`, `value`, and `words`
44521                *
44522                * @name _
44523                * @constructor
44524                * @category Seq
44525                * @param {*} value The value to wrap in a `lodash` instance.
44526                * @returns {Object} Returns the new `lodash` wrapper instance.
44527                * @example
44528                *
44529                * function square(n) {
44530                *   return n * n;
44531                * }
44532                *
44533                * var wrapped = _([1, 2, 3]);
44534                *
44535                * // Returns an unwrapped value.
44536                * wrapped.reduce(_.add);
44537                * // => 6
44538                *
44539                * // Returns a wrapped value.
44540                * var squares = wrapped.map(square);
44541                *
44542                * _.isArray(squares);
44543                * // => false
44544                *
44545                * _.isArray(squares.value());
44546                * // => true
44547                */
44548
44549               function lodash(value) {
44550                 if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
44551                   if (value instanceof LodashWrapper) {
44552                     return value;
44553                   }
44554
44555                   if (hasOwnProperty.call(value, '__wrapped__')) {
44556                     return wrapperClone(value);
44557                   }
44558                 }
44559
44560                 return new LodashWrapper(value);
44561               }
44562               /**
44563                * The base implementation of `_.create` without support for assigning
44564                * properties to the created object.
44565                *
44566                * @private
44567                * @param {Object} proto The object to inherit from.
44568                * @returns {Object} Returns the new object.
44569                */
44570
44571
44572               var baseCreate = function () {
44573                 function object() {}
44574
44575                 return function (proto) {
44576                   if (!isObject(proto)) {
44577                     return {};
44578                   }
44579
44580                   if (objectCreate) {
44581                     return objectCreate(proto);
44582                   }
44583
44584                   object.prototype = proto;
44585                   var result = new object();
44586                   object.prototype = undefined$1;
44587                   return result;
44588                 };
44589               }();
44590               /**
44591                * The function whose prototype chain sequence wrappers inherit from.
44592                *
44593                * @private
44594                */
44595
44596
44597               function baseLodash() {// No operation performed.
44598               }
44599               /**
44600                * The base constructor for creating `lodash` wrapper objects.
44601                *
44602                * @private
44603                * @param {*} value The value to wrap.
44604                * @param {boolean} [chainAll] Enable explicit method chain sequences.
44605                */
44606
44607
44608               function LodashWrapper(value, chainAll) {
44609                 this.__wrapped__ = value;
44610                 this.__actions__ = [];
44611                 this.__chain__ = !!chainAll;
44612                 this.__index__ = 0;
44613                 this.__values__ = undefined$1;
44614               }
44615               /**
44616                * By default, the template delimiters used by lodash are like those in
44617                * embedded Ruby (ERB) as well as ES2015 template strings. Change the
44618                * following template settings to use alternative delimiters.
44619                *
44620                * @static
44621                * @memberOf _
44622                * @type {Object}
44623                */
44624
44625
44626               lodash.templateSettings = {
44627                 /**
44628                  * Used to detect `data` property values to be HTML-escaped.
44629                  *
44630                  * @memberOf _.templateSettings
44631                  * @type {RegExp}
44632                  */
44633                 'escape': reEscape,
44634
44635                 /**
44636                  * Used to detect code to be evaluated.
44637                  *
44638                  * @memberOf _.templateSettings
44639                  * @type {RegExp}
44640                  */
44641                 'evaluate': reEvaluate,
44642
44643                 /**
44644                  * Used to detect `data` property values to inject.
44645                  *
44646                  * @memberOf _.templateSettings
44647                  * @type {RegExp}
44648                  */
44649                 'interpolate': reInterpolate,
44650
44651                 /**
44652                  * Used to reference the data object in the template text.
44653                  *
44654                  * @memberOf _.templateSettings
44655                  * @type {string}
44656                  */
44657                 'variable': '',
44658
44659                 /**
44660                  * Used to import variables into the compiled template.
44661                  *
44662                  * @memberOf _.templateSettings
44663                  * @type {Object}
44664                  */
44665                 'imports': {
44666                   /**
44667                    * A reference to the `lodash` function.
44668                    *
44669                    * @memberOf _.templateSettings.imports
44670                    * @type {Function}
44671                    */
44672                   '_': lodash
44673                 }
44674               }; // Ensure wrappers are instances of `baseLodash`.
44675
44676               lodash.prototype = baseLodash.prototype;
44677               lodash.prototype.constructor = lodash;
44678               LodashWrapper.prototype = baseCreate(baseLodash.prototype);
44679               LodashWrapper.prototype.constructor = LodashWrapper;
44680               /*------------------------------------------------------------------------*/
44681
44682               /**
44683                * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
44684                *
44685                * @private
44686                * @constructor
44687                * @param {*} value The value to wrap.
44688                */
44689
44690               function LazyWrapper(value) {
44691                 this.__wrapped__ = value;
44692                 this.__actions__ = [];
44693                 this.__dir__ = 1;
44694                 this.__filtered__ = false;
44695                 this.__iteratees__ = [];
44696                 this.__takeCount__ = MAX_ARRAY_LENGTH;
44697                 this.__views__ = [];
44698               }
44699               /**
44700                * Creates a clone of the lazy wrapper object.
44701                *
44702                * @private
44703                * @name clone
44704                * @memberOf LazyWrapper
44705                * @returns {Object} Returns the cloned `LazyWrapper` object.
44706                */
44707
44708
44709               function lazyClone() {
44710                 var result = new LazyWrapper(this.__wrapped__);
44711                 result.__actions__ = copyArray(this.__actions__);
44712                 result.__dir__ = this.__dir__;
44713                 result.__filtered__ = this.__filtered__;
44714                 result.__iteratees__ = copyArray(this.__iteratees__);
44715                 result.__takeCount__ = this.__takeCount__;
44716                 result.__views__ = copyArray(this.__views__);
44717                 return result;
44718               }
44719               /**
44720                * Reverses the direction of lazy iteration.
44721                *
44722                * @private
44723                * @name reverse
44724                * @memberOf LazyWrapper
44725                * @returns {Object} Returns the new reversed `LazyWrapper` object.
44726                */
44727
44728
44729               function lazyReverse() {
44730                 if (this.__filtered__) {
44731                   var result = new LazyWrapper(this);
44732                   result.__dir__ = -1;
44733                   result.__filtered__ = true;
44734                 } else {
44735                   result = this.clone();
44736                   result.__dir__ *= -1;
44737                 }
44738
44739                 return result;
44740               }
44741               /**
44742                * Extracts the unwrapped value from its lazy wrapper.
44743                *
44744                * @private
44745                * @name value
44746                * @memberOf LazyWrapper
44747                * @returns {*} Returns the unwrapped value.
44748                */
44749
44750
44751               function lazyValue() {
44752                 var array = this.__wrapped__.value(),
44753                     dir = this.__dir__,
44754                     isArr = isArray(array),
44755                     isRight = dir < 0,
44756                     arrLength = isArr ? array.length : 0,
44757                     view = getView(0, arrLength, this.__views__),
44758                     start = view.start,
44759                     end = view.end,
44760                     length = end - start,
44761                     index = isRight ? end : start - 1,
44762                     iteratees = this.__iteratees__,
44763                     iterLength = iteratees.length,
44764                     resIndex = 0,
44765                     takeCount = nativeMin(length, this.__takeCount__);
44766
44767                 if (!isArr || !isRight && arrLength == length && takeCount == length) {
44768                   return baseWrapperValue(array, this.__actions__);
44769                 }
44770
44771                 var result = [];
44772
44773                 outer: while (length-- && resIndex < takeCount) {
44774                   index += dir;
44775                   var iterIndex = -1,
44776                       value = array[index];
44777
44778                   while (++iterIndex < iterLength) {
44779                     var data = iteratees[iterIndex],
44780                         iteratee = data.iteratee,
44781                         type = data.type,
44782                         computed = iteratee(value);
44783
44784                     if (type == LAZY_MAP_FLAG) {
44785                       value = computed;
44786                     } else if (!computed) {
44787                       if (type == LAZY_FILTER_FLAG) {
44788                         continue outer;
44789                       } else {
44790                         break outer;
44791                       }
44792                     }
44793                   }
44794
44795                   result[resIndex++] = value;
44796                 }
44797
44798                 return result;
44799               } // Ensure `LazyWrapper` is an instance of `baseLodash`.
44800
44801
44802               LazyWrapper.prototype = baseCreate(baseLodash.prototype);
44803               LazyWrapper.prototype.constructor = LazyWrapper;
44804               /*------------------------------------------------------------------------*/
44805
44806               /**
44807                * Creates a hash object.
44808                *
44809                * @private
44810                * @constructor
44811                * @param {Array} [entries] The key-value pairs to cache.
44812                */
44813
44814               function Hash(entries) {
44815                 var index = -1,
44816                     length = entries == null ? 0 : entries.length;
44817                 this.clear();
44818
44819                 while (++index < length) {
44820                   var entry = entries[index];
44821                   this.set(entry[0], entry[1]);
44822                 }
44823               }
44824               /**
44825                * Removes all key-value entries from the hash.
44826                *
44827                * @private
44828                * @name clear
44829                * @memberOf Hash
44830                */
44831
44832
44833               function hashClear() {
44834                 this.__data__ = nativeCreate ? nativeCreate(null) : {};
44835                 this.size = 0;
44836               }
44837               /**
44838                * Removes `key` and its value from the hash.
44839                *
44840                * @private
44841                * @name delete
44842                * @memberOf Hash
44843                * @param {Object} hash The hash to modify.
44844                * @param {string} key The key of the value to remove.
44845                * @returns {boolean} Returns `true` if the entry was removed, else `false`.
44846                */
44847
44848
44849               function hashDelete(key) {
44850                 var result = this.has(key) && delete this.__data__[key];
44851                 this.size -= result ? 1 : 0;
44852                 return result;
44853               }
44854               /**
44855                * Gets the hash value for `key`.
44856                *
44857                * @private
44858                * @name get
44859                * @memberOf Hash
44860                * @param {string} key The key of the value to get.
44861                * @returns {*} Returns the entry value.
44862                */
44863
44864
44865               function hashGet(key) {
44866                 var data = this.__data__;
44867
44868                 if (nativeCreate) {
44869                   var result = data[key];
44870                   return result === HASH_UNDEFINED ? undefined$1 : result;
44871                 }
44872
44873                 return hasOwnProperty.call(data, key) ? data[key] : undefined$1;
44874               }
44875               /**
44876                * Checks if a hash value for `key` exists.
44877                *
44878                * @private
44879                * @name has
44880                * @memberOf Hash
44881                * @param {string} key The key of the entry to check.
44882                * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
44883                */
44884
44885
44886               function hashHas(key) {
44887                 var data = this.__data__;
44888                 return nativeCreate ? data[key] !== undefined$1 : hasOwnProperty.call(data, key);
44889               }
44890               /**
44891                * Sets the hash `key` to `value`.
44892                *
44893                * @private
44894                * @name set
44895                * @memberOf Hash
44896                * @param {string} key The key of the value to set.
44897                * @param {*} value The value to set.
44898                * @returns {Object} Returns the hash instance.
44899                */
44900
44901
44902               function hashSet(key, value) {
44903                 var data = this.__data__;
44904                 this.size += this.has(key) ? 0 : 1;
44905                 data[key] = nativeCreate && value === undefined$1 ? HASH_UNDEFINED : value;
44906                 return this;
44907               } // Add methods to `Hash`.
44908
44909
44910               Hash.prototype.clear = hashClear;
44911               Hash.prototype['delete'] = hashDelete;
44912               Hash.prototype.get = hashGet;
44913               Hash.prototype.has = hashHas;
44914               Hash.prototype.set = hashSet;
44915               /*------------------------------------------------------------------------*/
44916
44917               /**
44918                * Creates an list cache object.
44919                *
44920                * @private
44921                * @constructor
44922                * @param {Array} [entries] The key-value pairs to cache.
44923                */
44924
44925               function ListCache(entries) {
44926                 var index = -1,
44927                     length = entries == null ? 0 : entries.length;
44928                 this.clear();
44929
44930                 while (++index < length) {
44931                   var entry = entries[index];
44932                   this.set(entry[0], entry[1]);
44933                 }
44934               }
44935               /**
44936                * Removes all key-value entries from the list cache.
44937                *
44938                * @private
44939                * @name clear
44940                * @memberOf ListCache
44941                */
44942
44943
44944               function listCacheClear() {
44945                 this.__data__ = [];
44946                 this.size = 0;
44947               }
44948               /**
44949                * Removes `key` and its value from the list cache.
44950                *
44951                * @private
44952                * @name delete
44953                * @memberOf ListCache
44954                * @param {string} key The key of the value to remove.
44955                * @returns {boolean} Returns `true` if the entry was removed, else `false`.
44956                */
44957
44958
44959               function listCacheDelete(key) {
44960                 var data = this.__data__,
44961                     index = assocIndexOf(data, key);
44962
44963                 if (index < 0) {
44964                   return false;
44965                 }
44966
44967                 var lastIndex = data.length - 1;
44968
44969                 if (index == lastIndex) {
44970                   data.pop();
44971                 } else {
44972                   splice.call(data, index, 1);
44973                 }
44974
44975                 --this.size;
44976                 return true;
44977               }
44978               /**
44979                * Gets the list cache value for `key`.
44980                *
44981                * @private
44982                * @name get
44983                * @memberOf ListCache
44984                * @param {string} key The key of the value to get.
44985                * @returns {*} Returns the entry value.
44986                */
44987
44988
44989               function listCacheGet(key) {
44990                 var data = this.__data__,
44991                     index = assocIndexOf(data, key);
44992                 return index < 0 ? undefined$1 : data[index][1];
44993               }
44994               /**
44995                * Checks if a list cache value for `key` exists.
44996                *
44997                * @private
44998                * @name has
44999                * @memberOf ListCache
45000                * @param {string} key The key of the entry to check.
45001                * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
45002                */
45003
45004
45005               function listCacheHas(key) {
45006                 return assocIndexOf(this.__data__, key) > -1;
45007               }
45008               /**
45009                * Sets the list cache `key` to `value`.
45010                *
45011                * @private
45012                * @name set
45013                * @memberOf ListCache
45014                * @param {string} key The key of the value to set.
45015                * @param {*} value The value to set.
45016                * @returns {Object} Returns the list cache instance.
45017                */
45018
45019
45020               function listCacheSet(key, value) {
45021                 var data = this.__data__,
45022                     index = assocIndexOf(data, key);
45023
45024                 if (index < 0) {
45025                   ++this.size;
45026                   data.push([key, value]);
45027                 } else {
45028                   data[index][1] = value;
45029                 }
45030
45031                 return this;
45032               } // Add methods to `ListCache`.
45033
45034
45035               ListCache.prototype.clear = listCacheClear;
45036               ListCache.prototype['delete'] = listCacheDelete;
45037               ListCache.prototype.get = listCacheGet;
45038               ListCache.prototype.has = listCacheHas;
45039               ListCache.prototype.set = listCacheSet;
45040               /*------------------------------------------------------------------------*/
45041
45042               /**
45043                * Creates a map cache object to store key-value pairs.
45044                *
45045                * @private
45046                * @constructor
45047                * @param {Array} [entries] The key-value pairs to cache.
45048                */
45049
45050               function MapCache(entries) {
45051                 var index = -1,
45052                     length = entries == null ? 0 : entries.length;
45053                 this.clear();
45054
45055                 while (++index < length) {
45056                   var entry = entries[index];
45057                   this.set(entry[0], entry[1]);
45058                 }
45059               }
45060               /**
45061                * Removes all key-value entries from the map.
45062                *
45063                * @private
45064                * @name clear
45065                * @memberOf MapCache
45066                */
45067
45068
45069               function mapCacheClear() {
45070                 this.size = 0;
45071                 this.__data__ = {
45072                   'hash': new Hash(),
45073                   'map': new (Map || ListCache)(),
45074                   'string': new Hash()
45075                 };
45076               }
45077               /**
45078                * Removes `key` and its value from the map.
45079                *
45080                * @private
45081                * @name delete
45082                * @memberOf MapCache
45083                * @param {string} key The key of the value to remove.
45084                * @returns {boolean} Returns `true` if the entry was removed, else `false`.
45085                */
45086
45087
45088               function mapCacheDelete(key) {
45089                 var result = getMapData(this, key)['delete'](key);
45090                 this.size -= result ? 1 : 0;
45091                 return result;
45092               }
45093               /**
45094                * Gets the map value for `key`.
45095                *
45096                * @private
45097                * @name get
45098                * @memberOf MapCache
45099                * @param {string} key The key of the value to get.
45100                * @returns {*} Returns the entry value.
45101                */
45102
45103
45104               function mapCacheGet(key) {
45105                 return getMapData(this, key).get(key);
45106               }
45107               /**
45108                * Checks if a map value for `key` exists.
45109                *
45110                * @private
45111                * @name has
45112                * @memberOf MapCache
45113                * @param {string} key The key of the entry to check.
45114                * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
45115                */
45116
45117
45118               function mapCacheHas(key) {
45119                 return getMapData(this, key).has(key);
45120               }
45121               /**
45122                * Sets the map `key` to `value`.
45123                *
45124                * @private
45125                * @name set
45126                * @memberOf MapCache
45127                * @param {string} key The key of the value to set.
45128                * @param {*} value The value to set.
45129                * @returns {Object} Returns the map cache instance.
45130                */
45131
45132
45133               function mapCacheSet(key, value) {
45134                 var data = getMapData(this, key),
45135                     size = data.size;
45136                 data.set(key, value);
45137                 this.size += data.size == size ? 0 : 1;
45138                 return this;
45139               } // Add methods to `MapCache`.
45140
45141
45142               MapCache.prototype.clear = mapCacheClear;
45143               MapCache.prototype['delete'] = mapCacheDelete;
45144               MapCache.prototype.get = mapCacheGet;
45145               MapCache.prototype.has = mapCacheHas;
45146               MapCache.prototype.set = mapCacheSet;
45147               /*------------------------------------------------------------------------*/
45148
45149               /**
45150                *
45151                * Creates an array cache object to store unique values.
45152                *
45153                * @private
45154                * @constructor
45155                * @param {Array} [values] The values to cache.
45156                */
45157
45158               function SetCache(values) {
45159                 var index = -1,
45160                     length = values == null ? 0 : values.length;
45161                 this.__data__ = new MapCache();
45162
45163                 while (++index < length) {
45164                   this.add(values[index]);
45165                 }
45166               }
45167               /**
45168                * Adds `value` to the array cache.
45169                *
45170                * @private
45171                * @name add
45172                * @memberOf SetCache
45173                * @alias push
45174                * @param {*} value The value to cache.
45175                * @returns {Object} Returns the cache instance.
45176                */
45177
45178
45179               function setCacheAdd(value) {
45180                 this.__data__.set(value, HASH_UNDEFINED);
45181
45182                 return this;
45183               }
45184               /**
45185                * Checks if `value` is in the array cache.
45186                *
45187                * @private
45188                * @name has
45189                * @memberOf SetCache
45190                * @param {*} value The value to search for.
45191                * @returns {number} Returns `true` if `value` is found, else `false`.
45192                */
45193
45194
45195               function setCacheHas(value) {
45196                 return this.__data__.has(value);
45197               } // Add methods to `SetCache`.
45198
45199
45200               SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
45201               SetCache.prototype.has = setCacheHas;
45202               /*------------------------------------------------------------------------*/
45203
45204               /**
45205                * Creates a stack cache object to store key-value pairs.
45206                *
45207                * @private
45208                * @constructor
45209                * @param {Array} [entries] The key-value pairs to cache.
45210                */
45211
45212               function Stack(entries) {
45213                 var data = this.__data__ = new ListCache(entries);
45214                 this.size = data.size;
45215               }
45216               /**
45217                * Removes all key-value entries from the stack.
45218                *
45219                * @private
45220                * @name clear
45221                * @memberOf Stack
45222                */
45223
45224
45225               function stackClear() {
45226                 this.__data__ = new ListCache();
45227                 this.size = 0;
45228               }
45229               /**
45230                * Removes `key` and its value from the stack.
45231                *
45232                * @private
45233                * @name delete
45234                * @memberOf Stack
45235                * @param {string} key The key of the value to remove.
45236                * @returns {boolean} Returns `true` if the entry was removed, else `false`.
45237                */
45238
45239
45240               function stackDelete(key) {
45241                 var data = this.__data__,
45242                     result = data['delete'](key);
45243                 this.size = data.size;
45244                 return result;
45245               }
45246               /**
45247                * Gets the stack value for `key`.
45248                *
45249                * @private
45250                * @name get
45251                * @memberOf Stack
45252                * @param {string} key The key of the value to get.
45253                * @returns {*} Returns the entry value.
45254                */
45255
45256
45257               function stackGet(key) {
45258                 return this.__data__.get(key);
45259               }
45260               /**
45261                * Checks if a stack value for `key` exists.
45262                *
45263                * @private
45264                * @name has
45265                * @memberOf Stack
45266                * @param {string} key The key of the entry to check.
45267                * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
45268                */
45269
45270
45271               function stackHas(key) {
45272                 return this.__data__.has(key);
45273               }
45274               /**
45275                * Sets the stack `key` to `value`.
45276                *
45277                * @private
45278                * @name set
45279                * @memberOf Stack
45280                * @param {string} key The key of the value to set.
45281                * @param {*} value The value to set.
45282                * @returns {Object} Returns the stack cache instance.
45283                */
45284
45285
45286               function stackSet(key, value) {
45287                 var data = this.__data__;
45288
45289                 if (data instanceof ListCache) {
45290                   var pairs = data.__data__;
45291
45292                   if (!Map || pairs.length < LARGE_ARRAY_SIZE - 1) {
45293                     pairs.push([key, value]);
45294                     this.size = ++data.size;
45295                     return this;
45296                   }
45297
45298                   data = this.__data__ = new MapCache(pairs);
45299                 }
45300
45301                 data.set(key, value);
45302                 this.size = data.size;
45303                 return this;
45304               } // Add methods to `Stack`.
45305
45306
45307               Stack.prototype.clear = stackClear;
45308               Stack.prototype['delete'] = stackDelete;
45309               Stack.prototype.get = stackGet;
45310               Stack.prototype.has = stackHas;
45311               Stack.prototype.set = stackSet;
45312               /*------------------------------------------------------------------------*/
45313
45314               /**
45315                * Creates an array of the enumerable property names of the array-like `value`.
45316                *
45317                * @private
45318                * @param {*} value The value to query.
45319                * @param {boolean} inherited Specify returning inherited property names.
45320                * @returns {Array} Returns the array of property names.
45321                */
45322
45323               function arrayLikeKeys(value, inherited) {
45324                 var isArr = isArray(value),
45325                     isArg = !isArr && isArguments(value),
45326                     isBuff = !isArr && !isArg && isBuffer(value),
45327                     isType = !isArr && !isArg && !isBuff && isTypedArray(value),
45328                     skipIndexes = isArr || isArg || isBuff || isType,
45329                     result = skipIndexes ? baseTimes(value.length, String) : [],
45330                     length = result.length;
45331
45332                 for (var key in value) {
45333                   if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && ( // Safari 9 has enumerable `arguments.length` in strict mode.
45334                   key == 'length' || // Node.js 0.10 has enumerable non-index properties on buffers.
45335                   isBuff && (key == 'offset' || key == 'parent') || // PhantomJS 2 has enumerable non-index properties on typed arrays.
45336                   isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset') || // Skip index properties.
45337                   isIndex(key, length)))) {
45338                     result.push(key);
45339                   }
45340                 }
45341
45342                 return result;
45343               }
45344               /**
45345                * A specialized version of `_.sample` for arrays.
45346                *
45347                * @private
45348                * @param {Array} array The array to sample.
45349                * @returns {*} Returns the random element.
45350                */
45351
45352
45353               function arraySample(array) {
45354                 var length = array.length;
45355                 return length ? array[baseRandom(0, length - 1)] : undefined$1;
45356               }
45357               /**
45358                * A specialized version of `_.sampleSize` for arrays.
45359                *
45360                * @private
45361                * @param {Array} array The array to sample.
45362                * @param {number} n The number of elements to sample.
45363                * @returns {Array} Returns the random elements.
45364                */
45365
45366
45367               function arraySampleSize(array, n) {
45368                 return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
45369               }
45370               /**
45371                * A specialized version of `_.shuffle` for arrays.
45372                *
45373                * @private
45374                * @param {Array} array The array to shuffle.
45375                * @returns {Array} Returns the new shuffled array.
45376                */
45377
45378
45379               function arrayShuffle(array) {
45380                 return shuffleSelf(copyArray(array));
45381               }
45382               /**
45383                * This function is like `assignValue` except that it doesn't assign
45384                * `undefined` values.
45385                *
45386                * @private
45387                * @param {Object} object The object to modify.
45388                * @param {string} key The key of the property to assign.
45389                * @param {*} value The value to assign.
45390                */
45391
45392
45393               function assignMergeValue(object, key, value) {
45394                 if (value !== undefined$1 && !eq(object[key], value) || value === undefined$1 && !(key in object)) {
45395                   baseAssignValue(object, key, value);
45396                 }
45397               }
45398               /**
45399                * Assigns `value` to `key` of `object` if the existing value is not equivalent
45400                * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
45401                * for equality comparisons.
45402                *
45403                * @private
45404                * @param {Object} object The object to modify.
45405                * @param {string} key The key of the property to assign.
45406                * @param {*} value The value to assign.
45407                */
45408
45409
45410               function assignValue(object, key, value) {
45411                 var objValue = object[key];
45412
45413                 if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || value === undefined$1 && !(key in object)) {
45414                   baseAssignValue(object, key, value);
45415                 }
45416               }
45417               /**
45418                * Gets the index at which the `key` is found in `array` of key-value pairs.
45419                *
45420                * @private
45421                * @param {Array} array The array to inspect.
45422                * @param {*} key The key to search for.
45423                * @returns {number} Returns the index of the matched value, else `-1`.
45424                */
45425
45426
45427               function assocIndexOf(array, key) {
45428                 var length = array.length;
45429
45430                 while (length--) {
45431                   if (eq(array[length][0], key)) {
45432                     return length;
45433                   }
45434                 }
45435
45436                 return -1;
45437               }
45438               /**
45439                * Aggregates elements of `collection` on `accumulator` with keys transformed
45440                * by `iteratee` and values set by `setter`.
45441                *
45442                * @private
45443                * @param {Array|Object} collection The collection to iterate over.
45444                * @param {Function} setter The function to set `accumulator` values.
45445                * @param {Function} iteratee The iteratee to transform keys.
45446                * @param {Object} accumulator The initial aggregated object.
45447                * @returns {Function} Returns `accumulator`.
45448                */
45449
45450
45451               function baseAggregator(collection, setter, iteratee, accumulator) {
45452                 baseEach(collection, function (value, key, collection) {
45453                   setter(accumulator, value, iteratee(value), collection);
45454                 });
45455                 return accumulator;
45456               }
45457               /**
45458                * The base implementation of `_.assign` without support for multiple sources
45459                * or `customizer` functions.
45460                *
45461                * @private
45462                * @param {Object} object The destination object.
45463                * @param {Object} source The source object.
45464                * @returns {Object} Returns `object`.
45465                */
45466
45467
45468               function baseAssign(object, source) {
45469                 return object && copyObject(source, keys(source), object);
45470               }
45471               /**
45472                * The base implementation of `_.assignIn` without support for multiple sources
45473                * or `customizer` functions.
45474                *
45475                * @private
45476                * @param {Object} object The destination object.
45477                * @param {Object} source The source object.
45478                * @returns {Object} Returns `object`.
45479                */
45480
45481
45482               function baseAssignIn(object, source) {
45483                 return object && copyObject(source, keysIn(source), object);
45484               }
45485               /**
45486                * The base implementation of `assignValue` and `assignMergeValue` without
45487                * value checks.
45488                *
45489                * @private
45490                * @param {Object} object The object to modify.
45491                * @param {string} key The key of the property to assign.
45492                * @param {*} value The value to assign.
45493                */
45494
45495
45496               function baseAssignValue(object, key, value) {
45497                 if (key == '__proto__' && defineProperty) {
45498                   defineProperty(object, key, {
45499                     'configurable': true,
45500                     'enumerable': true,
45501                     'value': value,
45502                     'writable': true
45503                   });
45504                 } else {
45505                   object[key] = value;
45506                 }
45507               }
45508               /**
45509                * The base implementation of `_.at` without support for individual paths.
45510                *
45511                * @private
45512                * @param {Object} object The object to iterate over.
45513                * @param {string[]} paths The property paths to pick.
45514                * @returns {Array} Returns the picked elements.
45515                */
45516
45517
45518               function baseAt(object, paths) {
45519                 var index = -1,
45520                     length = paths.length,
45521                     result = Array(length),
45522                     skip = object == null;
45523
45524                 while (++index < length) {
45525                   result[index] = skip ? undefined$1 : get(object, paths[index]);
45526                 }
45527
45528                 return result;
45529               }
45530               /**
45531                * The base implementation of `_.clamp` which doesn't coerce arguments.
45532                *
45533                * @private
45534                * @param {number} number The number to clamp.
45535                * @param {number} [lower] The lower bound.
45536                * @param {number} upper The upper bound.
45537                * @returns {number} Returns the clamped number.
45538                */
45539
45540
45541               function baseClamp(number, lower, upper) {
45542                 if (number === number) {
45543                   if (upper !== undefined$1) {
45544                     number = number <= upper ? number : upper;
45545                   }
45546
45547                   if (lower !== undefined$1) {
45548                     number = number >= lower ? number : lower;
45549                   }
45550                 }
45551
45552                 return number;
45553               }
45554               /**
45555                * The base implementation of `_.clone` and `_.cloneDeep` which tracks
45556                * traversed objects.
45557                *
45558                * @private
45559                * @param {*} value The value to clone.
45560                * @param {boolean} bitmask The bitmask flags.
45561                *  1 - Deep clone
45562                *  2 - Flatten inherited properties
45563                *  4 - Clone symbols
45564                * @param {Function} [customizer] The function to customize cloning.
45565                * @param {string} [key] The key of `value`.
45566                * @param {Object} [object] The parent object of `value`.
45567                * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
45568                * @returns {*} Returns the cloned value.
45569                */
45570
45571
45572               function baseClone(value, bitmask, customizer, key, object, stack) {
45573                 var result,
45574                     isDeep = bitmask & CLONE_DEEP_FLAG,
45575                     isFlat = bitmask & CLONE_FLAT_FLAG,
45576                     isFull = bitmask & CLONE_SYMBOLS_FLAG;
45577
45578                 if (customizer) {
45579                   result = object ? customizer(value, key, object, stack) : customizer(value);
45580                 }
45581
45582                 if (result !== undefined$1) {
45583                   return result;
45584                 }
45585
45586                 if (!isObject(value)) {
45587                   return value;
45588                 }
45589
45590                 var isArr = isArray(value);
45591
45592                 if (isArr) {
45593                   result = initCloneArray(value);
45594
45595                   if (!isDeep) {
45596                     return copyArray(value, result);
45597                   }
45598                 } else {
45599                   var tag = getTag(value),
45600                       isFunc = tag == funcTag || tag == genTag;
45601
45602                   if (isBuffer(value)) {
45603                     return cloneBuffer(value, isDeep);
45604                   }
45605
45606                   if (tag == objectTag || tag == argsTag || isFunc && !object) {
45607                     result = isFlat || isFunc ? {} : initCloneObject(value);
45608
45609                     if (!isDeep) {
45610                       return isFlat ? copySymbolsIn(value, baseAssignIn(result, value)) : copySymbols(value, baseAssign(result, value));
45611                     }
45612                   } else {
45613                     if (!cloneableTags[tag]) {
45614                       return object ? value : {};
45615                     }
45616
45617                     result = initCloneByTag(value, tag, isDeep);
45618                   }
45619                 } // Check for circular references and return its corresponding clone.
45620
45621
45622                 stack || (stack = new Stack());
45623                 var stacked = stack.get(value);
45624
45625                 if (stacked) {
45626                   return stacked;
45627                 }
45628
45629                 stack.set(value, result);
45630
45631                 if (isSet(value)) {
45632                   value.forEach(function (subValue) {
45633                     result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
45634                   });
45635                 } else if (isMap(value)) {
45636                   value.forEach(function (subValue, key) {
45637                     result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
45638                   });
45639                 }
45640
45641                 var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys;
45642                 var props = isArr ? undefined$1 : keysFunc(value);
45643                 arrayEach(props || value, function (subValue, key) {
45644                   if (props) {
45645                     key = subValue;
45646                     subValue = value[key];
45647                   } // Recursively populate clone (susceptible to call stack limits).
45648
45649
45650                   assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
45651                 });
45652                 return result;
45653               }
45654               /**
45655                * The base implementation of `_.conforms` which doesn't clone `source`.
45656                *
45657                * @private
45658                * @param {Object} source The object of property predicates to conform to.
45659                * @returns {Function} Returns the new spec function.
45660                */
45661
45662
45663               function baseConforms(source) {
45664                 var props = keys(source);
45665                 return function (object) {
45666                   return baseConformsTo(object, source, props);
45667                 };
45668               }
45669               /**
45670                * The base implementation of `_.conformsTo` which accepts `props` to check.
45671                *
45672                * @private
45673                * @param {Object} object The object to inspect.
45674                * @param {Object} source The object of property predicates to conform to.
45675                * @returns {boolean} Returns `true` if `object` conforms, else `false`.
45676                */
45677
45678
45679               function baseConformsTo(object, source, props) {
45680                 var length = props.length;
45681
45682                 if (object == null) {
45683                   return !length;
45684                 }
45685
45686                 object = Object(object);
45687
45688                 while (length--) {
45689                   var key = props[length],
45690                       predicate = source[key],
45691                       value = object[key];
45692
45693                   if (value === undefined$1 && !(key in object) || !predicate(value)) {
45694                     return false;
45695                   }
45696                 }
45697
45698                 return true;
45699               }
45700               /**
45701                * The base implementation of `_.delay` and `_.defer` which accepts `args`
45702                * to provide to `func`.
45703                *
45704                * @private
45705                * @param {Function} func The function to delay.
45706                * @param {number} wait The number of milliseconds to delay invocation.
45707                * @param {Array} args The arguments to provide to `func`.
45708                * @returns {number|Object} Returns the timer id or timeout object.
45709                */
45710
45711
45712               function baseDelay(func, wait, args) {
45713                 if (typeof func != 'function') {
45714                   throw new TypeError(FUNC_ERROR_TEXT);
45715                 }
45716
45717                 return setTimeout(function () {
45718                   func.apply(undefined$1, args);
45719                 }, wait);
45720               }
45721               /**
45722                * The base implementation of methods like `_.difference` without support
45723                * for excluding multiple arrays or iteratee shorthands.
45724                *
45725                * @private
45726                * @param {Array} array The array to inspect.
45727                * @param {Array} values The values to exclude.
45728                * @param {Function} [iteratee] The iteratee invoked per element.
45729                * @param {Function} [comparator] The comparator invoked per element.
45730                * @returns {Array} Returns the new array of filtered values.
45731                */
45732
45733
45734               function baseDifference(array, values, iteratee, comparator) {
45735                 var index = -1,
45736                     includes = arrayIncludes,
45737                     isCommon = true,
45738                     length = array.length,
45739                     result = [],
45740                     valuesLength = values.length;
45741
45742                 if (!length) {
45743                   return result;
45744                 }
45745
45746                 if (iteratee) {
45747                   values = arrayMap(values, baseUnary(iteratee));
45748                 }
45749
45750                 if (comparator) {
45751                   includes = arrayIncludesWith;
45752                   isCommon = false;
45753                 } else if (values.length >= LARGE_ARRAY_SIZE) {
45754                   includes = cacheHas;
45755                   isCommon = false;
45756                   values = new SetCache(values);
45757                 }
45758
45759                 outer: while (++index < length) {
45760                   var value = array[index],
45761                       computed = iteratee == null ? value : iteratee(value);
45762                   value = comparator || value !== 0 ? value : 0;
45763
45764                   if (isCommon && computed === computed) {
45765                     var valuesIndex = valuesLength;
45766
45767                     while (valuesIndex--) {
45768                       if (values[valuesIndex] === computed) {
45769                         continue outer;
45770                       }
45771                     }
45772
45773                     result.push(value);
45774                   } else if (!includes(values, computed, comparator)) {
45775                     result.push(value);
45776                   }
45777                 }
45778
45779                 return result;
45780               }
45781               /**
45782                * The base implementation of `_.forEach` without support for iteratee shorthands.
45783                *
45784                * @private
45785                * @param {Array|Object} collection The collection to iterate over.
45786                * @param {Function} iteratee The function invoked per iteration.
45787                * @returns {Array|Object} Returns `collection`.
45788                */
45789
45790
45791               var baseEach = createBaseEach(baseForOwn);
45792               /**
45793                * The base implementation of `_.forEachRight` without support for iteratee shorthands.
45794                *
45795                * @private
45796                * @param {Array|Object} collection The collection to iterate over.
45797                * @param {Function} iteratee The function invoked per iteration.
45798                * @returns {Array|Object} Returns `collection`.
45799                */
45800
45801               var baseEachRight = createBaseEach(baseForOwnRight, true);
45802               /**
45803                * The base implementation of `_.every` without support for iteratee shorthands.
45804                *
45805                * @private
45806                * @param {Array|Object} collection The collection to iterate over.
45807                * @param {Function} predicate The function invoked per iteration.
45808                * @returns {boolean} Returns `true` if all elements pass the predicate check,
45809                *  else `false`
45810                */
45811
45812               function baseEvery(collection, predicate) {
45813                 var result = true;
45814                 baseEach(collection, function (value, index, collection) {
45815                   result = !!predicate(value, index, collection);
45816                   return result;
45817                 });
45818                 return result;
45819               }
45820               /**
45821                * The base implementation of methods like `_.max` and `_.min` which accepts a
45822                * `comparator` to determine the extremum value.
45823                *
45824                * @private
45825                * @param {Array} array The array to iterate over.
45826                * @param {Function} iteratee The iteratee invoked per iteration.
45827                * @param {Function} comparator The comparator used to compare values.
45828                * @returns {*} Returns the extremum value.
45829                */
45830
45831
45832               function baseExtremum(array, iteratee, comparator) {
45833                 var index = -1,
45834                     length = array.length;
45835
45836                 while (++index < length) {
45837                   var value = array[index],
45838                       current = iteratee(value);
45839
45840                   if (current != null && (computed === undefined$1 ? current === current && !isSymbol(current) : comparator(current, computed))) {
45841                     var computed = current,
45842                         result = value;
45843                   }
45844                 }
45845
45846                 return result;
45847               }
45848               /**
45849                * The base implementation of `_.fill` without an iteratee call guard.
45850                *
45851                * @private
45852                * @param {Array} array The array to fill.
45853                * @param {*} value The value to fill `array` with.
45854                * @param {number} [start=0] The start position.
45855                * @param {number} [end=array.length] The end position.
45856                * @returns {Array} Returns `array`.
45857                */
45858
45859
45860               function baseFill(array, value, start, end) {
45861                 var length = array.length;
45862                 start = toInteger(start);
45863
45864                 if (start < 0) {
45865                   start = -start > length ? 0 : length + start;
45866                 }
45867
45868                 end = end === undefined$1 || end > length ? length : toInteger(end);
45869
45870                 if (end < 0) {
45871                   end += length;
45872                 }
45873
45874                 end = start > end ? 0 : toLength(end);
45875
45876                 while (start < end) {
45877                   array[start++] = value;
45878                 }
45879
45880                 return array;
45881               }
45882               /**
45883                * The base implementation of `_.filter` without support for iteratee shorthands.
45884                *
45885                * @private
45886                * @param {Array|Object} collection The collection to iterate over.
45887                * @param {Function} predicate The function invoked per iteration.
45888                * @returns {Array} Returns the new filtered array.
45889                */
45890
45891
45892               function baseFilter(collection, predicate) {
45893                 var result = [];
45894                 baseEach(collection, function (value, index, collection) {
45895                   if (predicate(value, index, collection)) {
45896                     result.push(value);
45897                   }
45898                 });
45899                 return result;
45900               }
45901               /**
45902                * The base implementation of `_.flatten` with support for restricting flattening.
45903                *
45904                * @private
45905                * @param {Array} array The array to flatten.
45906                * @param {number} depth The maximum recursion depth.
45907                * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
45908                * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
45909                * @param {Array} [result=[]] The initial result value.
45910                * @returns {Array} Returns the new flattened array.
45911                */
45912
45913
45914               function baseFlatten(array, depth, predicate, isStrict, result) {
45915                 var index = -1,
45916                     length = array.length;
45917                 predicate || (predicate = isFlattenable);
45918                 result || (result = []);
45919
45920                 while (++index < length) {
45921                   var value = array[index];
45922
45923                   if (depth > 0 && predicate(value)) {
45924                     if (depth > 1) {
45925                       // Recursively flatten arrays (susceptible to call stack limits).
45926                       baseFlatten(value, depth - 1, predicate, isStrict, result);
45927                     } else {
45928                       arrayPush(result, value);
45929                     }
45930                   } else if (!isStrict) {
45931                     result[result.length] = value;
45932                   }
45933                 }
45934
45935                 return result;
45936               }
45937               /**
45938                * The base implementation of `baseForOwn` which iterates over `object`
45939                * properties returned by `keysFunc` and invokes `iteratee` for each property.
45940                * Iteratee functions may exit iteration early by explicitly returning `false`.
45941                *
45942                * @private
45943                * @param {Object} object The object to iterate over.
45944                * @param {Function} iteratee The function invoked per iteration.
45945                * @param {Function} keysFunc The function to get the keys of `object`.
45946                * @returns {Object} Returns `object`.
45947                */
45948
45949
45950               var baseFor = createBaseFor();
45951               /**
45952                * This function is like `baseFor` except that it iterates over properties
45953                * in the opposite order.
45954                *
45955                * @private
45956                * @param {Object} object The object to iterate over.
45957                * @param {Function} iteratee The function invoked per iteration.
45958                * @param {Function} keysFunc The function to get the keys of `object`.
45959                * @returns {Object} Returns `object`.
45960                */
45961
45962               var baseForRight = createBaseFor(true);
45963               /**
45964                * The base implementation of `_.forOwn` without support for iteratee shorthands.
45965                *
45966                * @private
45967                * @param {Object} object The object to iterate over.
45968                * @param {Function} iteratee The function invoked per iteration.
45969                * @returns {Object} Returns `object`.
45970                */
45971
45972               function baseForOwn(object, iteratee) {
45973                 return object && baseFor(object, iteratee, keys);
45974               }
45975               /**
45976                * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
45977                *
45978                * @private
45979                * @param {Object} object The object to iterate over.
45980                * @param {Function} iteratee The function invoked per iteration.
45981                * @returns {Object} Returns `object`.
45982                */
45983
45984
45985               function baseForOwnRight(object, iteratee) {
45986                 return object && baseForRight(object, iteratee, keys);
45987               }
45988               /**
45989                * The base implementation of `_.functions` which creates an array of
45990                * `object` function property names filtered from `props`.
45991                *
45992                * @private
45993                * @param {Object} object The object to inspect.
45994                * @param {Array} props The property names to filter.
45995                * @returns {Array} Returns the function names.
45996                */
45997
45998
45999               function baseFunctions(object, props) {
46000                 return arrayFilter(props, function (key) {
46001                   return isFunction(object[key]);
46002                 });
46003               }
46004               /**
46005                * The base implementation of `_.get` without support for default values.
46006                *
46007                * @private
46008                * @param {Object} object The object to query.
46009                * @param {Array|string} path The path of the property to get.
46010                * @returns {*} Returns the resolved value.
46011                */
46012
46013
46014               function baseGet(object, path) {
46015                 path = castPath(path, object);
46016                 var index = 0,
46017                     length = path.length;
46018
46019                 while (object != null && index < length) {
46020                   object = object[toKey(path[index++])];
46021                 }
46022
46023                 return index && index == length ? object : undefined$1;
46024               }
46025               /**
46026                * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
46027                * `keysFunc` and `symbolsFunc` to get the enumerable property names and
46028                * symbols of `object`.
46029                *
46030                * @private
46031                * @param {Object} object The object to query.
46032                * @param {Function} keysFunc The function to get the keys of `object`.
46033                * @param {Function} symbolsFunc The function to get the symbols of `object`.
46034                * @returns {Array} Returns the array of property names and symbols.
46035                */
46036
46037
46038               function baseGetAllKeys(object, keysFunc, symbolsFunc) {
46039                 var result = keysFunc(object);
46040                 return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
46041               }
46042               /**
46043                * The base implementation of `getTag` without fallbacks for buggy environments.
46044                *
46045                * @private
46046                * @param {*} value The value to query.
46047                * @returns {string} Returns the `toStringTag`.
46048                */
46049
46050
46051               function baseGetTag(value) {
46052                 if (value == null) {
46053                   return value === undefined$1 ? undefinedTag : nullTag;
46054                 }
46055
46056                 return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
46057               }
46058               /**
46059                * The base implementation of `_.gt` which doesn't coerce arguments.
46060                *
46061                * @private
46062                * @param {*} value The value to compare.
46063                * @param {*} other The other value to compare.
46064                * @returns {boolean} Returns `true` if `value` is greater than `other`,
46065                *  else `false`.
46066                */
46067
46068
46069               function baseGt(value, other) {
46070                 return value > other;
46071               }
46072               /**
46073                * The base implementation of `_.has` without support for deep paths.
46074                *
46075                * @private
46076                * @param {Object} [object] The object to query.
46077                * @param {Array|string} key The key to check.
46078                * @returns {boolean} Returns `true` if `key` exists, else `false`.
46079                */
46080
46081
46082               function baseHas(object, key) {
46083                 return object != null && hasOwnProperty.call(object, key);
46084               }
46085               /**
46086                * The base implementation of `_.hasIn` without support for deep paths.
46087                *
46088                * @private
46089                * @param {Object} [object] The object to query.
46090                * @param {Array|string} key The key to check.
46091                * @returns {boolean} Returns `true` if `key` exists, else `false`.
46092                */
46093
46094
46095               function baseHasIn(object, key) {
46096                 return object != null && key in Object(object);
46097               }
46098               /**
46099                * The base implementation of `_.inRange` which doesn't coerce arguments.
46100                *
46101                * @private
46102                * @param {number} number The number to check.
46103                * @param {number} start The start of the range.
46104                * @param {number} end The end of the range.
46105                * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
46106                */
46107
46108
46109               function baseInRange(number, start, end) {
46110                 return number >= nativeMin(start, end) && number < nativeMax(start, end);
46111               }
46112               /**
46113                * The base implementation of methods like `_.intersection`, without support
46114                * for iteratee shorthands, that accepts an array of arrays to inspect.
46115                *
46116                * @private
46117                * @param {Array} arrays The arrays to inspect.
46118                * @param {Function} [iteratee] The iteratee invoked per element.
46119                * @param {Function} [comparator] The comparator invoked per element.
46120                * @returns {Array} Returns the new array of shared values.
46121                */
46122
46123
46124               function baseIntersection(arrays, iteratee, comparator) {
46125                 var includes = comparator ? arrayIncludesWith : arrayIncludes,
46126                     length = arrays[0].length,
46127                     othLength = arrays.length,
46128                     othIndex = othLength,
46129                     caches = Array(othLength),
46130                     maxLength = Infinity,
46131                     result = [];
46132
46133                 while (othIndex--) {
46134                   var array = arrays[othIndex];
46135
46136                   if (othIndex && iteratee) {
46137                     array = arrayMap(array, baseUnary(iteratee));
46138                   }
46139
46140                   maxLength = nativeMin(array.length, maxLength);
46141                   caches[othIndex] = !comparator && (iteratee || length >= 120 && array.length >= 120) ? new SetCache(othIndex && array) : undefined$1;
46142                 }
46143
46144                 array = arrays[0];
46145                 var index = -1,
46146                     seen = caches[0];
46147
46148                 outer: while (++index < length && result.length < maxLength) {
46149                   var value = array[index],
46150                       computed = iteratee ? iteratee(value) : value;
46151                   value = comparator || value !== 0 ? value : 0;
46152
46153                   if (!(seen ? cacheHas(seen, computed) : includes(result, computed, comparator))) {
46154                     othIndex = othLength;
46155
46156                     while (--othIndex) {
46157                       var cache = caches[othIndex];
46158
46159                       if (!(cache ? cacheHas(cache, computed) : includes(arrays[othIndex], computed, comparator))) {
46160                         continue outer;
46161                       }
46162                     }
46163
46164                     if (seen) {
46165                       seen.push(computed);
46166                     }
46167
46168                     result.push(value);
46169                   }
46170                 }
46171
46172                 return result;
46173               }
46174               /**
46175                * The base implementation of `_.invert` and `_.invertBy` which inverts
46176                * `object` with values transformed by `iteratee` and set by `setter`.
46177                *
46178                * @private
46179                * @param {Object} object The object to iterate over.
46180                * @param {Function} setter The function to set `accumulator` values.
46181                * @param {Function} iteratee The iteratee to transform values.
46182                * @param {Object} accumulator The initial inverted object.
46183                * @returns {Function} Returns `accumulator`.
46184                */
46185
46186
46187               function baseInverter(object, setter, iteratee, accumulator) {
46188                 baseForOwn(object, function (value, key, object) {
46189                   setter(accumulator, iteratee(value), key, object);
46190                 });
46191                 return accumulator;
46192               }
46193               /**
46194                * The base implementation of `_.invoke` without support for individual
46195                * method arguments.
46196                *
46197                * @private
46198                * @param {Object} object The object to query.
46199                * @param {Array|string} path The path of the method to invoke.
46200                * @param {Array} args The arguments to invoke the method with.
46201                * @returns {*} Returns the result of the invoked method.
46202                */
46203
46204
46205               function baseInvoke(object, path, args) {
46206                 path = castPath(path, object);
46207                 object = parent(object, path);
46208                 var func = object == null ? object : object[toKey(last(path))];
46209                 return func == null ? undefined$1 : apply(func, object, args);
46210               }
46211               /**
46212                * The base implementation of `_.isArguments`.
46213                *
46214                * @private
46215                * @param {*} value The value to check.
46216                * @returns {boolean} Returns `true` if `value` is an `arguments` object,
46217                */
46218
46219
46220               function baseIsArguments(value) {
46221                 return isObjectLike(value) && baseGetTag(value) == argsTag;
46222               }
46223               /**
46224                * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
46225                *
46226                * @private
46227                * @param {*} value The value to check.
46228                * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
46229                */
46230
46231
46232               function baseIsArrayBuffer(value) {
46233                 return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
46234               }
46235               /**
46236                * The base implementation of `_.isDate` without Node.js optimizations.
46237                *
46238                * @private
46239                * @param {*} value The value to check.
46240                * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
46241                */
46242
46243
46244               function baseIsDate(value) {
46245                 return isObjectLike(value) && baseGetTag(value) == dateTag;
46246               }
46247               /**
46248                * The base implementation of `_.isEqual` which supports partial comparisons
46249                * and tracks traversed objects.
46250                *
46251                * @private
46252                * @param {*} value The value to compare.
46253                * @param {*} other The other value to compare.
46254                * @param {boolean} bitmask The bitmask flags.
46255                *  1 - Unordered comparison
46256                *  2 - Partial comparison
46257                * @param {Function} [customizer] The function to customize comparisons.
46258                * @param {Object} [stack] Tracks traversed `value` and `other` objects.
46259                * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
46260                */
46261
46262
46263               function baseIsEqual(value, other, bitmask, customizer, stack) {
46264                 if (value === other) {
46265                   return true;
46266                 }
46267
46268                 if (value == null || other == null || !isObjectLike(value) && !isObjectLike(other)) {
46269                   return value !== value && other !== other;
46270                 }
46271
46272                 return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
46273               }
46274               /**
46275                * A specialized version of `baseIsEqual` for arrays and objects which performs
46276                * deep comparisons and tracks traversed objects enabling objects with circular
46277                * references to be compared.
46278                *
46279                * @private
46280                * @param {Object} object The object to compare.
46281                * @param {Object} other The other object to compare.
46282                * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
46283                * @param {Function} customizer The function to customize comparisons.
46284                * @param {Function} equalFunc The function to determine equivalents of values.
46285                * @param {Object} [stack] Tracks traversed `object` and `other` objects.
46286                * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
46287                */
46288
46289
46290               function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
46291                 var objIsArr = isArray(object),
46292                     othIsArr = isArray(other),
46293                     objTag = objIsArr ? arrayTag : getTag(object),
46294                     othTag = othIsArr ? arrayTag : getTag(other);
46295                 objTag = objTag == argsTag ? objectTag : objTag;
46296                 othTag = othTag == argsTag ? objectTag : othTag;
46297                 var objIsObj = objTag == objectTag,
46298                     othIsObj = othTag == objectTag,
46299                     isSameTag = objTag == othTag;
46300
46301                 if (isSameTag && isBuffer(object)) {
46302                   if (!isBuffer(other)) {
46303                     return false;
46304                   }
46305
46306                   objIsArr = true;
46307                   objIsObj = false;
46308                 }
46309
46310                 if (isSameTag && !objIsObj) {
46311                   stack || (stack = new Stack());
46312                   return objIsArr || isTypedArray(object) ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
46313                 }
46314
46315                 if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
46316                   var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
46317                       othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
46318
46319                   if (objIsWrapped || othIsWrapped) {
46320                     var objUnwrapped = objIsWrapped ? object.value() : object,
46321                         othUnwrapped = othIsWrapped ? other.value() : other;
46322                     stack || (stack = new Stack());
46323                     return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
46324                   }
46325                 }
46326
46327                 if (!isSameTag) {
46328                   return false;
46329                 }
46330
46331                 stack || (stack = new Stack());
46332                 return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
46333               }
46334               /**
46335                * The base implementation of `_.isMap` without Node.js optimizations.
46336                *
46337                * @private
46338                * @param {*} value The value to check.
46339                * @returns {boolean} Returns `true` if `value` is a map, else `false`.
46340                */
46341
46342
46343               function baseIsMap(value) {
46344                 return isObjectLike(value) && getTag(value) == mapTag;
46345               }
46346               /**
46347                * The base implementation of `_.isMatch` without support for iteratee shorthands.
46348                *
46349                * @private
46350                * @param {Object} object The object to inspect.
46351                * @param {Object} source The object of property values to match.
46352                * @param {Array} matchData The property names, values, and compare flags to match.
46353                * @param {Function} [customizer] The function to customize comparisons.
46354                * @returns {boolean} Returns `true` if `object` is a match, else `false`.
46355                */
46356
46357
46358               function baseIsMatch(object, source, matchData, customizer) {
46359                 var index = matchData.length,
46360                     length = index,
46361                     noCustomizer = !customizer;
46362
46363                 if (object == null) {
46364                   return !length;
46365                 }
46366
46367                 object = Object(object);
46368
46369                 while (index--) {
46370                   var data = matchData[index];
46371
46372                   if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) {
46373                     return false;
46374                   }
46375                 }
46376
46377                 while (++index < length) {
46378                   data = matchData[index];
46379                   var key = data[0],
46380                       objValue = object[key],
46381                       srcValue = data[1];
46382
46383                   if (noCustomizer && data[2]) {
46384                     if (objValue === undefined$1 && !(key in object)) {
46385                       return false;
46386                     }
46387                   } else {
46388                     var stack = new Stack();
46389
46390                     if (customizer) {
46391                       var result = customizer(objValue, srcValue, key, object, source, stack);
46392                     }
46393
46394                     if (!(result === undefined$1 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) : result)) {
46395                       return false;
46396                     }
46397                   }
46398                 }
46399
46400                 return true;
46401               }
46402               /**
46403                * The base implementation of `_.isNative` without bad shim checks.
46404                *
46405                * @private
46406                * @param {*} value The value to check.
46407                * @returns {boolean} Returns `true` if `value` is a native function,
46408                *  else `false`.
46409                */
46410
46411
46412               function baseIsNative(value) {
46413                 if (!isObject(value) || isMasked(value)) {
46414                   return false;
46415                 }
46416
46417                 var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
46418                 return pattern.test(toSource(value));
46419               }
46420               /**
46421                * The base implementation of `_.isRegExp` without Node.js optimizations.
46422                *
46423                * @private
46424                * @param {*} value The value to check.
46425                * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
46426                */
46427
46428
46429               function baseIsRegExp(value) {
46430                 return isObjectLike(value) && baseGetTag(value) == regexpTag;
46431               }
46432               /**
46433                * The base implementation of `_.isSet` without Node.js optimizations.
46434                *
46435                * @private
46436                * @param {*} value The value to check.
46437                * @returns {boolean} Returns `true` if `value` is a set, else `false`.
46438                */
46439
46440
46441               function baseIsSet(value) {
46442                 return isObjectLike(value) && getTag(value) == setTag;
46443               }
46444               /**
46445                * The base implementation of `_.isTypedArray` without Node.js optimizations.
46446                *
46447                * @private
46448                * @param {*} value The value to check.
46449                * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
46450                */
46451
46452
46453               function baseIsTypedArray(value) {
46454                 return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
46455               }
46456               /**
46457                * The base implementation of `_.iteratee`.
46458                *
46459                * @private
46460                * @param {*} [value=_.identity] The value to convert to an iteratee.
46461                * @returns {Function} Returns the iteratee.
46462                */
46463
46464
46465               function baseIteratee(value) {
46466                 // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
46467                 // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
46468                 if (typeof value == 'function') {
46469                   return value;
46470                 }
46471
46472                 if (value == null) {
46473                   return identity;
46474                 }
46475
46476                 if (_typeof(value) == 'object') {
46477                   return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value);
46478                 }
46479
46480                 return property(value);
46481               }
46482               /**
46483                * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
46484                *
46485                * @private
46486                * @param {Object} object The object to query.
46487                * @returns {Array} Returns the array of property names.
46488                */
46489
46490
46491               function baseKeys(object) {
46492                 if (!isPrototype(object)) {
46493                   return nativeKeys(object);
46494                 }
46495
46496                 var result = [];
46497
46498                 for (var key in Object(object)) {
46499                   if (hasOwnProperty.call(object, key) && key != 'constructor') {
46500                     result.push(key);
46501                   }
46502                 }
46503
46504                 return result;
46505               }
46506               /**
46507                * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
46508                *
46509                * @private
46510                * @param {Object} object The object to query.
46511                * @returns {Array} Returns the array of property names.
46512                */
46513
46514
46515               function baseKeysIn(object) {
46516                 if (!isObject(object)) {
46517                   return nativeKeysIn(object);
46518                 }
46519
46520                 var isProto = isPrototype(object),
46521                     result = [];
46522
46523                 for (var key in object) {
46524                   if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
46525                     result.push(key);
46526                   }
46527                 }
46528
46529                 return result;
46530               }
46531               /**
46532                * The base implementation of `_.lt` which doesn't coerce arguments.
46533                *
46534                * @private
46535                * @param {*} value The value to compare.
46536                * @param {*} other The other value to compare.
46537                * @returns {boolean} Returns `true` if `value` is less than `other`,
46538                *  else `false`.
46539                */
46540
46541
46542               function baseLt(value, other) {
46543                 return value < other;
46544               }
46545               /**
46546                * The base implementation of `_.map` without support for iteratee shorthands.
46547                *
46548                * @private
46549                * @param {Array|Object} collection The collection to iterate over.
46550                * @param {Function} iteratee The function invoked per iteration.
46551                * @returns {Array} Returns the new mapped array.
46552                */
46553
46554
46555               function baseMap(collection, iteratee) {
46556                 var index = -1,
46557                     result = isArrayLike(collection) ? Array(collection.length) : [];
46558                 baseEach(collection, function (value, key, collection) {
46559                   result[++index] = iteratee(value, key, collection);
46560                 });
46561                 return result;
46562               }
46563               /**
46564                * The base implementation of `_.matches` which doesn't clone `source`.
46565                *
46566                * @private
46567                * @param {Object} source The object of property values to match.
46568                * @returns {Function} Returns the new spec function.
46569                */
46570
46571
46572               function baseMatches(source) {
46573                 var matchData = getMatchData(source);
46574
46575                 if (matchData.length == 1 && matchData[0][2]) {
46576                   return matchesStrictComparable(matchData[0][0], matchData[0][1]);
46577                 }
46578
46579                 return function (object) {
46580                   return object === source || baseIsMatch(object, source, matchData);
46581                 };
46582               }
46583               /**
46584                * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
46585                *
46586                * @private
46587                * @param {string} path The path of the property to get.
46588                * @param {*} srcValue The value to match.
46589                * @returns {Function} Returns the new spec function.
46590                */
46591
46592
46593               function baseMatchesProperty(path, srcValue) {
46594                 if (isKey(path) && isStrictComparable(srcValue)) {
46595                   return matchesStrictComparable(toKey(path), srcValue);
46596                 }
46597
46598                 return function (object) {
46599                   var objValue = get(object, path);
46600                   return objValue === undefined$1 && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
46601                 };
46602               }
46603               /**
46604                * The base implementation of `_.merge` without support for multiple sources.
46605                *
46606                * @private
46607                * @param {Object} object The destination object.
46608                * @param {Object} source The source object.
46609                * @param {number} srcIndex The index of `source`.
46610                * @param {Function} [customizer] The function to customize merged values.
46611                * @param {Object} [stack] Tracks traversed source values and their merged
46612                *  counterparts.
46613                */
46614
46615
46616               function baseMerge(object, source, srcIndex, customizer, stack) {
46617                 if (object === source) {
46618                   return;
46619                 }
46620
46621                 baseFor(source, function (srcValue, key) {
46622                   stack || (stack = new Stack());
46623
46624                   if (isObject(srcValue)) {
46625                     baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
46626                   } else {
46627                     var newValue = customizer ? customizer(safeGet(object, key), srcValue, key + '', object, source, stack) : undefined$1;
46628
46629                     if (newValue === undefined$1) {
46630                       newValue = srcValue;
46631                     }
46632
46633                     assignMergeValue(object, key, newValue);
46634                   }
46635                 }, keysIn);
46636               }
46637               /**
46638                * A specialized version of `baseMerge` for arrays and objects which performs
46639                * deep merges and tracks traversed objects enabling objects with circular
46640                * references to be merged.
46641                *
46642                * @private
46643                * @param {Object} object The destination object.
46644                * @param {Object} source The source object.
46645                * @param {string} key The key of the value to merge.
46646                * @param {number} srcIndex The index of `source`.
46647                * @param {Function} mergeFunc The function to merge values.
46648                * @param {Function} [customizer] The function to customize assigned values.
46649                * @param {Object} [stack] Tracks traversed source values and their merged
46650                *  counterparts.
46651                */
46652
46653
46654               function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
46655                 var objValue = safeGet(object, key),
46656                     srcValue = safeGet(source, key),
46657                     stacked = stack.get(srcValue);
46658
46659                 if (stacked) {
46660                   assignMergeValue(object, key, stacked);
46661                   return;
46662                 }
46663
46664                 var newValue = customizer ? customizer(objValue, srcValue, key + '', object, source, stack) : undefined$1;
46665                 var isCommon = newValue === undefined$1;
46666
46667                 if (isCommon) {
46668                   var isArr = isArray(srcValue),
46669                       isBuff = !isArr && isBuffer(srcValue),
46670                       isTyped = !isArr && !isBuff && isTypedArray(srcValue);
46671                   newValue = srcValue;
46672
46673                   if (isArr || isBuff || isTyped) {
46674                     if (isArray(objValue)) {
46675                       newValue = objValue;
46676                     } else if (isArrayLikeObject(objValue)) {
46677                       newValue = copyArray(objValue);
46678                     } else if (isBuff) {
46679                       isCommon = false;
46680                       newValue = cloneBuffer(srcValue, true);
46681                     } else if (isTyped) {
46682                       isCommon = false;
46683                       newValue = cloneTypedArray(srcValue, true);
46684                     } else {
46685                       newValue = [];
46686                     }
46687                   } else if (isPlainObject(srcValue) || isArguments(srcValue)) {
46688                     newValue = objValue;
46689
46690                     if (isArguments(objValue)) {
46691                       newValue = toPlainObject(objValue);
46692                     } else if (!isObject(objValue) || isFunction(objValue)) {
46693                       newValue = initCloneObject(srcValue);
46694                     }
46695                   } else {
46696                     isCommon = false;
46697                   }
46698                 }
46699
46700                 if (isCommon) {
46701                   // Recursively merge objects and arrays (susceptible to call stack limits).
46702                   stack.set(srcValue, newValue);
46703                   mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
46704                   stack['delete'](srcValue);
46705                 }
46706
46707                 assignMergeValue(object, key, newValue);
46708               }
46709               /**
46710                * The base implementation of `_.nth` which doesn't coerce arguments.
46711                *
46712                * @private
46713                * @param {Array} array The array to query.
46714                * @param {number} n The index of the element to return.
46715                * @returns {*} Returns the nth element of `array`.
46716                */
46717
46718
46719               function baseNth(array, n) {
46720                 var length = array.length;
46721
46722                 if (!length) {
46723                   return;
46724                 }
46725
46726                 n += n < 0 ? length : 0;
46727                 return isIndex(n, length) ? array[n] : undefined$1;
46728               }
46729               /**
46730                * The base implementation of `_.orderBy` without param guards.
46731                *
46732                * @private
46733                * @param {Array|Object} collection The collection to iterate over.
46734                * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
46735                * @param {string[]} orders The sort orders of `iteratees`.
46736                * @returns {Array} Returns the new sorted array.
46737                */
46738
46739
46740               function baseOrderBy(collection, iteratees, orders) {
46741                 if (iteratees.length) {
46742                   iteratees = arrayMap(iteratees, function (iteratee) {
46743                     if (isArray(iteratee)) {
46744                       return function (value) {
46745                         return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
46746                       };
46747                     }
46748
46749                     return iteratee;
46750                   });
46751                 } else {
46752                   iteratees = [identity];
46753                 }
46754
46755                 var index = -1;
46756                 iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
46757                 var result = baseMap(collection, function (value, key, collection) {
46758                   var criteria = arrayMap(iteratees, function (iteratee) {
46759                     return iteratee(value);
46760                   });
46761                   return {
46762                     'criteria': criteria,
46763                     'index': ++index,
46764                     'value': value
46765                   };
46766                 });
46767                 return baseSortBy(result, function (object, other) {
46768                   return compareMultiple(object, other, orders);
46769                 });
46770               }
46771               /**
46772                * The base implementation of `_.pick` without support for individual
46773                * property identifiers.
46774                *
46775                * @private
46776                * @param {Object} object The source object.
46777                * @param {string[]} paths The property paths to pick.
46778                * @returns {Object} Returns the new object.
46779                */
46780
46781
46782               function basePick(object, paths) {
46783                 return basePickBy(object, paths, function (value, path) {
46784                   return hasIn(object, path);
46785                 });
46786               }
46787               /**
46788                * The base implementation of  `_.pickBy` without support for iteratee shorthands.
46789                *
46790                * @private
46791                * @param {Object} object The source object.
46792                * @param {string[]} paths The property paths to pick.
46793                * @param {Function} predicate The function invoked per property.
46794                * @returns {Object} Returns the new object.
46795                */
46796
46797
46798               function basePickBy(object, paths, predicate) {
46799                 var index = -1,
46800                     length = paths.length,
46801                     result = {};
46802
46803                 while (++index < length) {
46804                   var path = paths[index],
46805                       value = baseGet(object, path);
46806
46807                   if (predicate(value, path)) {
46808                     baseSet(result, castPath(path, object), value);
46809                   }
46810                 }
46811
46812                 return result;
46813               }
46814               /**
46815                * A specialized version of `baseProperty` which supports deep paths.
46816                *
46817                * @private
46818                * @param {Array|string} path The path of the property to get.
46819                * @returns {Function} Returns the new accessor function.
46820                */
46821
46822
46823               function basePropertyDeep(path) {
46824                 return function (object) {
46825                   return baseGet(object, path);
46826                 };
46827               }
46828               /**
46829                * The base implementation of `_.pullAllBy` without support for iteratee
46830                * shorthands.
46831                *
46832                * @private
46833                * @param {Array} array The array to modify.
46834                * @param {Array} values The values to remove.
46835                * @param {Function} [iteratee] The iteratee invoked per element.
46836                * @param {Function} [comparator] The comparator invoked per element.
46837                * @returns {Array} Returns `array`.
46838                */
46839
46840
46841               function basePullAll(array, values, iteratee, comparator) {
46842                 var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
46843                     index = -1,
46844                     length = values.length,
46845                     seen = array;
46846
46847                 if (array === values) {
46848                   values = copyArray(values);
46849                 }
46850
46851                 if (iteratee) {
46852                   seen = arrayMap(array, baseUnary(iteratee));
46853                 }
46854
46855                 while (++index < length) {
46856                   var fromIndex = 0,
46857                       value = values[index],
46858                       computed = iteratee ? iteratee(value) : value;
46859
46860                   while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
46861                     if (seen !== array) {
46862                       splice.call(seen, fromIndex, 1);
46863                     }
46864
46865                     splice.call(array, fromIndex, 1);
46866                   }
46867                 }
46868
46869                 return array;
46870               }
46871               /**
46872                * The base implementation of `_.pullAt` without support for individual
46873                * indexes or capturing the removed elements.
46874                *
46875                * @private
46876                * @param {Array} array The array to modify.
46877                * @param {number[]} indexes The indexes of elements to remove.
46878                * @returns {Array} Returns `array`.
46879                */
46880
46881
46882               function basePullAt(array, indexes) {
46883                 var length = array ? indexes.length : 0,
46884                     lastIndex = length - 1;
46885
46886                 while (length--) {
46887                   var index = indexes[length];
46888
46889                   if (length == lastIndex || index !== previous) {
46890                     var previous = index;
46891
46892                     if (isIndex(index)) {
46893                       splice.call(array, index, 1);
46894                     } else {
46895                       baseUnset(array, index);
46896                     }
46897                   }
46898                 }
46899
46900                 return array;
46901               }
46902               /**
46903                * The base implementation of `_.random` without support for returning
46904                * floating-point numbers.
46905                *
46906                * @private
46907                * @param {number} lower The lower bound.
46908                * @param {number} upper The upper bound.
46909                * @returns {number} Returns the random number.
46910                */
46911
46912
46913               function baseRandom(lower, upper) {
46914                 return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
46915               }
46916               /**
46917                * The base implementation of `_.range` and `_.rangeRight` which doesn't
46918                * coerce arguments.
46919                *
46920                * @private
46921                * @param {number} start The start of the range.
46922                * @param {number} end The end of the range.
46923                * @param {number} step The value to increment or decrement by.
46924                * @param {boolean} [fromRight] Specify iterating from right to left.
46925                * @returns {Array} Returns the range of numbers.
46926                */
46927
46928
46929               function baseRange(start, end, step, fromRight) {
46930                 var index = -1,
46931                     length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
46932                     result = Array(length);
46933
46934                 while (length--) {
46935                   result[fromRight ? length : ++index] = start;
46936                   start += step;
46937                 }
46938
46939                 return result;
46940               }
46941               /**
46942                * The base implementation of `_.repeat` which doesn't coerce arguments.
46943                *
46944                * @private
46945                * @param {string} string The string to repeat.
46946                * @param {number} n The number of times to repeat the string.
46947                * @returns {string} Returns the repeated string.
46948                */
46949
46950
46951               function baseRepeat(string, n) {
46952                 var result = '';
46953
46954                 if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
46955                   return result;
46956                 } // Leverage the exponentiation by squaring algorithm for a faster repeat.
46957                 // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
46958
46959
46960                 do {
46961                   if (n % 2) {
46962                     result += string;
46963                   }
46964
46965                   n = nativeFloor(n / 2);
46966
46967                   if (n) {
46968                     string += string;
46969                   }
46970                 } while (n);
46971
46972                 return result;
46973               }
46974               /**
46975                * The base implementation of `_.rest` which doesn't validate or coerce arguments.
46976                *
46977                * @private
46978                * @param {Function} func The function to apply a rest parameter to.
46979                * @param {number} [start=func.length-1] The start position of the rest parameter.
46980                * @returns {Function} Returns the new function.
46981                */
46982
46983
46984               function baseRest(func, start) {
46985                 return setToString(overRest(func, start, identity), func + '');
46986               }
46987               /**
46988                * The base implementation of `_.sample`.
46989                *
46990                * @private
46991                * @param {Array|Object} collection The collection to sample.
46992                * @returns {*} Returns the random element.
46993                */
46994
46995
46996               function baseSample(collection) {
46997                 return arraySample(values(collection));
46998               }
46999               /**
47000                * The base implementation of `_.sampleSize` without param guards.
47001                *
47002                * @private
47003                * @param {Array|Object} collection The collection to sample.
47004                * @param {number} n The number of elements to sample.
47005                * @returns {Array} Returns the random elements.
47006                */
47007
47008
47009               function baseSampleSize(collection, n) {
47010                 var array = values(collection);
47011                 return shuffleSelf(array, baseClamp(n, 0, array.length));
47012               }
47013               /**
47014                * The base implementation of `_.set`.
47015                *
47016                * @private
47017                * @param {Object} object The object to modify.
47018                * @param {Array|string} path The path of the property to set.
47019                * @param {*} value The value to set.
47020                * @param {Function} [customizer] The function to customize path creation.
47021                * @returns {Object} Returns `object`.
47022                */
47023
47024
47025               function baseSet(object, path, value, customizer) {
47026                 if (!isObject(object)) {
47027                   return object;
47028                 }
47029
47030                 path = castPath(path, object);
47031                 var index = -1,
47032                     length = path.length,
47033                     lastIndex = length - 1,
47034                     nested = object;
47035
47036                 while (nested != null && ++index < length) {
47037                   var key = toKey(path[index]),
47038                       newValue = value;
47039
47040                   if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
47041                     return object;
47042                   }
47043
47044                   if (index != lastIndex) {
47045                     var objValue = nested[key];
47046                     newValue = customizer ? customizer(objValue, key, nested) : undefined$1;
47047
47048                     if (newValue === undefined$1) {
47049                       newValue = isObject(objValue) ? objValue : isIndex(path[index + 1]) ? [] : {};
47050                     }
47051                   }
47052
47053                   assignValue(nested, key, newValue);
47054                   nested = nested[key];
47055                 }
47056
47057                 return object;
47058               }
47059               /**
47060                * The base implementation of `setData` without support for hot loop shorting.
47061                *
47062                * @private
47063                * @param {Function} func The function to associate metadata with.
47064                * @param {*} data The metadata.
47065                * @returns {Function} Returns `func`.
47066                */
47067
47068
47069               var baseSetData = !metaMap ? identity : function (func, data) {
47070                 metaMap.set(func, data);
47071                 return func;
47072               };
47073               /**
47074                * The base implementation of `setToString` without support for hot loop shorting.
47075                *
47076                * @private
47077                * @param {Function} func The function to modify.
47078                * @param {Function} string The `toString` result.
47079                * @returns {Function} Returns `func`.
47080                */
47081
47082               var baseSetToString = !defineProperty ? identity : function (func, string) {
47083                 return defineProperty(func, 'toString', {
47084                   'configurable': true,
47085                   'enumerable': false,
47086                   'value': constant(string),
47087                   'writable': true
47088                 });
47089               };
47090               /**
47091                * The base implementation of `_.shuffle`.
47092                *
47093                * @private
47094                * @param {Array|Object} collection The collection to shuffle.
47095                * @returns {Array} Returns the new shuffled array.
47096                */
47097
47098               function baseShuffle(collection) {
47099                 return shuffleSelf(values(collection));
47100               }
47101               /**
47102                * The base implementation of `_.slice` without an iteratee call guard.
47103                *
47104                * @private
47105                * @param {Array} array The array to slice.
47106                * @param {number} [start=0] The start position.
47107                * @param {number} [end=array.length] The end position.
47108                * @returns {Array} Returns the slice of `array`.
47109                */
47110
47111
47112               function baseSlice(array, start, end) {
47113                 var index = -1,
47114                     length = array.length;
47115
47116                 if (start < 0) {
47117                   start = -start > length ? 0 : length + start;
47118                 }
47119
47120                 end = end > length ? length : end;
47121
47122                 if (end < 0) {
47123                   end += length;
47124                 }
47125
47126                 length = start > end ? 0 : end - start >>> 0;
47127                 start >>>= 0;
47128                 var result = Array(length);
47129
47130                 while (++index < length) {
47131                   result[index] = array[index + start];
47132                 }
47133
47134                 return result;
47135               }
47136               /**
47137                * The base implementation of `_.some` without support for iteratee shorthands.
47138                *
47139                * @private
47140                * @param {Array|Object} collection The collection to iterate over.
47141                * @param {Function} predicate The function invoked per iteration.
47142                * @returns {boolean} Returns `true` if any element passes the predicate check,
47143                *  else `false`.
47144                */
47145
47146
47147               function baseSome(collection, predicate) {
47148                 var result;
47149                 baseEach(collection, function (value, index, collection) {
47150                   result = predicate(value, index, collection);
47151                   return !result;
47152                 });
47153                 return !!result;
47154               }
47155               /**
47156                * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
47157                * performs a binary search of `array` to determine the index at which `value`
47158                * should be inserted into `array` in order to maintain its sort order.
47159                *
47160                * @private
47161                * @param {Array} array The sorted array to inspect.
47162                * @param {*} value The value to evaluate.
47163                * @param {boolean} [retHighest] Specify returning the highest qualified index.
47164                * @returns {number} Returns the index at which `value` should be inserted
47165                *  into `array`.
47166                */
47167
47168
47169               function baseSortedIndex(array, value, retHighest) {
47170                 var low = 0,
47171                     high = array == null ? low : array.length;
47172
47173                 if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
47174                   while (low < high) {
47175                     var mid = low + high >>> 1,
47176                         computed = array[mid];
47177
47178                     if (computed !== null && !isSymbol(computed) && (retHighest ? computed <= value : computed < value)) {
47179                       low = mid + 1;
47180                     } else {
47181                       high = mid;
47182                     }
47183                   }
47184
47185                   return high;
47186                 }
47187
47188                 return baseSortedIndexBy(array, value, identity, retHighest);
47189               }
47190               /**
47191                * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
47192                * which invokes `iteratee` for `value` and each element of `array` to compute
47193                * their sort ranking. The iteratee is invoked with one argument; (value).
47194                *
47195                * @private
47196                * @param {Array} array The sorted array to inspect.
47197                * @param {*} value The value to evaluate.
47198                * @param {Function} iteratee The iteratee invoked per element.
47199                * @param {boolean} [retHighest] Specify returning the highest qualified index.
47200                * @returns {number} Returns the index at which `value` should be inserted
47201                *  into `array`.
47202                */
47203
47204
47205               function baseSortedIndexBy(array, value, iteratee, retHighest) {
47206                 var low = 0,
47207                     high = array == null ? 0 : array.length;
47208
47209                 if (high === 0) {
47210                   return 0;
47211                 }
47212
47213                 value = iteratee(value);
47214                 var valIsNaN = value !== value,
47215                     valIsNull = value === null,
47216                     valIsSymbol = isSymbol(value),
47217                     valIsUndefined = value === undefined$1;
47218
47219                 while (low < high) {
47220                   var mid = nativeFloor((low + high) / 2),
47221                       computed = iteratee(array[mid]),
47222                       othIsDefined = computed !== undefined$1,
47223                       othIsNull = computed === null,
47224                       othIsReflexive = computed === computed,
47225                       othIsSymbol = isSymbol(computed);
47226
47227                   if (valIsNaN) {
47228                     var setLow = retHighest || othIsReflexive;
47229                   } else if (valIsUndefined) {
47230                     setLow = othIsReflexive && (retHighest || othIsDefined);
47231                   } else if (valIsNull) {
47232                     setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
47233                   } else if (valIsSymbol) {
47234                     setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
47235                   } else if (othIsNull || othIsSymbol) {
47236                     setLow = false;
47237                   } else {
47238                     setLow = retHighest ? computed <= value : computed < value;
47239                   }
47240
47241                   if (setLow) {
47242                     low = mid + 1;
47243                   } else {
47244                     high = mid;
47245                   }
47246                 }
47247
47248                 return nativeMin(high, MAX_ARRAY_INDEX);
47249               }
47250               /**
47251                * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
47252                * support for iteratee shorthands.
47253                *
47254                * @private
47255                * @param {Array} array The array to inspect.
47256                * @param {Function} [iteratee] The iteratee invoked per element.
47257                * @returns {Array} Returns the new duplicate free array.
47258                */
47259
47260
47261               function baseSortedUniq(array, iteratee) {
47262                 var index = -1,
47263                     length = array.length,
47264                     resIndex = 0,
47265                     result = [];
47266
47267                 while (++index < length) {
47268                   var value = array[index],
47269                       computed = iteratee ? iteratee(value) : value;
47270
47271                   if (!index || !eq(computed, seen)) {
47272                     var seen = computed;
47273                     result[resIndex++] = value === 0 ? 0 : value;
47274                   }
47275                 }
47276
47277                 return result;
47278               }
47279               /**
47280                * The base implementation of `_.toNumber` which doesn't ensure correct
47281                * conversions of binary, hexadecimal, or octal string values.
47282                *
47283                * @private
47284                * @param {*} value The value to process.
47285                * @returns {number} Returns the number.
47286                */
47287
47288
47289               function baseToNumber(value) {
47290                 if (typeof value == 'number') {
47291                   return value;
47292                 }
47293
47294                 if (isSymbol(value)) {
47295                   return NAN;
47296                 }
47297
47298                 return +value;
47299               }
47300               /**
47301                * The base implementation of `_.toString` which doesn't convert nullish
47302                * values to empty strings.
47303                *
47304                * @private
47305                * @param {*} value The value to process.
47306                * @returns {string} Returns the string.
47307                */
47308
47309
47310               function baseToString(value) {
47311                 // Exit early for strings to avoid a performance hit in some environments.
47312                 if (typeof value == 'string') {
47313                   return value;
47314                 }
47315
47316                 if (isArray(value)) {
47317                   // Recursively convert values (susceptible to call stack limits).
47318                   return arrayMap(value, baseToString) + '';
47319                 }
47320
47321                 if (isSymbol(value)) {
47322                   return symbolToString ? symbolToString.call(value) : '';
47323                 }
47324
47325                 var result = value + '';
47326                 return result == '0' && 1 / value == -INFINITY ? '-0' : result;
47327               }
47328               /**
47329                * The base implementation of `_.uniqBy` without support for iteratee shorthands.
47330                *
47331                * @private
47332                * @param {Array} array The array to inspect.
47333                * @param {Function} [iteratee] The iteratee invoked per element.
47334                * @param {Function} [comparator] The comparator invoked per element.
47335                * @returns {Array} Returns the new duplicate free array.
47336                */
47337
47338
47339               function baseUniq(array, iteratee, comparator) {
47340                 var index = -1,
47341                     includes = arrayIncludes,
47342                     length = array.length,
47343                     isCommon = true,
47344                     result = [],
47345                     seen = result;
47346
47347                 if (comparator) {
47348                   isCommon = false;
47349                   includes = arrayIncludesWith;
47350                 } else if (length >= LARGE_ARRAY_SIZE) {
47351                   var set = iteratee ? null : createSet(array);
47352
47353                   if (set) {
47354                     return setToArray(set);
47355                   }
47356
47357                   isCommon = false;
47358                   includes = cacheHas;
47359                   seen = new SetCache();
47360                 } else {
47361                   seen = iteratee ? [] : result;
47362                 }
47363
47364                 outer: while (++index < length) {
47365                   var value = array[index],
47366                       computed = iteratee ? iteratee(value) : value;
47367                   value = comparator || value !== 0 ? value : 0;
47368
47369                   if (isCommon && computed === computed) {
47370                     var seenIndex = seen.length;
47371
47372                     while (seenIndex--) {
47373                       if (seen[seenIndex] === computed) {
47374                         continue outer;
47375                       }
47376                     }
47377
47378                     if (iteratee) {
47379                       seen.push(computed);
47380                     }
47381
47382                     result.push(value);
47383                   } else if (!includes(seen, computed, comparator)) {
47384                     if (seen !== result) {
47385                       seen.push(computed);
47386                     }
47387
47388                     result.push(value);
47389                   }
47390                 }
47391
47392                 return result;
47393               }
47394               /**
47395                * The base implementation of `_.unset`.
47396                *
47397                * @private
47398                * @param {Object} object The object to modify.
47399                * @param {Array|string} path The property path to unset.
47400                * @returns {boolean} Returns `true` if the property is deleted, else `false`.
47401                */
47402
47403
47404               function baseUnset(object, path) {
47405                 path = castPath(path, object);
47406                 object = parent(object, path);
47407                 return object == null || delete object[toKey(last(path))];
47408               }
47409               /**
47410                * The base implementation of `_.update`.
47411                *
47412                * @private
47413                * @param {Object} object The object to modify.
47414                * @param {Array|string} path The path of the property to update.
47415                * @param {Function} updater The function to produce the updated value.
47416                * @param {Function} [customizer] The function to customize path creation.
47417                * @returns {Object} Returns `object`.
47418                */
47419
47420
47421               function baseUpdate(object, path, updater, customizer) {
47422                 return baseSet(object, path, updater(baseGet(object, path)), customizer);
47423               }
47424               /**
47425                * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
47426                * without support for iteratee shorthands.
47427                *
47428                * @private
47429                * @param {Array} array The array to query.
47430                * @param {Function} predicate The function invoked per iteration.
47431                * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
47432                * @param {boolean} [fromRight] Specify iterating from right to left.
47433                * @returns {Array} Returns the slice of `array`.
47434                */
47435
47436
47437               function baseWhile(array, predicate, isDrop, fromRight) {
47438                 var length = array.length,
47439                     index = fromRight ? length : -1;
47440
47441                 while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}
47442
47443                 return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index);
47444               }
47445               /**
47446                * The base implementation of `wrapperValue` which returns the result of
47447                * performing a sequence of actions on the unwrapped `value`, where each
47448                * successive action is supplied the return value of the previous.
47449                *
47450                * @private
47451                * @param {*} value The unwrapped value.
47452                * @param {Array} actions Actions to perform to resolve the unwrapped value.
47453                * @returns {*} Returns the resolved value.
47454                */
47455
47456
47457               function baseWrapperValue(value, actions) {
47458                 var result = value;
47459
47460                 if (result instanceof LazyWrapper) {
47461                   result = result.value();
47462                 }
47463
47464                 return arrayReduce(actions, function (result, action) {
47465                   return action.func.apply(action.thisArg, arrayPush([result], action.args));
47466                 }, result);
47467               }
47468               /**
47469                * The base implementation of methods like `_.xor`, without support for
47470                * iteratee shorthands, that accepts an array of arrays to inspect.
47471                *
47472                * @private
47473                * @param {Array} arrays The arrays to inspect.
47474                * @param {Function} [iteratee] The iteratee invoked per element.
47475                * @param {Function} [comparator] The comparator invoked per element.
47476                * @returns {Array} Returns the new array of values.
47477                */
47478
47479
47480               function baseXor(arrays, iteratee, comparator) {
47481                 var length = arrays.length;
47482
47483                 if (length < 2) {
47484                   return length ? baseUniq(arrays[0]) : [];
47485                 }
47486
47487                 var index = -1,
47488                     result = Array(length);
47489
47490                 while (++index < length) {
47491                   var array = arrays[index],
47492                       othIndex = -1;
47493
47494                   while (++othIndex < length) {
47495                     if (othIndex != index) {
47496                       result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
47497                     }
47498                   }
47499                 }
47500
47501                 return baseUniq(baseFlatten(result, 1), iteratee, comparator);
47502               }
47503               /**
47504                * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
47505                *
47506                * @private
47507                * @param {Array} props The property identifiers.
47508                * @param {Array} values The property values.
47509                * @param {Function} assignFunc The function to assign values.
47510                * @returns {Object} Returns the new object.
47511                */
47512
47513
47514               function baseZipObject(props, values, assignFunc) {
47515                 var index = -1,
47516                     length = props.length,
47517                     valsLength = values.length,
47518                     result = {};
47519
47520                 while (++index < length) {
47521                   var value = index < valsLength ? values[index] : undefined$1;
47522                   assignFunc(result, props[index], value);
47523                 }
47524
47525                 return result;
47526               }
47527               /**
47528                * Casts `value` to an empty array if it's not an array like object.
47529                *
47530                * @private
47531                * @param {*} value The value to inspect.
47532                * @returns {Array|Object} Returns the cast array-like object.
47533                */
47534
47535
47536               function castArrayLikeObject(value) {
47537                 return isArrayLikeObject(value) ? value : [];
47538               }
47539               /**
47540                * Casts `value` to `identity` if it's not a function.
47541                *
47542                * @private
47543                * @param {*} value The value to inspect.
47544                * @returns {Function} Returns cast function.
47545                */
47546
47547
47548               function castFunction(value) {
47549                 return typeof value == 'function' ? value : identity;
47550               }
47551               /**
47552                * Casts `value` to a path array if it's not one.
47553                *
47554                * @private
47555                * @param {*} value The value to inspect.
47556                * @param {Object} [object] The object to query keys on.
47557                * @returns {Array} Returns the cast property path array.
47558                */
47559
47560
47561               function castPath(value, object) {
47562                 if (isArray(value)) {
47563                   return value;
47564                 }
47565
47566                 return isKey(value, object) ? [value] : stringToPath(toString(value));
47567               }
47568               /**
47569                * A `baseRest` alias which can be replaced with `identity` by module
47570                * replacement plugins.
47571                *
47572                * @private
47573                * @type {Function}
47574                * @param {Function} func The function to apply a rest parameter to.
47575                * @returns {Function} Returns the new function.
47576                */
47577
47578
47579               var castRest = baseRest;
47580               /**
47581                * Casts `array` to a slice if it's needed.
47582                *
47583                * @private
47584                * @param {Array} array The array to inspect.
47585                * @param {number} start The start position.
47586                * @param {number} [end=array.length] The end position.
47587                * @returns {Array} Returns the cast slice.
47588                */
47589
47590               function castSlice(array, start, end) {
47591                 var length = array.length;
47592                 end = end === undefined$1 ? length : end;
47593                 return !start && end >= length ? array : baseSlice(array, start, end);
47594               }
47595               /**
47596                * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
47597                *
47598                * @private
47599                * @param {number|Object} id The timer id or timeout object of the timer to clear.
47600                */
47601
47602
47603               var clearTimeout = ctxClearTimeout || function (id) {
47604                 return root.clearTimeout(id);
47605               };
47606               /**
47607                * Creates a clone of  `buffer`.
47608                *
47609                * @private
47610                * @param {Buffer} buffer The buffer to clone.
47611                * @param {boolean} [isDeep] Specify a deep clone.
47612                * @returns {Buffer} Returns the cloned buffer.
47613                */
47614
47615
47616               function cloneBuffer(buffer, isDeep) {
47617                 if (isDeep) {
47618                   return buffer.slice();
47619                 }
47620
47621                 var length = buffer.length,
47622                     result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
47623                 buffer.copy(result);
47624                 return result;
47625               }
47626               /**
47627                * Creates a clone of `arrayBuffer`.
47628                *
47629                * @private
47630                * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
47631                * @returns {ArrayBuffer} Returns the cloned array buffer.
47632                */
47633
47634
47635               function cloneArrayBuffer(arrayBuffer) {
47636                 var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
47637                 new Uint8Array(result).set(new Uint8Array(arrayBuffer));
47638                 return result;
47639               }
47640               /**
47641                * Creates a clone of `dataView`.
47642                *
47643                * @private
47644                * @param {Object} dataView The data view to clone.
47645                * @param {boolean} [isDeep] Specify a deep clone.
47646                * @returns {Object} Returns the cloned data view.
47647                */
47648
47649
47650               function cloneDataView(dataView, isDeep) {
47651                 var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
47652                 return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
47653               }
47654               /**
47655                * Creates a clone of `regexp`.
47656                *
47657                * @private
47658                * @param {Object} regexp The regexp to clone.
47659                * @returns {Object} Returns the cloned regexp.
47660                */
47661
47662
47663               function cloneRegExp(regexp) {
47664                 var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
47665                 result.lastIndex = regexp.lastIndex;
47666                 return result;
47667               }
47668               /**
47669                * Creates a clone of the `symbol` object.
47670                *
47671                * @private
47672                * @param {Object} symbol The symbol object to clone.
47673                * @returns {Object} Returns the cloned symbol object.
47674                */
47675
47676
47677               function cloneSymbol(symbol) {
47678                 return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
47679               }
47680               /**
47681                * Creates a clone of `typedArray`.
47682                *
47683                * @private
47684                * @param {Object} typedArray The typed array to clone.
47685                * @param {boolean} [isDeep] Specify a deep clone.
47686                * @returns {Object} Returns the cloned typed array.
47687                */
47688
47689
47690               function cloneTypedArray(typedArray, isDeep) {
47691                 var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
47692                 return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
47693               }
47694               /**
47695                * Compares values to sort them in ascending order.
47696                *
47697                * @private
47698                * @param {*} value The value to compare.
47699                * @param {*} other The other value to compare.
47700                * @returns {number} Returns the sort order indicator for `value`.
47701                */
47702
47703
47704               function compareAscending(value, other) {
47705                 if (value !== other) {
47706                   var valIsDefined = value !== undefined$1,
47707                       valIsNull = value === null,
47708                       valIsReflexive = value === value,
47709                       valIsSymbol = isSymbol(value);
47710                   var othIsDefined = other !== undefined$1,
47711                       othIsNull = other === null,
47712                       othIsReflexive = other === other,
47713                       othIsSymbol = isSymbol(other);
47714
47715                   if (!othIsNull && !othIsSymbol && !valIsSymbol && value > other || valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol || valIsNull && othIsDefined && othIsReflexive || !valIsDefined && othIsReflexive || !valIsReflexive) {
47716                     return 1;
47717                   }
47718
47719                   if (!valIsNull && !valIsSymbol && !othIsSymbol && value < other || othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol || othIsNull && valIsDefined && valIsReflexive || !othIsDefined && valIsReflexive || !othIsReflexive) {
47720                     return -1;
47721                   }
47722                 }
47723
47724                 return 0;
47725               }
47726               /**
47727                * Used by `_.orderBy` to compare multiple properties of a value to another
47728                * and stable sort them.
47729                *
47730                * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
47731                * specify an order of "desc" for descending or "asc" for ascending sort order
47732                * of corresponding values.
47733                *
47734                * @private
47735                * @param {Object} object The object to compare.
47736                * @param {Object} other The other object to compare.
47737                * @param {boolean[]|string[]} orders The order to sort by for each property.
47738                * @returns {number} Returns the sort order indicator for `object`.
47739                */
47740
47741
47742               function compareMultiple(object, other, orders) {
47743                 var index = -1,
47744                     objCriteria = object.criteria,
47745                     othCriteria = other.criteria,
47746                     length = objCriteria.length,
47747                     ordersLength = orders.length;
47748
47749                 while (++index < length) {
47750                   var result = compareAscending(objCriteria[index], othCriteria[index]);
47751
47752                   if (result) {
47753                     if (index >= ordersLength) {
47754                       return result;
47755                     }
47756
47757                     var order = orders[index];
47758                     return result * (order == 'desc' ? -1 : 1);
47759                   }
47760                 } // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
47761                 // that causes it, under certain circumstances, to provide the same value for
47762                 // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
47763                 // for more details.
47764                 //
47765                 // This also ensures a stable sort in V8 and other engines.
47766                 // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
47767
47768
47769                 return object.index - other.index;
47770               }
47771               /**
47772                * Creates an array that is the composition of partially applied arguments,
47773                * placeholders, and provided arguments into a single array of arguments.
47774                *
47775                * @private
47776                * @param {Array} args The provided arguments.
47777                * @param {Array} partials The arguments to prepend to those provided.
47778                * @param {Array} holders The `partials` placeholder indexes.
47779                * @params {boolean} [isCurried] Specify composing for a curried function.
47780                * @returns {Array} Returns the new array of composed arguments.
47781                */
47782
47783
47784               function composeArgs(args, partials, holders, isCurried) {
47785                 var argsIndex = -1,
47786                     argsLength = args.length,
47787                     holdersLength = holders.length,
47788                     leftIndex = -1,
47789                     leftLength = partials.length,
47790                     rangeLength = nativeMax(argsLength - holdersLength, 0),
47791                     result = Array(leftLength + rangeLength),
47792                     isUncurried = !isCurried;
47793
47794                 while (++leftIndex < leftLength) {
47795                   result[leftIndex] = partials[leftIndex];
47796                 }
47797
47798                 while (++argsIndex < holdersLength) {
47799                   if (isUncurried || argsIndex < argsLength) {
47800                     result[holders[argsIndex]] = args[argsIndex];
47801                   }
47802                 }
47803
47804                 while (rangeLength--) {
47805                   result[leftIndex++] = args[argsIndex++];
47806                 }
47807
47808                 return result;
47809               }
47810               /**
47811                * This function is like `composeArgs` except that the arguments composition
47812                * is tailored for `_.partialRight`.
47813                *
47814                * @private
47815                * @param {Array} args The provided arguments.
47816                * @param {Array} partials The arguments to append to those provided.
47817                * @param {Array} holders The `partials` placeholder indexes.
47818                * @params {boolean} [isCurried] Specify composing for a curried function.
47819                * @returns {Array} Returns the new array of composed arguments.
47820                */
47821
47822
47823               function composeArgsRight(args, partials, holders, isCurried) {
47824                 var argsIndex = -1,
47825                     argsLength = args.length,
47826                     holdersIndex = -1,
47827                     holdersLength = holders.length,
47828                     rightIndex = -1,
47829                     rightLength = partials.length,
47830                     rangeLength = nativeMax(argsLength - holdersLength, 0),
47831                     result = Array(rangeLength + rightLength),
47832                     isUncurried = !isCurried;
47833
47834                 while (++argsIndex < rangeLength) {
47835                   result[argsIndex] = args[argsIndex];
47836                 }
47837
47838                 var offset = argsIndex;
47839
47840                 while (++rightIndex < rightLength) {
47841                   result[offset + rightIndex] = partials[rightIndex];
47842                 }
47843
47844                 while (++holdersIndex < holdersLength) {
47845                   if (isUncurried || argsIndex < argsLength) {
47846                     result[offset + holders[holdersIndex]] = args[argsIndex++];
47847                   }
47848                 }
47849
47850                 return result;
47851               }
47852               /**
47853                * Copies the values of `source` to `array`.
47854                *
47855                * @private
47856                * @param {Array} source The array to copy values from.
47857                * @param {Array} [array=[]] The array to copy values to.
47858                * @returns {Array} Returns `array`.
47859                */
47860
47861
47862               function copyArray(source, array) {
47863                 var index = -1,
47864                     length = source.length;
47865                 array || (array = Array(length));
47866
47867                 while (++index < length) {
47868                   array[index] = source[index];
47869                 }
47870
47871                 return array;
47872               }
47873               /**
47874                * Copies properties of `source` to `object`.
47875                *
47876                * @private
47877                * @param {Object} source The object to copy properties from.
47878                * @param {Array} props The property identifiers to copy.
47879                * @param {Object} [object={}] The object to copy properties to.
47880                * @param {Function} [customizer] The function to customize copied values.
47881                * @returns {Object} Returns `object`.
47882                */
47883
47884
47885               function copyObject(source, props, object, customizer) {
47886                 var isNew = !object;
47887                 object || (object = {});
47888                 var index = -1,
47889                     length = props.length;
47890
47891                 while (++index < length) {
47892                   var key = props[index];
47893                   var newValue = customizer ? customizer(object[key], source[key], key, object, source) : undefined$1;
47894
47895                   if (newValue === undefined$1) {
47896                     newValue = source[key];
47897                   }
47898
47899                   if (isNew) {
47900                     baseAssignValue(object, key, newValue);
47901                   } else {
47902                     assignValue(object, key, newValue);
47903                   }
47904                 }
47905
47906                 return object;
47907               }
47908               /**
47909                * Copies own symbols of `source` to `object`.
47910                *
47911                * @private
47912                * @param {Object} source The object to copy symbols from.
47913                * @param {Object} [object={}] The object to copy symbols to.
47914                * @returns {Object} Returns `object`.
47915                */
47916
47917
47918               function copySymbols(source, object) {
47919                 return copyObject(source, getSymbols(source), object);
47920               }
47921               /**
47922                * Copies own and inherited symbols of `source` to `object`.
47923                *
47924                * @private
47925                * @param {Object} source The object to copy symbols from.
47926                * @param {Object} [object={}] The object to copy symbols to.
47927                * @returns {Object} Returns `object`.
47928                */
47929
47930
47931               function copySymbolsIn(source, object) {
47932                 return copyObject(source, getSymbolsIn(source), object);
47933               }
47934               /**
47935                * Creates a function like `_.groupBy`.
47936                *
47937                * @private
47938                * @param {Function} setter The function to set accumulator values.
47939                * @param {Function} [initializer] The accumulator object initializer.
47940                * @returns {Function} Returns the new aggregator function.
47941                */
47942
47943
47944               function createAggregator(setter, initializer) {
47945                 return function (collection, iteratee) {
47946                   var func = isArray(collection) ? arrayAggregator : baseAggregator,
47947                       accumulator = initializer ? initializer() : {};
47948                   return func(collection, setter, getIteratee(iteratee, 2), accumulator);
47949                 };
47950               }
47951               /**
47952                * Creates a function like `_.assign`.
47953                *
47954                * @private
47955                * @param {Function} assigner The function to assign values.
47956                * @returns {Function} Returns the new assigner function.
47957                */
47958
47959
47960               function createAssigner(assigner) {
47961                 return baseRest(function (object, sources) {
47962                   var index = -1,
47963                       length = sources.length,
47964                       customizer = length > 1 ? sources[length - 1] : undefined$1,
47965                       guard = length > 2 ? sources[2] : undefined$1;
47966                   customizer = assigner.length > 3 && typeof customizer == 'function' ? (length--, customizer) : undefined$1;
47967
47968                   if (guard && isIterateeCall(sources[0], sources[1], guard)) {
47969                     customizer = length < 3 ? undefined$1 : customizer;
47970                     length = 1;
47971                   }
47972
47973                   object = Object(object);
47974
47975                   while (++index < length) {
47976                     var source = sources[index];
47977
47978                     if (source) {
47979                       assigner(object, source, index, customizer);
47980                     }
47981                   }
47982
47983                   return object;
47984                 });
47985               }
47986               /**
47987                * Creates a `baseEach` or `baseEachRight` function.
47988                *
47989                * @private
47990                * @param {Function} eachFunc The function to iterate over a collection.
47991                * @param {boolean} [fromRight] Specify iterating from right to left.
47992                * @returns {Function} Returns the new base function.
47993                */
47994
47995
47996               function createBaseEach(eachFunc, fromRight) {
47997                 return function (collection, iteratee) {
47998                   if (collection == null) {
47999                     return collection;
48000                   }
48001
48002                   if (!isArrayLike(collection)) {
48003                     return eachFunc(collection, iteratee);
48004                   }
48005
48006                   var length = collection.length,
48007                       index = fromRight ? length : -1,
48008                       iterable = Object(collection);
48009
48010                   while (fromRight ? index-- : ++index < length) {
48011                     if (iteratee(iterable[index], index, iterable) === false) {
48012                       break;
48013                     }
48014                   }
48015
48016                   return collection;
48017                 };
48018               }
48019               /**
48020                * Creates a base function for methods like `_.forIn` and `_.forOwn`.
48021                *
48022                * @private
48023                * @param {boolean} [fromRight] Specify iterating from right to left.
48024                * @returns {Function} Returns the new base function.
48025                */
48026
48027
48028               function createBaseFor(fromRight) {
48029                 return function (object, iteratee, keysFunc) {
48030                   var index = -1,
48031                       iterable = Object(object),
48032                       props = keysFunc(object),
48033                       length = props.length;
48034
48035                   while (length--) {
48036                     var key = props[fromRight ? length : ++index];
48037
48038                     if (iteratee(iterable[key], key, iterable) === false) {
48039                       break;
48040                     }
48041                   }
48042
48043                   return object;
48044                 };
48045               }
48046               /**
48047                * Creates a function that wraps `func` to invoke it with the optional `this`
48048                * binding of `thisArg`.
48049                *
48050                * @private
48051                * @param {Function} func The function to wrap.
48052                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48053                * @param {*} [thisArg] The `this` binding of `func`.
48054                * @returns {Function} Returns the new wrapped function.
48055                */
48056
48057
48058               function createBind(func, bitmask, thisArg) {
48059                 var isBind = bitmask & WRAP_BIND_FLAG,
48060                     Ctor = createCtor(func);
48061
48062                 function wrapper() {
48063                   var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
48064                   return fn.apply(isBind ? thisArg : this, arguments);
48065                 }
48066
48067                 return wrapper;
48068               }
48069               /**
48070                * Creates a function like `_.lowerFirst`.
48071                *
48072                * @private
48073                * @param {string} methodName The name of the `String` case method to use.
48074                * @returns {Function} Returns the new case function.
48075                */
48076
48077
48078               function createCaseFirst(methodName) {
48079                 return function (string) {
48080                   string = toString(string);
48081                   var strSymbols = hasUnicode(string) ? stringToArray(string) : undefined$1;
48082                   var chr = strSymbols ? strSymbols[0] : string.charAt(0);
48083                   var trailing = strSymbols ? castSlice(strSymbols, 1).join('') : string.slice(1);
48084                   return chr[methodName]() + trailing;
48085                 };
48086               }
48087               /**
48088                * Creates a function like `_.camelCase`.
48089                *
48090                * @private
48091                * @param {Function} callback The function to combine each word.
48092                * @returns {Function} Returns the new compounder function.
48093                */
48094
48095
48096               function createCompounder(callback) {
48097                 return function (string) {
48098                   return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
48099                 };
48100               }
48101               /**
48102                * Creates a function that produces an instance of `Ctor` regardless of
48103                * whether it was invoked as part of a `new` expression or by `call` or `apply`.
48104                *
48105                * @private
48106                * @param {Function} Ctor The constructor to wrap.
48107                * @returns {Function} Returns the new wrapped function.
48108                */
48109
48110
48111               function createCtor(Ctor) {
48112                 return function () {
48113                   // Use a `switch` statement to work with class constructors. See
48114                   // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
48115                   // for more details.
48116                   var args = arguments;
48117
48118                   switch (args.length) {
48119                     case 0:
48120                       return new Ctor();
48121
48122                     case 1:
48123                       return new Ctor(args[0]);
48124
48125                     case 2:
48126                       return new Ctor(args[0], args[1]);
48127
48128                     case 3:
48129                       return new Ctor(args[0], args[1], args[2]);
48130
48131                     case 4:
48132                       return new Ctor(args[0], args[1], args[2], args[3]);
48133
48134                     case 5:
48135                       return new Ctor(args[0], args[1], args[2], args[3], args[4]);
48136
48137                     case 6:
48138                       return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
48139
48140                     case 7:
48141                       return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
48142                   }
48143
48144                   var thisBinding = baseCreate(Ctor.prototype),
48145                       result = Ctor.apply(thisBinding, args); // Mimic the constructor's `return` behavior.
48146                   // See https://es5.github.io/#x13.2.2 for more details.
48147
48148                   return isObject(result) ? result : thisBinding;
48149                 };
48150               }
48151               /**
48152                * Creates a function that wraps `func` to enable currying.
48153                *
48154                * @private
48155                * @param {Function} func The function to wrap.
48156                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48157                * @param {number} arity The arity of `func`.
48158                * @returns {Function} Returns the new wrapped function.
48159                */
48160
48161
48162               function createCurry(func, bitmask, arity) {
48163                 var Ctor = createCtor(func);
48164
48165                 function wrapper() {
48166                   var length = arguments.length,
48167                       args = Array(length),
48168                       index = length,
48169                       placeholder = getHolder(wrapper);
48170
48171                   while (index--) {
48172                     args[index] = arguments[index];
48173                   }
48174
48175                   var holders = length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder ? [] : replaceHolders(args, placeholder);
48176                   length -= holders.length;
48177
48178                   if (length < arity) {
48179                     return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, undefined$1, args, holders, undefined$1, undefined$1, arity - length);
48180                   }
48181
48182                   var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
48183                   return apply(fn, this, args);
48184                 }
48185
48186                 return wrapper;
48187               }
48188               /**
48189                * Creates a `_.find` or `_.findLast` function.
48190                *
48191                * @private
48192                * @param {Function} findIndexFunc The function to find the collection index.
48193                * @returns {Function} Returns the new find function.
48194                */
48195
48196
48197               function createFind(findIndexFunc) {
48198                 return function (collection, predicate, fromIndex) {
48199                   var iterable = Object(collection);
48200
48201                   if (!isArrayLike(collection)) {
48202                     var iteratee = getIteratee(predicate, 3);
48203                     collection = keys(collection);
48204
48205                     predicate = function predicate(key) {
48206                       return iteratee(iterable[key], key, iterable);
48207                     };
48208                   }
48209
48210                   var index = findIndexFunc(collection, predicate, fromIndex);
48211                   return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined$1;
48212                 };
48213               }
48214               /**
48215                * Creates a `_.flow` or `_.flowRight` function.
48216                *
48217                * @private
48218                * @param {boolean} [fromRight] Specify iterating from right to left.
48219                * @returns {Function} Returns the new flow function.
48220                */
48221
48222
48223               function createFlow(fromRight) {
48224                 return flatRest(function (funcs) {
48225                   var length = funcs.length,
48226                       index = length,
48227                       prereq = LodashWrapper.prototype.thru;
48228
48229                   if (fromRight) {
48230                     funcs.reverse();
48231                   }
48232
48233                   while (index--) {
48234                     var func = funcs[index];
48235
48236                     if (typeof func != 'function') {
48237                       throw new TypeError(FUNC_ERROR_TEXT);
48238                     }
48239
48240                     if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
48241                       var wrapper = new LodashWrapper([], true);
48242                     }
48243                   }
48244
48245                   index = wrapper ? index : length;
48246
48247                   while (++index < length) {
48248                     func = funcs[index];
48249                     var funcName = getFuncName(func),
48250                         data = funcName == 'wrapper' ? getData(func) : undefined$1;
48251
48252                     if (data && isLaziable(data[0]) && data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && !data[4].length && data[9] == 1) {
48253                       wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
48254                     } else {
48255                       wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func);
48256                     }
48257                   }
48258
48259                   return function () {
48260                     var args = arguments,
48261                         value = args[0];
48262
48263                     if (wrapper && args.length == 1 && isArray(value)) {
48264                       return wrapper.plant(value).value();
48265                     }
48266
48267                     var index = 0,
48268                         result = length ? funcs[index].apply(this, args) : value;
48269
48270                     while (++index < length) {
48271                       result = funcs[index].call(this, result);
48272                     }
48273
48274                     return result;
48275                   };
48276                 });
48277               }
48278               /**
48279                * Creates a function that wraps `func` to invoke it with optional `this`
48280                * binding of `thisArg`, partial application, and currying.
48281                *
48282                * @private
48283                * @param {Function|string} func The function or method name to wrap.
48284                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48285                * @param {*} [thisArg] The `this` binding of `func`.
48286                * @param {Array} [partials] The arguments to prepend to those provided to
48287                *  the new function.
48288                * @param {Array} [holders] The `partials` placeholder indexes.
48289                * @param {Array} [partialsRight] The arguments to append to those provided
48290                *  to the new function.
48291                * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
48292                * @param {Array} [argPos] The argument positions of the new function.
48293                * @param {number} [ary] The arity cap of `func`.
48294                * @param {number} [arity] The arity of `func`.
48295                * @returns {Function} Returns the new wrapped function.
48296                */
48297
48298
48299               function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
48300                 var isAry = bitmask & WRAP_ARY_FLAG,
48301                     isBind = bitmask & WRAP_BIND_FLAG,
48302                     isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
48303                     isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
48304                     isFlip = bitmask & WRAP_FLIP_FLAG,
48305                     Ctor = isBindKey ? undefined$1 : createCtor(func);
48306
48307                 function wrapper() {
48308                   var length = arguments.length,
48309                       args = Array(length),
48310                       index = length;
48311
48312                   while (index--) {
48313                     args[index] = arguments[index];
48314                   }
48315
48316                   if (isCurried) {
48317                     var placeholder = getHolder(wrapper),
48318                         holdersCount = countHolders(args, placeholder);
48319                   }
48320
48321                   if (partials) {
48322                     args = composeArgs(args, partials, holders, isCurried);
48323                   }
48324
48325                   if (partialsRight) {
48326                     args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
48327                   }
48328
48329                   length -= holdersCount;
48330
48331                   if (isCurried && length < arity) {
48332                     var newHolders = replaceHolders(args, placeholder);
48333                     return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, thisArg, args, newHolders, argPos, ary, arity - length);
48334                   }
48335
48336                   var thisBinding = isBind ? thisArg : this,
48337                       fn = isBindKey ? thisBinding[func] : func;
48338                   length = args.length;
48339
48340                   if (argPos) {
48341                     args = reorder(args, argPos);
48342                   } else if (isFlip && length > 1) {
48343                     args.reverse();
48344                   }
48345
48346                   if (isAry && ary < length) {
48347                     args.length = ary;
48348                   }
48349
48350                   if (this && this !== root && this instanceof wrapper) {
48351                     fn = Ctor || createCtor(fn);
48352                   }
48353
48354                   return fn.apply(thisBinding, args);
48355                 }
48356
48357                 return wrapper;
48358               }
48359               /**
48360                * Creates a function like `_.invertBy`.
48361                *
48362                * @private
48363                * @param {Function} setter The function to set accumulator values.
48364                * @param {Function} toIteratee The function to resolve iteratees.
48365                * @returns {Function} Returns the new inverter function.
48366                */
48367
48368
48369               function createInverter(setter, toIteratee) {
48370                 return function (object, iteratee) {
48371                   return baseInverter(object, setter, toIteratee(iteratee), {});
48372                 };
48373               }
48374               /**
48375                * Creates a function that performs a mathematical operation on two values.
48376                *
48377                * @private
48378                * @param {Function} operator The function to perform the operation.
48379                * @param {number} [defaultValue] The value used for `undefined` arguments.
48380                * @returns {Function} Returns the new mathematical operation function.
48381                */
48382
48383
48384               function createMathOperation(operator, defaultValue) {
48385                 return function (value, other) {
48386                   var result;
48387
48388                   if (value === undefined$1 && other === undefined$1) {
48389                     return defaultValue;
48390                   }
48391
48392                   if (value !== undefined$1) {
48393                     result = value;
48394                   }
48395
48396                   if (other !== undefined$1) {
48397                     if (result === undefined$1) {
48398                       return other;
48399                     }
48400
48401                     if (typeof value == 'string' || typeof other == 'string') {
48402                       value = baseToString(value);
48403                       other = baseToString(other);
48404                     } else {
48405                       value = baseToNumber(value);
48406                       other = baseToNumber(other);
48407                     }
48408
48409                     result = operator(value, other);
48410                   }
48411
48412                   return result;
48413                 };
48414               }
48415               /**
48416                * Creates a function like `_.over`.
48417                *
48418                * @private
48419                * @param {Function} arrayFunc The function to iterate over iteratees.
48420                * @returns {Function} Returns the new over function.
48421                */
48422
48423
48424               function createOver(arrayFunc) {
48425                 return flatRest(function (iteratees) {
48426                   iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
48427                   return baseRest(function (args) {
48428                     var thisArg = this;
48429                     return arrayFunc(iteratees, function (iteratee) {
48430                       return apply(iteratee, thisArg, args);
48431                     });
48432                   });
48433                 });
48434               }
48435               /**
48436                * Creates the padding for `string` based on `length`. The `chars` string
48437                * is truncated if the number of characters exceeds `length`.
48438                *
48439                * @private
48440                * @param {number} length The padding length.
48441                * @param {string} [chars=' '] The string used as padding.
48442                * @returns {string} Returns the padding for `string`.
48443                */
48444
48445
48446               function createPadding(length, chars) {
48447                 chars = chars === undefined$1 ? ' ' : baseToString(chars);
48448                 var charsLength = chars.length;
48449
48450                 if (charsLength < 2) {
48451                   return charsLength ? baseRepeat(chars, length) : chars;
48452                 }
48453
48454                 var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
48455                 return hasUnicode(chars) ? castSlice(stringToArray(result), 0, length).join('') : result.slice(0, length);
48456               }
48457               /**
48458                * Creates a function that wraps `func` to invoke it with the `this` binding
48459                * of `thisArg` and `partials` prepended to the arguments it receives.
48460                *
48461                * @private
48462                * @param {Function} func The function to wrap.
48463                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48464                * @param {*} thisArg The `this` binding of `func`.
48465                * @param {Array} partials The arguments to prepend to those provided to
48466                *  the new function.
48467                * @returns {Function} Returns the new wrapped function.
48468                */
48469
48470
48471               function createPartial(func, bitmask, thisArg, partials) {
48472                 var isBind = bitmask & WRAP_BIND_FLAG,
48473                     Ctor = createCtor(func);
48474
48475                 function wrapper() {
48476                   var argsIndex = -1,
48477                       argsLength = arguments.length,
48478                       leftIndex = -1,
48479                       leftLength = partials.length,
48480                       args = Array(leftLength + argsLength),
48481                       fn = this && this !== root && this instanceof wrapper ? Ctor : func;
48482
48483                   while (++leftIndex < leftLength) {
48484                     args[leftIndex] = partials[leftIndex];
48485                   }
48486
48487                   while (argsLength--) {
48488                     args[leftIndex++] = arguments[++argsIndex];
48489                   }
48490
48491                   return apply(fn, isBind ? thisArg : this, args);
48492                 }
48493
48494                 return wrapper;
48495               }
48496               /**
48497                * Creates a `_.range` or `_.rangeRight` function.
48498                *
48499                * @private
48500                * @param {boolean} [fromRight] Specify iterating from right to left.
48501                * @returns {Function} Returns the new range function.
48502                */
48503
48504
48505               function createRange(fromRight) {
48506                 return function (start, end, step) {
48507                   if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
48508                     end = step = undefined$1;
48509                   } // Ensure the sign of `-0` is preserved.
48510
48511
48512                   start = toFinite(start);
48513
48514                   if (end === undefined$1) {
48515                     end = start;
48516                     start = 0;
48517                   } else {
48518                     end = toFinite(end);
48519                   }
48520
48521                   step = step === undefined$1 ? start < end ? 1 : -1 : toFinite(step);
48522                   return baseRange(start, end, step, fromRight);
48523                 };
48524               }
48525               /**
48526                * Creates a function that performs a relational operation on two values.
48527                *
48528                * @private
48529                * @param {Function} operator The function to perform the operation.
48530                * @returns {Function} Returns the new relational operation function.
48531                */
48532
48533
48534               function createRelationalOperation(operator) {
48535                 return function (value, other) {
48536                   if (!(typeof value == 'string' && typeof other == 'string')) {
48537                     value = toNumber(value);
48538                     other = toNumber(other);
48539                   }
48540
48541                   return operator(value, other);
48542                 };
48543               }
48544               /**
48545                * Creates a function that wraps `func` to continue currying.
48546                *
48547                * @private
48548                * @param {Function} func The function to wrap.
48549                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
48550                * @param {Function} wrapFunc The function to create the `func` wrapper.
48551                * @param {*} placeholder The placeholder value.
48552                * @param {*} [thisArg] The `this` binding of `func`.
48553                * @param {Array} [partials] The arguments to prepend to those provided to
48554                *  the new function.
48555                * @param {Array} [holders] The `partials` placeholder indexes.
48556                * @param {Array} [argPos] The argument positions of the new function.
48557                * @param {number} [ary] The arity cap of `func`.
48558                * @param {number} [arity] The arity of `func`.
48559                * @returns {Function} Returns the new wrapped function.
48560                */
48561
48562
48563               function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
48564                 var isCurry = bitmask & WRAP_CURRY_FLAG,
48565                     newHolders = isCurry ? holders : undefined$1,
48566                     newHoldersRight = isCurry ? undefined$1 : holders,
48567                     newPartials = isCurry ? partials : undefined$1,
48568                     newPartialsRight = isCurry ? undefined$1 : partials;
48569                 bitmask |= isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG;
48570                 bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
48571
48572                 if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
48573                   bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
48574                 }
48575
48576                 var newData = [func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, newHoldersRight, argPos, ary, arity];
48577                 var result = wrapFunc.apply(undefined$1, newData);
48578
48579                 if (isLaziable(func)) {
48580                   setData(result, newData);
48581                 }
48582
48583                 result.placeholder = placeholder;
48584                 return setWrapToString(result, func, bitmask);
48585               }
48586               /**
48587                * Creates a function like `_.round`.
48588                *
48589                * @private
48590                * @param {string} methodName The name of the `Math` method to use when rounding.
48591                * @returns {Function} Returns the new round function.
48592                */
48593
48594
48595               function createRound(methodName) {
48596                 var func = Math[methodName];
48597                 return function (number, precision) {
48598                   number = toNumber(number);
48599                   precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
48600
48601                   if (precision && nativeIsFinite(number)) {
48602                     // Shift with exponential notation to avoid floating-point issues.
48603                     // See [MDN](https://mdn.io/round#Examples) for more details.
48604                     var pair = (toString(number) + 'e').split('e'),
48605                         value = func(pair[0] + 'e' + (+pair[1] + precision));
48606                     pair = (toString(value) + 'e').split('e');
48607                     return +(pair[0] + 'e' + (+pair[1] - precision));
48608                   }
48609
48610                   return func(number);
48611                 };
48612               }
48613               /**
48614                * Creates a set object of `values`.
48615                *
48616                * @private
48617                * @param {Array} values The values to add to the set.
48618                * @returns {Object} Returns the new set.
48619                */
48620
48621
48622               var createSet = !(Set && 1 / setToArray(new Set([, -0]))[1] == INFINITY) ? noop : function (values) {
48623                 return new Set(values);
48624               };
48625               /**
48626                * Creates a `_.toPairs` or `_.toPairsIn` function.
48627                *
48628                * @private
48629                * @param {Function} keysFunc The function to get the keys of a given object.
48630                * @returns {Function} Returns the new pairs function.
48631                */
48632
48633               function createToPairs(keysFunc) {
48634                 return function (object) {
48635                   var tag = getTag(object);
48636
48637                   if (tag == mapTag) {
48638                     return mapToArray(object);
48639                   }
48640
48641                   if (tag == setTag) {
48642                     return setToPairs(object);
48643                   }
48644
48645                   return baseToPairs(object, keysFunc(object));
48646                 };
48647               }
48648               /**
48649                * Creates a function that either curries or invokes `func` with optional
48650                * `this` binding and partially applied arguments.
48651                *
48652                * @private
48653                * @param {Function|string} func The function or method name to wrap.
48654                * @param {number} bitmask The bitmask flags.
48655                *    1 - `_.bind`
48656                *    2 - `_.bindKey`
48657                *    4 - `_.curry` or `_.curryRight` of a bound function
48658                *    8 - `_.curry`
48659                *   16 - `_.curryRight`
48660                *   32 - `_.partial`
48661                *   64 - `_.partialRight`
48662                *  128 - `_.rearg`
48663                *  256 - `_.ary`
48664                *  512 - `_.flip`
48665                * @param {*} [thisArg] The `this` binding of `func`.
48666                * @param {Array} [partials] The arguments to be partially applied.
48667                * @param {Array} [holders] The `partials` placeholder indexes.
48668                * @param {Array} [argPos] The argument positions of the new function.
48669                * @param {number} [ary] The arity cap of `func`.
48670                * @param {number} [arity] The arity of `func`.
48671                * @returns {Function} Returns the new wrapped function.
48672                */
48673
48674
48675               function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
48676                 var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
48677
48678                 if (!isBindKey && typeof func != 'function') {
48679                   throw new TypeError(FUNC_ERROR_TEXT);
48680                 }
48681
48682                 var length = partials ? partials.length : 0;
48683
48684                 if (!length) {
48685                   bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
48686                   partials = holders = undefined$1;
48687                 }
48688
48689                 ary = ary === undefined$1 ? ary : nativeMax(toInteger(ary), 0);
48690                 arity = arity === undefined$1 ? arity : toInteger(arity);
48691                 length -= holders ? holders.length : 0;
48692
48693                 if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
48694                   var partialsRight = partials,
48695                       holdersRight = holders;
48696                   partials = holders = undefined$1;
48697                 }
48698
48699                 var data = isBindKey ? undefined$1 : getData(func);
48700                 var newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
48701
48702                 if (data) {
48703                   mergeData(newData, data);
48704                 }
48705
48706                 func = newData[0];
48707                 bitmask = newData[1];
48708                 thisArg = newData[2];
48709                 partials = newData[3];
48710                 holders = newData[4];
48711                 arity = newData[9] = newData[9] === undefined$1 ? isBindKey ? 0 : func.length : nativeMax(newData[9] - length, 0);
48712
48713                 if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
48714                   bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
48715                 }
48716
48717                 if (!bitmask || bitmask == WRAP_BIND_FLAG) {
48718                   var result = createBind(func, bitmask, thisArg);
48719                 } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
48720                   result = createCurry(func, bitmask, arity);
48721                 } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
48722                   result = createPartial(func, bitmask, thisArg, partials);
48723                 } else {
48724                   result = createHybrid.apply(undefined$1, newData);
48725                 }
48726
48727                 var setter = data ? baseSetData : setData;
48728                 return setWrapToString(setter(result, newData), func, bitmask);
48729               }
48730               /**
48731                * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
48732                * of source objects to the destination object for all destination properties
48733                * that resolve to `undefined`.
48734                *
48735                * @private
48736                * @param {*} objValue The destination value.
48737                * @param {*} srcValue The source value.
48738                * @param {string} key The key of the property to assign.
48739                * @param {Object} object The parent object of `objValue`.
48740                * @returns {*} Returns the value to assign.
48741                */
48742
48743
48744               function customDefaultsAssignIn(objValue, srcValue, key, object) {
48745                 if (objValue === undefined$1 || eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key)) {
48746                   return srcValue;
48747                 }
48748
48749                 return objValue;
48750               }
48751               /**
48752                * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source
48753                * objects into destination objects that are passed thru.
48754                *
48755                * @private
48756                * @param {*} objValue The destination value.
48757                * @param {*} srcValue The source value.
48758                * @param {string} key The key of the property to merge.
48759                * @param {Object} object The parent object of `objValue`.
48760                * @param {Object} source The parent object of `srcValue`.
48761                * @param {Object} [stack] Tracks traversed source values and their merged
48762                *  counterparts.
48763                * @returns {*} Returns the value to assign.
48764                */
48765
48766
48767               function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
48768                 if (isObject(objValue) && isObject(srcValue)) {
48769                   // Recursively merge objects and arrays (susceptible to call stack limits).
48770                   stack.set(srcValue, objValue);
48771                   baseMerge(objValue, srcValue, undefined$1, customDefaultsMerge, stack);
48772                   stack['delete'](srcValue);
48773                 }
48774
48775                 return objValue;
48776               }
48777               /**
48778                * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain
48779                * objects.
48780                *
48781                * @private
48782                * @param {*} value The value to inspect.
48783                * @param {string} key The key of the property to inspect.
48784                * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`.
48785                */
48786
48787
48788               function customOmitClone(value) {
48789                 return isPlainObject(value) ? undefined$1 : value;
48790               }
48791               /**
48792                * A specialized version of `baseIsEqualDeep` for arrays with support for
48793                * partial deep comparisons.
48794                *
48795                * @private
48796                * @param {Array} array The array to compare.
48797                * @param {Array} other The other array to compare.
48798                * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
48799                * @param {Function} customizer The function to customize comparisons.
48800                * @param {Function} equalFunc The function to determine equivalents of values.
48801                * @param {Object} stack Tracks traversed `array` and `other` objects.
48802                * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
48803                */
48804
48805
48806               function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
48807                 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
48808                     arrLength = array.length,
48809                     othLength = other.length;
48810
48811                 if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
48812                   return false;
48813                 } // Check that cyclic values are equal.
48814
48815
48816                 var arrStacked = stack.get(array);
48817                 var othStacked = stack.get(other);
48818
48819                 if (arrStacked && othStacked) {
48820                   return arrStacked == other && othStacked == array;
48821                 }
48822
48823                 var index = -1,
48824                     result = true,
48825                     seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache() : undefined$1;
48826                 stack.set(array, other);
48827                 stack.set(other, array); // Ignore non-index properties.
48828
48829                 while (++index < arrLength) {
48830                   var arrValue = array[index],
48831                       othValue = other[index];
48832
48833                   if (customizer) {
48834                     var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack);
48835                   }
48836
48837                   if (compared !== undefined$1) {
48838                     if (compared) {
48839                       continue;
48840                     }
48841
48842                     result = false;
48843                     break;
48844                   } // Recursively compare arrays (susceptible to call stack limits).
48845
48846
48847                   if (seen) {
48848                     if (!arraySome(other, function (othValue, othIndex) {
48849                       if (!cacheHas(seen, othIndex) && (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
48850                         return seen.push(othIndex);
48851                       }
48852                     })) {
48853                       result = false;
48854                       break;
48855                     }
48856                   } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
48857                     result = false;
48858                     break;
48859                   }
48860                 }
48861
48862                 stack['delete'](array);
48863                 stack['delete'](other);
48864                 return result;
48865               }
48866               /**
48867                * A specialized version of `baseIsEqualDeep` for comparing objects of
48868                * the same `toStringTag`.
48869                *
48870                * **Note:** This function only supports comparing values with tags of
48871                * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
48872                *
48873                * @private
48874                * @param {Object} object The object to compare.
48875                * @param {Object} other The other object to compare.
48876                * @param {string} tag The `toStringTag` of the objects to compare.
48877                * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
48878                * @param {Function} customizer The function to customize comparisons.
48879                * @param {Function} equalFunc The function to determine equivalents of values.
48880                * @param {Object} stack Tracks traversed `object` and `other` objects.
48881                * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
48882                */
48883
48884
48885               function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
48886                 switch (tag) {
48887                   case dataViewTag:
48888                     if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) {
48889                       return false;
48890                     }
48891
48892                     object = object.buffer;
48893                     other = other.buffer;
48894
48895                   case arrayBufferTag:
48896                     if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
48897                       return false;
48898                     }
48899
48900                     return true;
48901
48902                   case boolTag:
48903                   case dateTag:
48904                   case numberTag:
48905                     // Coerce booleans to `1` or `0` and dates to milliseconds.
48906                     // Invalid dates are coerced to `NaN`.
48907                     return eq(+object, +other);
48908
48909                   case errorTag:
48910                     return object.name == other.name && object.message == other.message;
48911
48912                   case regexpTag:
48913                   case stringTag:
48914                     // Coerce regexes to strings and treat strings, primitives and objects,
48915                     // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
48916                     // for more details.
48917                     return object == other + '';
48918
48919                   case mapTag:
48920                     var convert = mapToArray;
48921
48922                   case setTag:
48923                     var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
48924                     convert || (convert = setToArray);
48925
48926                     if (object.size != other.size && !isPartial) {
48927                       return false;
48928                     } // Assume cyclic values are equal.
48929
48930
48931                     var stacked = stack.get(object);
48932
48933                     if (stacked) {
48934                       return stacked == other;
48935                     }
48936
48937                     bitmask |= COMPARE_UNORDERED_FLAG; // Recursively compare objects (susceptible to call stack limits).
48938
48939                     stack.set(object, other);
48940                     var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
48941                     stack['delete'](object);
48942                     return result;
48943
48944                   case symbolTag:
48945                     if (symbolValueOf) {
48946                       return symbolValueOf.call(object) == symbolValueOf.call(other);
48947                     }
48948
48949                 }
48950
48951                 return false;
48952               }
48953               /**
48954                * A specialized version of `baseIsEqualDeep` for objects with support for
48955                * partial deep comparisons.
48956                *
48957                * @private
48958                * @param {Object} object The object to compare.
48959                * @param {Object} other The other object to compare.
48960                * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
48961                * @param {Function} customizer The function to customize comparisons.
48962                * @param {Function} equalFunc The function to determine equivalents of values.
48963                * @param {Object} stack Tracks traversed `object` and `other` objects.
48964                * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
48965                */
48966
48967
48968               function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
48969                 var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
48970                     objProps = getAllKeys(object),
48971                     objLength = objProps.length,
48972                     othProps = getAllKeys(other),
48973                     othLength = othProps.length;
48974
48975                 if (objLength != othLength && !isPartial) {
48976                   return false;
48977                 }
48978
48979                 var index = objLength;
48980
48981                 while (index--) {
48982                   var key = objProps[index];
48983
48984                   if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
48985                     return false;
48986                   }
48987                 } // Check that cyclic values are equal.
48988
48989
48990                 var objStacked = stack.get(object);
48991                 var othStacked = stack.get(other);
48992
48993                 if (objStacked && othStacked) {
48994                   return objStacked == other && othStacked == object;
48995                 }
48996
48997                 var result = true;
48998                 stack.set(object, other);
48999                 stack.set(other, object);
49000                 var skipCtor = isPartial;
49001
49002                 while (++index < objLength) {
49003                   key = objProps[index];
49004                   var objValue = object[key],
49005                       othValue = other[key];
49006
49007                   if (customizer) {
49008                     var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack);
49009                   } // Recursively compare objects (susceptible to call stack limits).
49010
49011
49012                   if (!(compared === undefined$1 ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) {
49013                     result = false;
49014                     break;
49015                   }
49016
49017                   skipCtor || (skipCtor = key == 'constructor');
49018                 }
49019
49020                 if (result && !skipCtor) {
49021                   var objCtor = object.constructor,
49022                       othCtor = other.constructor; // Non `Object` object instances with different constructors are not equal.
49023
49024                   if (objCtor != othCtor && 'constructor' in object && 'constructor' in other && !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) {
49025                     result = false;
49026                   }
49027                 }
49028
49029                 stack['delete'](object);
49030                 stack['delete'](other);
49031                 return result;
49032               }
49033               /**
49034                * A specialized version of `baseRest` which flattens the rest array.
49035                *
49036                * @private
49037                * @param {Function} func The function to apply a rest parameter to.
49038                * @returns {Function} Returns the new function.
49039                */
49040
49041
49042               function flatRest(func) {
49043                 return setToString(overRest(func, undefined$1, flatten), func + '');
49044               }
49045               /**
49046                * Creates an array of own enumerable property names and symbols of `object`.
49047                *
49048                * @private
49049                * @param {Object} object The object to query.
49050                * @returns {Array} Returns the array of property names and symbols.
49051                */
49052
49053
49054               function getAllKeys(object) {
49055                 return baseGetAllKeys(object, keys, getSymbols);
49056               }
49057               /**
49058                * Creates an array of own and inherited enumerable property names and
49059                * symbols of `object`.
49060                *
49061                * @private
49062                * @param {Object} object The object to query.
49063                * @returns {Array} Returns the array of property names and symbols.
49064                */
49065
49066
49067               function getAllKeysIn(object) {
49068                 return baseGetAllKeys(object, keysIn, getSymbolsIn);
49069               }
49070               /**
49071                * Gets metadata for `func`.
49072                *
49073                * @private
49074                * @param {Function} func The function to query.
49075                * @returns {*} Returns the metadata for `func`.
49076                */
49077
49078
49079               var getData = !metaMap ? noop : function (func) {
49080                 return metaMap.get(func);
49081               };
49082               /**
49083                * Gets the name of `func`.
49084                *
49085                * @private
49086                * @param {Function} func The function to query.
49087                * @returns {string} Returns the function name.
49088                */
49089
49090               function getFuncName(func) {
49091                 var result = func.name + '',
49092                     array = realNames[result],
49093                     length = hasOwnProperty.call(realNames, result) ? array.length : 0;
49094
49095                 while (length--) {
49096                   var data = array[length],
49097                       otherFunc = data.func;
49098
49099                   if (otherFunc == null || otherFunc == func) {
49100                     return data.name;
49101                   }
49102                 }
49103
49104                 return result;
49105               }
49106               /**
49107                * Gets the argument placeholder value for `func`.
49108                *
49109                * @private
49110                * @param {Function} func The function to inspect.
49111                * @returns {*} Returns the placeholder value.
49112                */
49113
49114
49115               function getHolder(func) {
49116                 var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
49117                 return object.placeholder;
49118               }
49119               /**
49120                * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
49121                * this function returns the custom method, otherwise it returns `baseIteratee`.
49122                * If arguments are provided, the chosen function is invoked with them and
49123                * its result is returned.
49124                *
49125                * @private
49126                * @param {*} [value] The value to convert to an iteratee.
49127                * @param {number} [arity] The arity of the created iteratee.
49128                * @returns {Function} Returns the chosen function or its result.
49129                */
49130
49131
49132               function getIteratee() {
49133                 var result = lodash.iteratee || iteratee;
49134                 result = result === iteratee ? baseIteratee : result;
49135                 return arguments.length ? result(arguments[0], arguments[1]) : result;
49136               }
49137               /**
49138                * Gets the data for `map`.
49139                *
49140                * @private
49141                * @param {Object} map The map to query.
49142                * @param {string} key The reference key.
49143                * @returns {*} Returns the map data.
49144                */
49145
49146
49147               function getMapData(map, key) {
49148                 var data = map.__data__;
49149                 return isKeyable(key) ? data[typeof key == 'string' ? 'string' : 'hash'] : data.map;
49150               }
49151               /**
49152                * Gets the property names, values, and compare flags of `object`.
49153                *
49154                * @private
49155                * @param {Object} object The object to query.
49156                * @returns {Array} Returns the match data of `object`.
49157                */
49158
49159
49160               function getMatchData(object) {
49161                 var result = keys(object),
49162                     length = result.length;
49163
49164                 while (length--) {
49165                   var key = result[length],
49166                       value = object[key];
49167                   result[length] = [key, value, isStrictComparable(value)];
49168                 }
49169
49170                 return result;
49171               }
49172               /**
49173                * Gets the native function at `key` of `object`.
49174                *
49175                * @private
49176                * @param {Object} object The object to query.
49177                * @param {string} key The key of the method to get.
49178                * @returns {*} Returns the function if it's native, else `undefined`.
49179                */
49180
49181
49182               function getNative(object, key) {
49183                 var value = getValue(object, key);
49184                 return baseIsNative(value) ? value : undefined$1;
49185               }
49186               /**
49187                * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
49188                *
49189                * @private
49190                * @param {*} value The value to query.
49191                * @returns {string} Returns the raw `toStringTag`.
49192                */
49193
49194
49195               function getRawTag(value) {
49196                 var isOwn = hasOwnProperty.call(value, symToStringTag),
49197                     tag = value[symToStringTag];
49198
49199                 try {
49200                   value[symToStringTag] = undefined$1;
49201                   var unmasked = true;
49202                 } catch (e) {}
49203
49204                 var result = nativeObjectToString.call(value);
49205
49206                 if (unmasked) {
49207                   if (isOwn) {
49208                     value[symToStringTag] = tag;
49209                   } else {
49210                     delete value[symToStringTag];
49211                   }
49212                 }
49213
49214                 return result;
49215               }
49216               /**
49217                * Creates an array of the own enumerable symbols of `object`.
49218                *
49219                * @private
49220                * @param {Object} object The object to query.
49221                * @returns {Array} Returns the array of symbols.
49222                */
49223
49224
49225               var getSymbols = !nativeGetSymbols ? stubArray : function (object) {
49226                 if (object == null) {
49227                   return [];
49228                 }
49229
49230                 object = Object(object);
49231                 return arrayFilter(nativeGetSymbols(object), function (symbol) {
49232                   return propertyIsEnumerable.call(object, symbol);
49233                 });
49234               };
49235               /**
49236                * Creates an array of the own and inherited enumerable symbols of `object`.
49237                *
49238                * @private
49239                * @param {Object} object The object to query.
49240                * @returns {Array} Returns the array of symbols.
49241                */
49242
49243               var getSymbolsIn = !nativeGetSymbols ? stubArray : function (object) {
49244                 var result = [];
49245
49246                 while (object) {
49247                   arrayPush(result, getSymbols(object));
49248                   object = getPrototype(object);
49249                 }
49250
49251                 return result;
49252               };
49253               /**
49254                * Gets the `toStringTag` of `value`.
49255                *
49256                * @private
49257                * @param {*} value The value to query.
49258                * @returns {string} Returns the `toStringTag`.
49259                */
49260
49261               var getTag = baseGetTag; // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
49262
49263               if (DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag || Map && getTag(new Map()) != mapTag || Promise && getTag(Promise.resolve()) != promiseTag || Set && getTag(new Set()) != setTag || WeakMap && getTag(new WeakMap()) != weakMapTag) {
49264                 getTag = function getTag(value) {
49265                   var result = baseGetTag(value),
49266                       Ctor = result == objectTag ? value.constructor : undefined$1,
49267                       ctorString = Ctor ? toSource(Ctor) : '';
49268
49269                   if (ctorString) {
49270                     switch (ctorString) {
49271                       case dataViewCtorString:
49272                         return dataViewTag;
49273
49274                       case mapCtorString:
49275                         return mapTag;
49276
49277                       case promiseCtorString:
49278                         return promiseTag;
49279
49280                       case setCtorString:
49281                         return setTag;
49282
49283                       case weakMapCtorString:
49284                         return weakMapTag;
49285                     }
49286                   }
49287
49288                   return result;
49289                 };
49290               }
49291               /**
49292                * Gets the view, applying any `transforms` to the `start` and `end` positions.
49293                *
49294                * @private
49295                * @param {number} start The start of the view.
49296                * @param {number} end The end of the view.
49297                * @param {Array} transforms The transformations to apply to the view.
49298                * @returns {Object} Returns an object containing the `start` and `end`
49299                *  positions of the view.
49300                */
49301
49302
49303               function getView(start, end, transforms) {
49304                 var index = -1,
49305                     length = transforms.length;
49306
49307                 while (++index < length) {
49308                   var data = transforms[index],
49309                       size = data.size;
49310
49311                   switch (data.type) {
49312                     case 'drop':
49313                       start += size;
49314                       break;
49315
49316                     case 'dropRight':
49317                       end -= size;
49318                       break;
49319
49320                     case 'take':
49321                       end = nativeMin(end, start + size);
49322                       break;
49323
49324                     case 'takeRight':
49325                       start = nativeMax(start, end - size);
49326                       break;
49327                   }
49328                 }
49329
49330                 return {
49331                   'start': start,
49332                   'end': end
49333                 };
49334               }
49335               /**
49336                * Extracts wrapper details from the `source` body comment.
49337                *
49338                * @private
49339                * @param {string} source The source to inspect.
49340                * @returns {Array} Returns the wrapper details.
49341                */
49342
49343
49344               function getWrapDetails(source) {
49345                 var match = source.match(reWrapDetails);
49346                 return match ? match[1].split(reSplitDetails) : [];
49347               }
49348               /**
49349                * Checks if `path` exists on `object`.
49350                *
49351                * @private
49352                * @param {Object} object The object to query.
49353                * @param {Array|string} path The path to check.
49354                * @param {Function} hasFunc The function to check properties.
49355                * @returns {boolean} Returns `true` if `path` exists, else `false`.
49356                */
49357
49358
49359               function hasPath(object, path, hasFunc) {
49360                 path = castPath(path, object);
49361                 var index = -1,
49362                     length = path.length,
49363                     result = false;
49364
49365                 while (++index < length) {
49366                   var key = toKey(path[index]);
49367
49368                   if (!(result = object != null && hasFunc(object, key))) {
49369                     break;
49370                   }
49371
49372                   object = object[key];
49373                 }
49374
49375                 if (result || ++index != length) {
49376                   return result;
49377                 }
49378
49379                 length = object == null ? 0 : object.length;
49380                 return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object));
49381               }
49382               /**
49383                * Initializes an array clone.
49384                *
49385                * @private
49386                * @param {Array} array The array to clone.
49387                * @returns {Array} Returns the initialized clone.
49388                */
49389
49390
49391               function initCloneArray(array) {
49392                 var length = array.length,
49393                     result = new array.constructor(length); // Add properties assigned by `RegExp#exec`.
49394
49395                 if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
49396                   result.index = array.index;
49397                   result.input = array.input;
49398                 }
49399
49400                 return result;
49401               }
49402               /**
49403                * Initializes an object clone.
49404                *
49405                * @private
49406                * @param {Object} object The object to clone.
49407                * @returns {Object} Returns the initialized clone.
49408                */
49409
49410
49411               function initCloneObject(object) {
49412                 return typeof object.constructor == 'function' && !isPrototype(object) ? baseCreate(getPrototype(object)) : {};
49413               }
49414               /**
49415                * Initializes an object clone based on its `toStringTag`.
49416                *
49417                * **Note:** This function only supports cloning values with tags of
49418                * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`.
49419                *
49420                * @private
49421                * @param {Object} object The object to clone.
49422                * @param {string} tag The `toStringTag` of the object to clone.
49423                * @param {boolean} [isDeep] Specify a deep clone.
49424                * @returns {Object} Returns the initialized clone.
49425                */
49426
49427
49428               function initCloneByTag(object, tag, isDeep) {
49429                 var Ctor = object.constructor;
49430
49431                 switch (tag) {
49432                   case arrayBufferTag:
49433                     return cloneArrayBuffer(object);
49434
49435                   case boolTag:
49436                   case dateTag:
49437                     return new Ctor(+object);
49438
49439                   case dataViewTag:
49440                     return cloneDataView(object, isDeep);
49441
49442                   case float32Tag:
49443                   case float64Tag:
49444                   case int8Tag:
49445                   case int16Tag:
49446                   case int32Tag:
49447                   case uint8Tag:
49448                   case uint8ClampedTag:
49449                   case uint16Tag:
49450                   case uint32Tag:
49451                     return cloneTypedArray(object, isDeep);
49452
49453                   case mapTag:
49454                     return new Ctor();
49455
49456                   case numberTag:
49457                   case stringTag:
49458                     return new Ctor(object);
49459
49460                   case regexpTag:
49461                     return cloneRegExp(object);
49462
49463                   case setTag:
49464                     return new Ctor();
49465
49466                   case symbolTag:
49467                     return cloneSymbol(object);
49468                 }
49469               }
49470               /**
49471                * Inserts wrapper `details` in a comment at the top of the `source` body.
49472                *
49473                * @private
49474                * @param {string} source The source to modify.
49475                * @returns {Array} details The details to insert.
49476                * @returns {string} Returns the modified source.
49477                */
49478
49479
49480               function insertWrapDetails(source, details) {
49481                 var length = details.length;
49482
49483                 if (!length) {
49484                   return source;
49485                 }
49486
49487                 var lastIndex = length - 1;
49488                 details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
49489                 details = details.join(length > 2 ? ', ' : ' ');
49490                 return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
49491               }
49492               /**
49493                * Checks if `value` is a flattenable `arguments` object or array.
49494                *
49495                * @private
49496                * @param {*} value The value to check.
49497                * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
49498                */
49499
49500
49501               function isFlattenable(value) {
49502                 return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]);
49503               }
49504               /**
49505                * Checks if `value` is a valid array-like index.
49506                *
49507                * @private
49508                * @param {*} value The value to check.
49509                * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
49510                * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
49511                */
49512
49513
49514               function isIndex(value, length) {
49515                 var type = _typeof(value);
49516
49517                 length = length == null ? MAX_SAFE_INTEGER : length;
49518                 return !!length && (type == 'number' || type != 'symbol' && reIsUint.test(value)) && value > -1 && value % 1 == 0 && value < length;
49519               }
49520               /**
49521                * Checks if the given arguments are from an iteratee call.
49522                *
49523                * @private
49524                * @param {*} value The potential iteratee value argument.
49525                * @param {*} index The potential iteratee index or key argument.
49526                * @param {*} object The potential iteratee object argument.
49527                * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
49528                *  else `false`.
49529                */
49530
49531
49532               function isIterateeCall(value, index, object) {
49533                 if (!isObject(object)) {
49534                   return false;
49535                 }
49536
49537                 var type = _typeof(index);
49538
49539                 if (type == 'number' ? isArrayLike(object) && isIndex(index, object.length) : type == 'string' && index in object) {
49540                   return eq(object[index], value);
49541                 }
49542
49543                 return false;
49544               }
49545               /**
49546                * Checks if `value` is a property name and not a property path.
49547                *
49548                * @private
49549                * @param {*} value The value to check.
49550                * @param {Object} [object] The object to query keys on.
49551                * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
49552                */
49553
49554
49555               function isKey(value, object) {
49556                 if (isArray(value)) {
49557                   return false;
49558                 }
49559
49560                 var type = _typeof(value);
49561
49562                 if (type == 'number' || type == 'symbol' || type == 'boolean' || value == null || isSymbol(value)) {
49563                   return true;
49564                 }
49565
49566                 return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object(object);
49567               }
49568               /**
49569                * Checks if `value` is suitable for use as unique object key.
49570                *
49571                * @private
49572                * @param {*} value The value to check.
49573                * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
49574                */
49575
49576
49577               function isKeyable(value) {
49578                 var type = _typeof(value);
49579
49580                 return type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean' ? value !== '__proto__' : value === null;
49581               }
49582               /**
49583                * Checks if `func` has a lazy counterpart.
49584                *
49585                * @private
49586                * @param {Function} func The function to check.
49587                * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
49588                *  else `false`.
49589                */
49590
49591
49592               function isLaziable(func) {
49593                 var funcName = getFuncName(func),
49594                     other = lodash[funcName];
49595
49596                 if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
49597                   return false;
49598                 }
49599
49600                 if (func === other) {
49601                   return true;
49602                 }
49603
49604                 var data = getData(other);
49605                 return !!data && func === data[0];
49606               }
49607               /**
49608                * Checks if `func` has its source masked.
49609                *
49610                * @private
49611                * @param {Function} func The function to check.
49612                * @returns {boolean} Returns `true` if `func` is masked, else `false`.
49613                */
49614
49615
49616               function isMasked(func) {
49617                 return !!maskSrcKey && maskSrcKey in func;
49618               }
49619               /**
49620                * Checks if `func` is capable of being masked.
49621                *
49622                * @private
49623                * @param {*} value The value to check.
49624                * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
49625                */
49626
49627
49628               var isMaskable = coreJsData ? isFunction : stubFalse;
49629               /**
49630                * Checks if `value` is likely a prototype object.
49631                *
49632                * @private
49633                * @param {*} value The value to check.
49634                * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
49635                */
49636
49637               function isPrototype(value) {
49638                 var Ctor = value && value.constructor,
49639                     proto = typeof Ctor == 'function' && Ctor.prototype || objectProto;
49640                 return value === proto;
49641               }
49642               /**
49643                * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
49644                *
49645                * @private
49646                * @param {*} value The value to check.
49647                * @returns {boolean} Returns `true` if `value` if suitable for strict
49648                *  equality comparisons, else `false`.
49649                */
49650
49651
49652               function isStrictComparable(value) {
49653                 return value === value && !isObject(value);
49654               }
49655               /**
49656                * A specialized version of `matchesProperty` for source values suitable
49657                * for strict equality comparisons, i.e. `===`.
49658                *
49659                * @private
49660                * @param {string} key The key of the property to get.
49661                * @param {*} srcValue The value to match.
49662                * @returns {Function} Returns the new spec function.
49663                */
49664
49665
49666               function matchesStrictComparable(key, srcValue) {
49667                 return function (object) {
49668                   if (object == null) {
49669                     return false;
49670                   }
49671
49672                   return object[key] === srcValue && (srcValue !== undefined$1 || key in Object(object));
49673                 };
49674               }
49675               /**
49676                * A specialized version of `_.memoize` which clears the memoized function's
49677                * cache when it exceeds `MAX_MEMOIZE_SIZE`.
49678                *
49679                * @private
49680                * @param {Function} func The function to have its output memoized.
49681                * @returns {Function} Returns the new memoized function.
49682                */
49683
49684
49685               function memoizeCapped(func) {
49686                 var result = memoize(func, function (key) {
49687                   if (cache.size === MAX_MEMOIZE_SIZE) {
49688                     cache.clear();
49689                   }
49690
49691                   return key;
49692                 });
49693                 var cache = result.cache;
49694                 return result;
49695               }
49696               /**
49697                * Merges the function metadata of `source` into `data`.
49698                *
49699                * Merging metadata reduces the number of wrappers used to invoke a function.
49700                * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
49701                * may be applied regardless of execution order. Methods like `_.ary` and
49702                * `_.rearg` modify function arguments, making the order in which they are
49703                * executed important, preventing the merging of metadata. However, we make
49704                * an exception for a safe combined case where curried functions have `_.ary`
49705                * and or `_.rearg` applied.
49706                *
49707                * @private
49708                * @param {Array} data The destination metadata.
49709                * @param {Array} source The source metadata.
49710                * @returns {Array} Returns `data`.
49711                */
49712
49713
49714               function mergeData(data, source) {
49715                 var bitmask = data[1],
49716                     srcBitmask = source[1],
49717                     newBitmask = bitmask | srcBitmask,
49718                     isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
49719                 var isCombo = srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_CURRY_FLAG || srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_REARG_FLAG && data[7].length <= source[8] || srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG) && source[7].length <= source[8] && bitmask == WRAP_CURRY_FLAG; // Exit early if metadata can't be merged.
49720
49721                 if (!(isCommon || isCombo)) {
49722                   return data;
49723                 } // Use source `thisArg` if available.
49724
49725
49726                 if (srcBitmask & WRAP_BIND_FLAG) {
49727                   data[2] = source[2]; // Set when currying a bound function.
49728
49729                   newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
49730                 } // Compose partial arguments.
49731
49732
49733                 var value = source[3];
49734
49735                 if (value) {
49736                   var partials = data[3];
49737                   data[3] = partials ? composeArgs(partials, value, source[4]) : value;
49738                   data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
49739                 } // Compose partial right arguments.
49740
49741
49742                 value = source[5];
49743
49744                 if (value) {
49745                   partials = data[5];
49746                   data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
49747                   data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
49748                 } // Use source `argPos` if available.
49749
49750
49751                 value = source[7];
49752
49753                 if (value) {
49754                   data[7] = value;
49755                 } // Use source `ary` if it's smaller.
49756
49757
49758                 if (srcBitmask & WRAP_ARY_FLAG) {
49759                   data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
49760                 } // Use source `arity` if one is not provided.
49761
49762
49763                 if (data[9] == null) {
49764                   data[9] = source[9];
49765                 } // Use source `func` and merge bitmasks.
49766
49767
49768                 data[0] = source[0];
49769                 data[1] = newBitmask;
49770                 return data;
49771               }
49772               /**
49773                * This function is like
49774                * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
49775                * except that it includes inherited enumerable properties.
49776                *
49777                * @private
49778                * @param {Object} object The object to query.
49779                * @returns {Array} Returns the array of property names.
49780                */
49781
49782
49783               function nativeKeysIn(object) {
49784                 var result = [];
49785
49786                 if (object != null) {
49787                   for (var key in Object(object)) {
49788                     result.push(key);
49789                   }
49790                 }
49791
49792                 return result;
49793               }
49794               /**
49795                * Converts `value` to a string using `Object.prototype.toString`.
49796                *
49797                * @private
49798                * @param {*} value The value to convert.
49799                * @returns {string} Returns the converted string.
49800                */
49801
49802
49803               function objectToString(value) {
49804                 return nativeObjectToString.call(value);
49805               }
49806               /**
49807                * A specialized version of `baseRest` which transforms the rest array.
49808                *
49809                * @private
49810                * @param {Function} func The function to apply a rest parameter to.
49811                * @param {number} [start=func.length-1] The start position of the rest parameter.
49812                * @param {Function} transform The rest array transform.
49813                * @returns {Function} Returns the new function.
49814                */
49815
49816
49817               function overRest(func, start, transform) {
49818                 start = nativeMax(start === undefined$1 ? func.length - 1 : start, 0);
49819                 return function () {
49820                   var args = arguments,
49821                       index = -1,
49822                       length = nativeMax(args.length - start, 0),
49823                       array = Array(length);
49824
49825                   while (++index < length) {
49826                     array[index] = args[start + index];
49827                   }
49828
49829                   index = -1;
49830                   var otherArgs = Array(start + 1);
49831
49832                   while (++index < start) {
49833                     otherArgs[index] = args[index];
49834                   }
49835
49836                   otherArgs[start] = transform(array);
49837                   return apply(func, this, otherArgs);
49838                 };
49839               }
49840               /**
49841                * Gets the parent value at `path` of `object`.
49842                *
49843                * @private
49844                * @param {Object} object The object to query.
49845                * @param {Array} path The path to get the parent value of.
49846                * @returns {*} Returns the parent value.
49847                */
49848
49849
49850               function parent(object, path) {
49851                 return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
49852               }
49853               /**
49854                * Reorder `array` according to the specified indexes where the element at
49855                * the first index is assigned as the first element, the element at
49856                * the second index is assigned as the second element, and so on.
49857                *
49858                * @private
49859                * @param {Array} array The array to reorder.
49860                * @param {Array} indexes The arranged array indexes.
49861                * @returns {Array} Returns `array`.
49862                */
49863
49864
49865               function reorder(array, indexes) {
49866                 var arrLength = array.length,
49867                     length = nativeMin(indexes.length, arrLength),
49868                     oldArray = copyArray(array);
49869
49870                 while (length--) {
49871                   var index = indexes[length];
49872                   array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined$1;
49873                 }
49874
49875                 return array;
49876               }
49877               /**
49878                * Gets the value at `key`, unless `key` is "__proto__" or "constructor".
49879                *
49880                * @private
49881                * @param {Object} object The object to query.
49882                * @param {string} key The key of the property to get.
49883                * @returns {*} Returns the property value.
49884                */
49885
49886
49887               function safeGet(object, key) {
49888                 if (key === 'constructor' && typeof object[key] === 'function') {
49889                   return;
49890                 }
49891
49892                 if (key == '__proto__') {
49893                   return;
49894                 }
49895
49896                 return object[key];
49897               }
49898               /**
49899                * Sets metadata for `func`.
49900                *
49901                * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
49902                * period of time, it will trip its breaker and transition to an identity
49903                * function to avoid garbage collection pauses in V8. See
49904                * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
49905                * for more details.
49906                *
49907                * @private
49908                * @param {Function} func The function to associate metadata with.
49909                * @param {*} data The metadata.
49910                * @returns {Function} Returns `func`.
49911                */
49912
49913
49914               var setData = shortOut(baseSetData);
49915               /**
49916                * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
49917                *
49918                * @private
49919                * @param {Function} func The function to delay.
49920                * @param {number} wait The number of milliseconds to delay invocation.
49921                * @returns {number|Object} Returns the timer id or timeout object.
49922                */
49923
49924               var setTimeout = ctxSetTimeout || function (func, wait) {
49925                 return root.setTimeout(func, wait);
49926               };
49927               /**
49928                * Sets the `toString` method of `func` to return `string`.
49929                *
49930                * @private
49931                * @param {Function} func The function to modify.
49932                * @param {Function} string The `toString` result.
49933                * @returns {Function} Returns `func`.
49934                */
49935
49936
49937               var setToString = shortOut(baseSetToString);
49938               /**
49939                * Sets the `toString` method of `wrapper` to mimic the source of `reference`
49940                * with wrapper details in a comment at the top of the source body.
49941                *
49942                * @private
49943                * @param {Function} wrapper The function to modify.
49944                * @param {Function} reference The reference function.
49945                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
49946                * @returns {Function} Returns `wrapper`.
49947                */
49948
49949               function setWrapToString(wrapper, reference, bitmask) {
49950                 var source = reference + '';
49951                 return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
49952               }
49953               /**
49954                * Creates a function that'll short out and invoke `identity` instead
49955                * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
49956                * milliseconds.
49957                *
49958                * @private
49959                * @param {Function} func The function to restrict.
49960                * @returns {Function} Returns the new shortable function.
49961                */
49962
49963
49964               function shortOut(func) {
49965                 var count = 0,
49966                     lastCalled = 0;
49967                 return function () {
49968                   var stamp = nativeNow(),
49969                       remaining = HOT_SPAN - (stamp - lastCalled);
49970                   lastCalled = stamp;
49971
49972                   if (remaining > 0) {
49973                     if (++count >= HOT_COUNT) {
49974                       return arguments[0];
49975                     }
49976                   } else {
49977                     count = 0;
49978                   }
49979
49980                   return func.apply(undefined$1, arguments);
49981                 };
49982               }
49983               /**
49984                * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
49985                *
49986                * @private
49987                * @param {Array} array The array to shuffle.
49988                * @param {number} [size=array.length] The size of `array`.
49989                * @returns {Array} Returns `array`.
49990                */
49991
49992
49993               function shuffleSelf(array, size) {
49994                 var index = -1,
49995                     length = array.length,
49996                     lastIndex = length - 1;
49997                 size = size === undefined$1 ? length : size;
49998
49999                 while (++index < size) {
50000                   var rand = baseRandom(index, lastIndex),
50001                       value = array[rand];
50002                   array[rand] = array[index];
50003                   array[index] = value;
50004                 }
50005
50006                 array.length = size;
50007                 return array;
50008               }
50009               /**
50010                * Converts `string` to a property path array.
50011                *
50012                * @private
50013                * @param {string} string The string to convert.
50014                * @returns {Array} Returns the property path array.
50015                */
50016
50017
50018               var stringToPath = memoizeCapped(function (string) {
50019                 var result = [];
50020
50021                 if (string.charCodeAt(0) === 46
50022                 /* . */
50023                 ) {
50024                   result.push('');
50025                 }
50026
50027                 string.replace(rePropName, function (match, number, quote, subString) {
50028                   result.push(quote ? subString.replace(reEscapeChar, '$1') : number || match);
50029                 });
50030                 return result;
50031               });
50032               /**
50033                * Converts `value` to a string key if it's not a string or symbol.
50034                *
50035                * @private
50036                * @param {*} value The value to inspect.
50037                * @returns {string|symbol} Returns the key.
50038                */
50039
50040               function toKey(value) {
50041                 if (typeof value == 'string' || isSymbol(value)) {
50042                   return value;
50043                 }
50044
50045                 var result = value + '';
50046                 return result == '0' && 1 / value == -INFINITY ? '-0' : result;
50047               }
50048               /**
50049                * Converts `func` to its source code.
50050                *
50051                * @private
50052                * @param {Function} func The function to convert.
50053                * @returns {string} Returns the source code.
50054                */
50055
50056
50057               function toSource(func) {
50058                 if (func != null) {
50059                   try {
50060                     return funcToString.call(func);
50061                   } catch (e) {}
50062
50063                   try {
50064                     return func + '';
50065                   } catch (e) {}
50066                 }
50067
50068                 return '';
50069               }
50070               /**
50071                * Updates wrapper `details` based on `bitmask` flags.
50072                *
50073                * @private
50074                * @returns {Array} details The details to modify.
50075                * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
50076                * @returns {Array} Returns `details`.
50077                */
50078
50079
50080               function updateWrapDetails(details, bitmask) {
50081                 arrayEach(wrapFlags, function (pair) {
50082                   var value = '_.' + pair[0];
50083
50084                   if (bitmask & pair[1] && !arrayIncludes(details, value)) {
50085                     details.push(value);
50086                   }
50087                 });
50088                 return details.sort();
50089               }
50090               /**
50091                * Creates a clone of `wrapper`.
50092                *
50093                * @private
50094                * @param {Object} wrapper The wrapper to clone.
50095                * @returns {Object} Returns the cloned wrapper.
50096                */
50097
50098
50099               function wrapperClone(wrapper) {
50100                 if (wrapper instanceof LazyWrapper) {
50101                   return wrapper.clone();
50102                 }
50103
50104                 var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
50105                 result.__actions__ = copyArray(wrapper.__actions__);
50106                 result.__index__ = wrapper.__index__;
50107                 result.__values__ = wrapper.__values__;
50108                 return result;
50109               }
50110               /*------------------------------------------------------------------------*/
50111
50112               /**
50113                * Creates an array of elements split into groups the length of `size`.
50114                * If `array` can't be split evenly, the final chunk will be the remaining
50115                * elements.
50116                *
50117                * @static
50118                * @memberOf _
50119                * @since 3.0.0
50120                * @category Array
50121                * @param {Array} array The array to process.
50122                * @param {number} [size=1] The length of each chunk
50123                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
50124                * @returns {Array} Returns the new array of chunks.
50125                * @example
50126                *
50127                * _.chunk(['a', 'b', 'c', 'd'], 2);
50128                * // => [['a', 'b'], ['c', 'd']]
50129                *
50130                * _.chunk(['a', 'b', 'c', 'd'], 3);
50131                * // => [['a', 'b', 'c'], ['d']]
50132                */
50133
50134
50135               function chunk(array, size, guard) {
50136                 if (guard ? isIterateeCall(array, size, guard) : size === undefined$1) {
50137                   size = 1;
50138                 } else {
50139                   size = nativeMax(toInteger(size), 0);
50140                 }
50141
50142                 var length = array == null ? 0 : array.length;
50143
50144                 if (!length || size < 1) {
50145                   return [];
50146                 }
50147
50148                 var index = 0,
50149                     resIndex = 0,
50150                     result = Array(nativeCeil(length / size));
50151
50152                 while (index < length) {
50153                   result[resIndex++] = baseSlice(array, index, index += size);
50154                 }
50155
50156                 return result;
50157               }
50158               /**
50159                * Creates an array with all falsey values removed. The values `false`, `null`,
50160                * `0`, `""`, `undefined`, and `NaN` are falsey.
50161                *
50162                * @static
50163                * @memberOf _
50164                * @since 0.1.0
50165                * @category Array
50166                * @param {Array} array The array to compact.
50167                * @returns {Array} Returns the new array of filtered values.
50168                * @example
50169                *
50170                * _.compact([0, 1, false, 2, '', 3]);
50171                * // => [1, 2, 3]
50172                */
50173
50174
50175               function compact(array) {
50176                 var index = -1,
50177                     length = array == null ? 0 : array.length,
50178                     resIndex = 0,
50179                     result = [];
50180
50181                 while (++index < length) {
50182                   var value = array[index];
50183
50184                   if (value) {
50185                     result[resIndex++] = value;
50186                   }
50187                 }
50188
50189                 return result;
50190               }
50191               /**
50192                * Creates a new array concatenating `array` with any additional arrays
50193                * and/or values.
50194                *
50195                * @static
50196                * @memberOf _
50197                * @since 4.0.0
50198                * @category Array
50199                * @param {Array} array The array to concatenate.
50200                * @param {...*} [values] The values to concatenate.
50201                * @returns {Array} Returns the new concatenated array.
50202                * @example
50203                *
50204                * var array = [1];
50205                * var other = _.concat(array, 2, [3], [[4]]);
50206                *
50207                * console.log(other);
50208                * // => [1, 2, 3, [4]]
50209                *
50210                * console.log(array);
50211                * // => [1]
50212                */
50213
50214
50215               function concat() {
50216                 var length = arguments.length;
50217
50218                 if (!length) {
50219                   return [];
50220                 }
50221
50222                 var args = Array(length - 1),
50223                     array = arguments[0],
50224                     index = length;
50225
50226                 while (index--) {
50227                   args[index - 1] = arguments[index];
50228                 }
50229
50230                 return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
50231               }
50232               /**
50233                * Creates an array of `array` values not included in the other given arrays
50234                * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
50235                * for equality comparisons. The order and references of result values are
50236                * determined by the first array.
50237                *
50238                * **Note:** Unlike `_.pullAll`, this method returns a new array.
50239                *
50240                * @static
50241                * @memberOf _
50242                * @since 0.1.0
50243                * @category Array
50244                * @param {Array} array The array to inspect.
50245                * @param {...Array} [values] The values to exclude.
50246                * @returns {Array} Returns the new array of filtered values.
50247                * @see _.without, _.xor
50248                * @example
50249                *
50250                * _.difference([2, 1], [2, 3]);
50251                * // => [1]
50252                */
50253
50254
50255               var difference = baseRest(function (array, values) {
50256                 return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) : [];
50257               });
50258               /**
50259                * This method is like `_.difference` except that it accepts `iteratee` which
50260                * is invoked for each element of `array` and `values` to generate the criterion
50261                * by which they're compared. The order and references of result values are
50262                * determined by the first array. The iteratee is invoked with one argument:
50263                * (value).
50264                *
50265                * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
50266                *
50267                * @static
50268                * @memberOf _
50269                * @since 4.0.0
50270                * @category Array
50271                * @param {Array} array The array to inspect.
50272                * @param {...Array} [values] The values to exclude.
50273                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
50274                * @returns {Array} Returns the new array of filtered values.
50275                * @example
50276                *
50277                * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
50278                * // => [1.2]
50279                *
50280                * // The `_.property` iteratee shorthand.
50281                * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
50282                * // => [{ 'x': 2 }]
50283                */
50284
50285               var differenceBy = baseRest(function (array, values) {
50286                 var iteratee = last(values);
50287
50288                 if (isArrayLikeObject(iteratee)) {
50289                   iteratee = undefined$1;
50290                 }
50291
50292                 return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) : [];
50293               });
50294               /**
50295                * This method is like `_.difference` except that it accepts `comparator`
50296                * which is invoked to compare elements of `array` to `values`. The order and
50297                * references of result values are determined by the first array. The comparator
50298                * is invoked with two arguments: (arrVal, othVal).
50299                *
50300                * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
50301                *
50302                * @static
50303                * @memberOf _
50304                * @since 4.0.0
50305                * @category Array
50306                * @param {Array} array The array to inspect.
50307                * @param {...Array} [values] The values to exclude.
50308                * @param {Function} [comparator] The comparator invoked per element.
50309                * @returns {Array} Returns the new array of filtered values.
50310                * @example
50311                *
50312                * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
50313                *
50314                * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
50315                * // => [{ 'x': 2, 'y': 1 }]
50316                */
50317
50318               var differenceWith = baseRest(function (array, values) {
50319                 var comparator = last(values);
50320
50321                 if (isArrayLikeObject(comparator)) {
50322                   comparator = undefined$1;
50323                 }
50324
50325                 return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined$1, comparator) : [];
50326               });
50327               /**
50328                * Creates a slice of `array` with `n` elements dropped from the beginning.
50329                *
50330                * @static
50331                * @memberOf _
50332                * @since 0.5.0
50333                * @category Array
50334                * @param {Array} array The array to query.
50335                * @param {number} [n=1] The number of elements to drop.
50336                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
50337                * @returns {Array} Returns the slice of `array`.
50338                * @example
50339                *
50340                * _.drop([1, 2, 3]);
50341                * // => [2, 3]
50342                *
50343                * _.drop([1, 2, 3], 2);
50344                * // => [3]
50345                *
50346                * _.drop([1, 2, 3], 5);
50347                * // => []
50348                *
50349                * _.drop([1, 2, 3], 0);
50350                * // => [1, 2, 3]
50351                */
50352
50353               function drop(array, n, guard) {
50354                 var length = array == null ? 0 : array.length;
50355
50356                 if (!length) {
50357                   return [];
50358                 }
50359
50360                 n = guard || n === undefined$1 ? 1 : toInteger(n);
50361                 return baseSlice(array, n < 0 ? 0 : n, length);
50362               }
50363               /**
50364                * Creates a slice of `array` with `n` elements dropped from the end.
50365                *
50366                * @static
50367                * @memberOf _
50368                * @since 3.0.0
50369                * @category Array
50370                * @param {Array} array The array to query.
50371                * @param {number} [n=1] The number of elements to drop.
50372                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
50373                * @returns {Array} Returns the slice of `array`.
50374                * @example
50375                *
50376                * _.dropRight([1, 2, 3]);
50377                * // => [1, 2]
50378                *
50379                * _.dropRight([1, 2, 3], 2);
50380                * // => [1]
50381                *
50382                * _.dropRight([1, 2, 3], 5);
50383                * // => []
50384                *
50385                * _.dropRight([1, 2, 3], 0);
50386                * // => [1, 2, 3]
50387                */
50388
50389
50390               function dropRight(array, n, guard) {
50391                 var length = array == null ? 0 : array.length;
50392
50393                 if (!length) {
50394                   return [];
50395                 }
50396
50397                 n = guard || n === undefined$1 ? 1 : toInteger(n);
50398                 n = length - n;
50399                 return baseSlice(array, 0, n < 0 ? 0 : n);
50400               }
50401               /**
50402                * Creates a slice of `array` excluding elements dropped from the end.
50403                * Elements are dropped until `predicate` returns falsey. The predicate is
50404                * invoked with three arguments: (value, index, array).
50405                *
50406                * @static
50407                * @memberOf _
50408                * @since 3.0.0
50409                * @category Array
50410                * @param {Array} array The array to query.
50411                * @param {Function} [predicate=_.identity] The function invoked per iteration.
50412                * @returns {Array} Returns the slice of `array`.
50413                * @example
50414                *
50415                * var users = [
50416                *   { 'user': 'barney',  'active': true },
50417                *   { 'user': 'fred',    'active': false },
50418                *   { 'user': 'pebbles', 'active': false }
50419                * ];
50420                *
50421                * _.dropRightWhile(users, function(o) { return !o.active; });
50422                * // => objects for ['barney']
50423                *
50424                * // The `_.matches` iteratee shorthand.
50425                * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
50426                * // => objects for ['barney', 'fred']
50427                *
50428                * // The `_.matchesProperty` iteratee shorthand.
50429                * _.dropRightWhile(users, ['active', false]);
50430                * // => objects for ['barney']
50431                *
50432                * // The `_.property` iteratee shorthand.
50433                * _.dropRightWhile(users, 'active');
50434                * // => objects for ['barney', 'fred', 'pebbles']
50435                */
50436
50437
50438               function dropRightWhile(array, predicate) {
50439                 return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true, true) : [];
50440               }
50441               /**
50442                * Creates a slice of `array` excluding elements dropped from the beginning.
50443                * Elements are dropped until `predicate` returns falsey. The predicate is
50444                * invoked with three arguments: (value, index, array).
50445                *
50446                * @static
50447                * @memberOf _
50448                * @since 3.0.0
50449                * @category Array
50450                * @param {Array} array The array to query.
50451                * @param {Function} [predicate=_.identity] The function invoked per iteration.
50452                * @returns {Array} Returns the slice of `array`.
50453                * @example
50454                *
50455                * var users = [
50456                *   { 'user': 'barney',  'active': false },
50457                *   { 'user': 'fred',    'active': false },
50458                *   { 'user': 'pebbles', 'active': true }
50459                * ];
50460                *
50461                * _.dropWhile(users, function(o) { return !o.active; });
50462                * // => objects for ['pebbles']
50463                *
50464                * // The `_.matches` iteratee shorthand.
50465                * _.dropWhile(users, { 'user': 'barney', 'active': false });
50466                * // => objects for ['fred', 'pebbles']
50467                *
50468                * // The `_.matchesProperty` iteratee shorthand.
50469                * _.dropWhile(users, ['active', false]);
50470                * // => objects for ['pebbles']
50471                *
50472                * // The `_.property` iteratee shorthand.
50473                * _.dropWhile(users, 'active');
50474                * // => objects for ['barney', 'fred', 'pebbles']
50475                */
50476
50477
50478               function dropWhile(array, predicate) {
50479                 return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true) : [];
50480               }
50481               /**
50482                * Fills elements of `array` with `value` from `start` up to, but not
50483                * including, `end`.
50484                *
50485                * **Note:** This method mutates `array`.
50486                *
50487                * @static
50488                * @memberOf _
50489                * @since 3.2.0
50490                * @category Array
50491                * @param {Array} array The array to fill.
50492                * @param {*} value The value to fill `array` with.
50493                * @param {number} [start=0] The start position.
50494                * @param {number} [end=array.length] The end position.
50495                * @returns {Array} Returns `array`.
50496                * @example
50497                *
50498                * var array = [1, 2, 3];
50499                *
50500                * _.fill(array, 'a');
50501                * console.log(array);
50502                * // => ['a', 'a', 'a']
50503                *
50504                * _.fill(Array(3), 2);
50505                * // => [2, 2, 2]
50506                *
50507                * _.fill([4, 6, 8, 10], '*', 1, 3);
50508                * // => [4, '*', '*', 10]
50509                */
50510
50511
50512               function fill(array, value, start, end) {
50513                 var length = array == null ? 0 : array.length;
50514
50515                 if (!length) {
50516                   return [];
50517                 }
50518
50519                 if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
50520                   start = 0;
50521                   end = length;
50522                 }
50523
50524                 return baseFill(array, value, start, end);
50525               }
50526               /**
50527                * This method is like `_.find` except that it returns the index of the first
50528                * element `predicate` returns truthy for instead of the element itself.
50529                *
50530                * @static
50531                * @memberOf _
50532                * @since 1.1.0
50533                * @category Array
50534                * @param {Array} array The array to inspect.
50535                * @param {Function} [predicate=_.identity] The function invoked per iteration.
50536                * @param {number} [fromIndex=0] The index to search from.
50537                * @returns {number} Returns the index of the found element, else `-1`.
50538                * @example
50539                *
50540                * var users = [
50541                *   { 'user': 'barney',  'active': false },
50542                *   { 'user': 'fred',    'active': false },
50543                *   { 'user': 'pebbles', 'active': true }
50544                * ];
50545                *
50546                * _.findIndex(users, function(o) { return o.user == 'barney'; });
50547                * // => 0
50548                *
50549                * // The `_.matches` iteratee shorthand.
50550                * _.findIndex(users, { 'user': 'fred', 'active': false });
50551                * // => 1
50552                *
50553                * // The `_.matchesProperty` iteratee shorthand.
50554                * _.findIndex(users, ['active', false]);
50555                * // => 0
50556                *
50557                * // The `_.property` iteratee shorthand.
50558                * _.findIndex(users, 'active');
50559                * // => 2
50560                */
50561
50562
50563               function findIndex(array, predicate, fromIndex) {
50564                 var length = array == null ? 0 : array.length;
50565
50566                 if (!length) {
50567                   return -1;
50568                 }
50569
50570                 var index = fromIndex == null ? 0 : toInteger(fromIndex);
50571
50572                 if (index < 0) {
50573                   index = nativeMax(length + index, 0);
50574                 }
50575
50576                 return baseFindIndex(array, getIteratee(predicate, 3), index);
50577               }
50578               /**
50579                * This method is like `_.findIndex` except that it iterates over elements
50580                * of `collection` from right to left.
50581                *
50582                * @static
50583                * @memberOf _
50584                * @since 2.0.0
50585                * @category Array
50586                * @param {Array} array The array to inspect.
50587                * @param {Function} [predicate=_.identity] The function invoked per iteration.
50588                * @param {number} [fromIndex=array.length-1] The index to search from.
50589                * @returns {number} Returns the index of the found element, else `-1`.
50590                * @example
50591                *
50592                * var users = [
50593                *   { 'user': 'barney',  'active': true },
50594                *   { 'user': 'fred',    'active': false },
50595                *   { 'user': 'pebbles', 'active': false }
50596                * ];
50597                *
50598                * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
50599                * // => 2
50600                *
50601                * // The `_.matches` iteratee shorthand.
50602                * _.findLastIndex(users, { 'user': 'barney', 'active': true });
50603                * // => 0
50604                *
50605                * // The `_.matchesProperty` iteratee shorthand.
50606                * _.findLastIndex(users, ['active', false]);
50607                * // => 2
50608                *
50609                * // The `_.property` iteratee shorthand.
50610                * _.findLastIndex(users, 'active');
50611                * // => 0
50612                */
50613
50614
50615               function findLastIndex(array, predicate, fromIndex) {
50616                 var length = array == null ? 0 : array.length;
50617
50618                 if (!length) {
50619                   return -1;
50620                 }
50621
50622                 var index = length - 1;
50623
50624                 if (fromIndex !== undefined$1) {
50625                   index = toInteger(fromIndex);
50626                   index = fromIndex < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
50627                 }
50628
50629                 return baseFindIndex(array, getIteratee(predicate, 3), index, true);
50630               }
50631               /**
50632                * Flattens `array` a single level deep.
50633                *
50634                * @static
50635                * @memberOf _
50636                * @since 0.1.0
50637                * @category Array
50638                * @param {Array} array The array to flatten.
50639                * @returns {Array} Returns the new flattened array.
50640                * @example
50641                *
50642                * _.flatten([1, [2, [3, [4]], 5]]);
50643                * // => [1, 2, [3, [4]], 5]
50644                */
50645
50646
50647               function flatten(array) {
50648                 var length = array == null ? 0 : array.length;
50649                 return length ? baseFlatten(array, 1) : [];
50650               }
50651               /**
50652                * Recursively flattens `array`.
50653                *
50654                * @static
50655                * @memberOf _
50656                * @since 3.0.0
50657                * @category Array
50658                * @param {Array} array The array to flatten.
50659                * @returns {Array} Returns the new flattened array.
50660                * @example
50661                *
50662                * _.flattenDeep([1, [2, [3, [4]], 5]]);
50663                * // => [1, 2, 3, 4, 5]
50664                */
50665
50666
50667               function flattenDeep(array) {
50668                 var length = array == null ? 0 : array.length;
50669                 return length ? baseFlatten(array, INFINITY) : [];
50670               }
50671               /**
50672                * Recursively flatten `array` up to `depth` times.
50673                *
50674                * @static
50675                * @memberOf _
50676                * @since 4.4.0
50677                * @category Array
50678                * @param {Array} array The array to flatten.
50679                * @param {number} [depth=1] The maximum recursion depth.
50680                * @returns {Array} Returns the new flattened array.
50681                * @example
50682                *
50683                * var array = [1, [2, [3, [4]], 5]];
50684                *
50685                * _.flattenDepth(array, 1);
50686                * // => [1, 2, [3, [4]], 5]
50687                *
50688                * _.flattenDepth(array, 2);
50689                * // => [1, 2, 3, [4], 5]
50690                */
50691
50692
50693               function flattenDepth(array, depth) {
50694                 var length = array == null ? 0 : array.length;
50695
50696                 if (!length) {
50697                   return [];
50698                 }
50699
50700                 depth = depth === undefined$1 ? 1 : toInteger(depth);
50701                 return baseFlatten(array, depth);
50702               }
50703               /**
50704                * The inverse of `_.toPairs`; this method returns an object composed
50705                * from key-value `pairs`.
50706                *
50707                * @static
50708                * @memberOf _
50709                * @since 4.0.0
50710                * @category Array
50711                * @param {Array} pairs The key-value pairs.
50712                * @returns {Object} Returns the new object.
50713                * @example
50714                *
50715                * _.fromPairs([['a', 1], ['b', 2]]);
50716                * // => { 'a': 1, 'b': 2 }
50717                */
50718
50719
50720               function fromPairs(pairs) {
50721                 var index = -1,
50722                     length = pairs == null ? 0 : pairs.length,
50723                     result = {};
50724
50725                 while (++index < length) {
50726                   var pair = pairs[index];
50727                   result[pair[0]] = pair[1];
50728                 }
50729
50730                 return result;
50731               }
50732               /**
50733                * Gets the first element of `array`.
50734                *
50735                * @static
50736                * @memberOf _
50737                * @since 0.1.0
50738                * @alias first
50739                * @category Array
50740                * @param {Array} array The array to query.
50741                * @returns {*} Returns the first element of `array`.
50742                * @example
50743                *
50744                * _.head([1, 2, 3]);
50745                * // => 1
50746                *
50747                * _.head([]);
50748                * // => undefined
50749                */
50750
50751
50752               function head(array) {
50753                 return array && array.length ? array[0] : undefined$1;
50754               }
50755               /**
50756                * Gets the index at which the first occurrence of `value` is found in `array`
50757                * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
50758                * for equality comparisons. If `fromIndex` is negative, it's used as the
50759                * offset from the end of `array`.
50760                *
50761                * @static
50762                * @memberOf _
50763                * @since 0.1.0
50764                * @category Array
50765                * @param {Array} array The array to inspect.
50766                * @param {*} value The value to search for.
50767                * @param {number} [fromIndex=0] The index to search from.
50768                * @returns {number} Returns the index of the matched value, else `-1`.
50769                * @example
50770                *
50771                * _.indexOf([1, 2, 1, 2], 2);
50772                * // => 1
50773                *
50774                * // Search from the `fromIndex`.
50775                * _.indexOf([1, 2, 1, 2], 2, 2);
50776                * // => 3
50777                */
50778
50779
50780               function indexOf(array, value, fromIndex) {
50781                 var length = array == null ? 0 : array.length;
50782
50783                 if (!length) {
50784                   return -1;
50785                 }
50786
50787                 var index = fromIndex == null ? 0 : toInteger(fromIndex);
50788
50789                 if (index < 0) {
50790                   index = nativeMax(length + index, 0);
50791                 }
50792
50793                 return baseIndexOf(array, value, index);
50794               }
50795               /**
50796                * Gets all but the last element of `array`.
50797                *
50798                * @static
50799                * @memberOf _
50800                * @since 0.1.0
50801                * @category Array
50802                * @param {Array} array The array to query.
50803                * @returns {Array} Returns the slice of `array`.
50804                * @example
50805                *
50806                * _.initial([1, 2, 3]);
50807                * // => [1, 2]
50808                */
50809
50810
50811               function initial(array) {
50812                 var length = array == null ? 0 : array.length;
50813                 return length ? baseSlice(array, 0, -1) : [];
50814               }
50815               /**
50816                * Creates an array of unique values that are included in all given arrays
50817                * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
50818                * for equality comparisons. The order and references of result values are
50819                * determined by the first array.
50820                *
50821                * @static
50822                * @memberOf _
50823                * @since 0.1.0
50824                * @category Array
50825                * @param {...Array} [arrays] The arrays to inspect.
50826                * @returns {Array} Returns the new array of intersecting values.
50827                * @example
50828                *
50829                * _.intersection([2, 1], [2, 3]);
50830                * // => [2]
50831                */
50832
50833
50834               var intersection = baseRest(function (arrays) {
50835                 var mapped = arrayMap(arrays, castArrayLikeObject);
50836                 return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : [];
50837               });
50838               /**
50839                * This method is like `_.intersection` except that it accepts `iteratee`
50840                * which is invoked for each element of each `arrays` to generate the criterion
50841                * by which they're compared. The order and references of result values are
50842                * determined by the first array. The iteratee is invoked with one argument:
50843                * (value).
50844                *
50845                * @static
50846                * @memberOf _
50847                * @since 4.0.0
50848                * @category Array
50849                * @param {...Array} [arrays] The arrays to inspect.
50850                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
50851                * @returns {Array} Returns the new array of intersecting values.
50852                * @example
50853                *
50854                * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
50855                * // => [2.1]
50856                *
50857                * // The `_.property` iteratee shorthand.
50858                * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
50859                * // => [{ 'x': 1 }]
50860                */
50861
50862               var intersectionBy = baseRest(function (arrays) {
50863                 var iteratee = last(arrays),
50864                     mapped = arrayMap(arrays, castArrayLikeObject);
50865
50866                 if (iteratee === last(mapped)) {
50867                   iteratee = undefined$1;
50868                 } else {
50869                   mapped.pop();
50870                 }
50871
50872                 return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, getIteratee(iteratee, 2)) : [];
50873               });
50874               /**
50875                * This method is like `_.intersection` except that it accepts `comparator`
50876                * which is invoked to compare elements of `arrays`. The order and references
50877                * of result values are determined by the first array. The comparator is
50878                * invoked with two arguments: (arrVal, othVal).
50879                *
50880                * @static
50881                * @memberOf _
50882                * @since 4.0.0
50883                * @category Array
50884                * @param {...Array} [arrays] The arrays to inspect.
50885                * @param {Function} [comparator] The comparator invoked per element.
50886                * @returns {Array} Returns the new array of intersecting values.
50887                * @example
50888                *
50889                * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
50890                * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
50891                *
50892                * _.intersectionWith(objects, others, _.isEqual);
50893                * // => [{ 'x': 1, 'y': 2 }]
50894                */
50895
50896               var intersectionWith = baseRest(function (arrays) {
50897                 var comparator = last(arrays),
50898                     mapped = arrayMap(arrays, castArrayLikeObject);
50899                 comparator = typeof comparator == 'function' ? comparator : undefined$1;
50900
50901                 if (comparator) {
50902                   mapped.pop();
50903                 }
50904
50905                 return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined$1, comparator) : [];
50906               });
50907               /**
50908                * Converts all elements in `array` into a string separated by `separator`.
50909                *
50910                * @static
50911                * @memberOf _
50912                * @since 4.0.0
50913                * @category Array
50914                * @param {Array} array The array to convert.
50915                * @param {string} [separator=','] The element separator.
50916                * @returns {string} Returns the joined string.
50917                * @example
50918                *
50919                * _.join(['a', 'b', 'c'], '~');
50920                * // => 'a~b~c'
50921                */
50922
50923               function join(array, separator) {
50924                 return array == null ? '' : nativeJoin.call(array, separator);
50925               }
50926               /**
50927                * Gets the last element of `array`.
50928                *
50929                * @static
50930                * @memberOf _
50931                * @since 0.1.0
50932                * @category Array
50933                * @param {Array} array The array to query.
50934                * @returns {*} Returns the last element of `array`.
50935                * @example
50936                *
50937                * _.last([1, 2, 3]);
50938                * // => 3
50939                */
50940
50941
50942               function last(array) {
50943                 var length = array == null ? 0 : array.length;
50944                 return length ? array[length - 1] : undefined$1;
50945               }
50946               /**
50947                * This method is like `_.indexOf` except that it iterates over elements of
50948                * `array` from right to left.
50949                *
50950                * @static
50951                * @memberOf _
50952                * @since 0.1.0
50953                * @category Array
50954                * @param {Array} array The array to inspect.
50955                * @param {*} value The value to search for.
50956                * @param {number} [fromIndex=array.length-1] The index to search from.
50957                * @returns {number} Returns the index of the matched value, else `-1`.
50958                * @example
50959                *
50960                * _.lastIndexOf([1, 2, 1, 2], 2);
50961                * // => 3
50962                *
50963                * // Search from the `fromIndex`.
50964                * _.lastIndexOf([1, 2, 1, 2], 2, 2);
50965                * // => 1
50966                */
50967
50968
50969               function lastIndexOf(array, value, fromIndex) {
50970                 var length = array == null ? 0 : array.length;
50971
50972                 if (!length) {
50973                   return -1;
50974                 }
50975
50976                 var index = length;
50977
50978                 if (fromIndex !== undefined$1) {
50979                   index = toInteger(fromIndex);
50980                   index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
50981                 }
50982
50983                 return value === value ? strictLastIndexOf(array, value, index) : baseFindIndex(array, baseIsNaN, index, true);
50984               }
50985               /**
50986                * Gets the element at index `n` of `array`. If `n` is negative, the nth
50987                * element from the end is returned.
50988                *
50989                * @static
50990                * @memberOf _
50991                * @since 4.11.0
50992                * @category Array
50993                * @param {Array} array The array to query.
50994                * @param {number} [n=0] The index of the element to return.
50995                * @returns {*} Returns the nth element of `array`.
50996                * @example
50997                *
50998                * var array = ['a', 'b', 'c', 'd'];
50999                *
51000                * _.nth(array, 1);
51001                * // => 'b'
51002                *
51003                * _.nth(array, -2);
51004                * // => 'c';
51005                */
51006
51007
51008               function nth(array, n) {
51009                 return array && array.length ? baseNth(array, toInteger(n)) : undefined$1;
51010               }
51011               /**
51012                * Removes all given values from `array` using
51013                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
51014                * for equality comparisons.
51015                *
51016                * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
51017                * to remove elements from an array by predicate.
51018                *
51019                * @static
51020                * @memberOf _
51021                * @since 2.0.0
51022                * @category Array
51023                * @param {Array} array The array to modify.
51024                * @param {...*} [values] The values to remove.
51025                * @returns {Array} Returns `array`.
51026                * @example
51027                *
51028                * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
51029                *
51030                * _.pull(array, 'a', 'c');
51031                * console.log(array);
51032                * // => ['b', 'b']
51033                */
51034
51035
51036               var pull = baseRest(pullAll);
51037               /**
51038                * This method is like `_.pull` except that it accepts an array of values to remove.
51039                *
51040                * **Note:** Unlike `_.difference`, this method mutates `array`.
51041                *
51042                * @static
51043                * @memberOf _
51044                * @since 4.0.0
51045                * @category Array
51046                * @param {Array} array The array to modify.
51047                * @param {Array} values The values to remove.
51048                * @returns {Array} Returns `array`.
51049                * @example
51050                *
51051                * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
51052                *
51053                * _.pullAll(array, ['a', 'c']);
51054                * console.log(array);
51055                * // => ['b', 'b']
51056                */
51057
51058               function pullAll(array, values) {
51059                 return array && array.length && values && values.length ? basePullAll(array, values) : array;
51060               }
51061               /**
51062                * This method is like `_.pullAll` except that it accepts `iteratee` which is
51063                * invoked for each element of `array` and `values` to generate the criterion
51064                * by which they're compared. The iteratee is invoked with one argument: (value).
51065                *
51066                * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
51067                *
51068                * @static
51069                * @memberOf _
51070                * @since 4.0.0
51071                * @category Array
51072                * @param {Array} array The array to modify.
51073                * @param {Array} values The values to remove.
51074                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51075                * @returns {Array} Returns `array`.
51076                * @example
51077                *
51078                * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
51079                *
51080                * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
51081                * console.log(array);
51082                * // => [{ 'x': 2 }]
51083                */
51084
51085
51086               function pullAllBy(array, values, iteratee) {
51087                 return array && array.length && values && values.length ? basePullAll(array, values, getIteratee(iteratee, 2)) : array;
51088               }
51089               /**
51090                * This method is like `_.pullAll` except that it accepts `comparator` which
51091                * is invoked to compare elements of `array` to `values`. The comparator is
51092                * invoked with two arguments: (arrVal, othVal).
51093                *
51094                * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
51095                *
51096                * @static
51097                * @memberOf _
51098                * @since 4.6.0
51099                * @category Array
51100                * @param {Array} array The array to modify.
51101                * @param {Array} values The values to remove.
51102                * @param {Function} [comparator] The comparator invoked per element.
51103                * @returns {Array} Returns `array`.
51104                * @example
51105                *
51106                * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
51107                *
51108                * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
51109                * console.log(array);
51110                * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
51111                */
51112
51113
51114               function pullAllWith(array, values, comparator) {
51115                 return array && array.length && values && values.length ? basePullAll(array, values, undefined$1, comparator) : array;
51116               }
51117               /**
51118                * Removes elements from `array` corresponding to `indexes` and returns an
51119                * array of removed elements.
51120                *
51121                * **Note:** Unlike `_.at`, this method mutates `array`.
51122                *
51123                * @static
51124                * @memberOf _
51125                * @since 3.0.0
51126                * @category Array
51127                * @param {Array} array The array to modify.
51128                * @param {...(number|number[])} [indexes] The indexes of elements to remove.
51129                * @returns {Array} Returns the new array of removed elements.
51130                * @example
51131                *
51132                * var array = ['a', 'b', 'c', 'd'];
51133                * var pulled = _.pullAt(array, [1, 3]);
51134                *
51135                * console.log(array);
51136                * // => ['a', 'c']
51137                *
51138                * console.log(pulled);
51139                * // => ['b', 'd']
51140                */
51141
51142
51143               var pullAt = flatRest(function (array, indexes) {
51144                 var length = array == null ? 0 : array.length,
51145                     result = baseAt(array, indexes);
51146                 basePullAt(array, arrayMap(indexes, function (index) {
51147                   return isIndex(index, length) ? +index : index;
51148                 }).sort(compareAscending));
51149                 return result;
51150               });
51151               /**
51152                * Removes all elements from `array` that `predicate` returns truthy for
51153                * and returns an array of the removed elements. The predicate is invoked
51154                * with three arguments: (value, index, array).
51155                *
51156                * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
51157                * to pull elements from an array by value.
51158                *
51159                * @static
51160                * @memberOf _
51161                * @since 2.0.0
51162                * @category Array
51163                * @param {Array} array The array to modify.
51164                * @param {Function} [predicate=_.identity] The function invoked per iteration.
51165                * @returns {Array} Returns the new array of removed elements.
51166                * @example
51167                *
51168                * var array = [1, 2, 3, 4];
51169                * var evens = _.remove(array, function(n) {
51170                *   return n % 2 == 0;
51171                * });
51172                *
51173                * console.log(array);
51174                * // => [1, 3]
51175                *
51176                * console.log(evens);
51177                * // => [2, 4]
51178                */
51179
51180               function remove(array, predicate) {
51181                 var result = [];
51182
51183                 if (!(array && array.length)) {
51184                   return result;
51185                 }
51186
51187                 var index = -1,
51188                     indexes = [],
51189                     length = array.length;
51190                 predicate = getIteratee(predicate, 3);
51191
51192                 while (++index < length) {
51193                   var value = array[index];
51194
51195                   if (predicate(value, index, array)) {
51196                     result.push(value);
51197                     indexes.push(index);
51198                   }
51199                 }
51200
51201                 basePullAt(array, indexes);
51202                 return result;
51203               }
51204               /**
51205                * Reverses `array` so that the first element becomes the last, the second
51206                * element becomes the second to last, and so on.
51207                *
51208                * **Note:** This method mutates `array` and is based on
51209                * [`Array#reverse`](https://mdn.io/Array/reverse).
51210                *
51211                * @static
51212                * @memberOf _
51213                * @since 4.0.0
51214                * @category Array
51215                * @param {Array} array The array to modify.
51216                * @returns {Array} Returns `array`.
51217                * @example
51218                *
51219                * var array = [1, 2, 3];
51220                *
51221                * _.reverse(array);
51222                * // => [3, 2, 1]
51223                *
51224                * console.log(array);
51225                * // => [3, 2, 1]
51226                */
51227
51228
51229               function reverse(array) {
51230                 return array == null ? array : nativeReverse.call(array);
51231               }
51232               /**
51233                * Creates a slice of `array` from `start` up to, but not including, `end`.
51234                *
51235                * **Note:** This method is used instead of
51236                * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
51237                * returned.
51238                *
51239                * @static
51240                * @memberOf _
51241                * @since 3.0.0
51242                * @category Array
51243                * @param {Array} array The array to slice.
51244                * @param {number} [start=0] The start position.
51245                * @param {number} [end=array.length] The end position.
51246                * @returns {Array} Returns the slice of `array`.
51247                */
51248
51249
51250               function slice(array, start, end) {
51251                 var length = array == null ? 0 : array.length;
51252
51253                 if (!length) {
51254                   return [];
51255                 }
51256
51257                 if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
51258                   start = 0;
51259                   end = length;
51260                 } else {
51261                   start = start == null ? 0 : toInteger(start);
51262                   end = end === undefined$1 ? length : toInteger(end);
51263                 }
51264
51265                 return baseSlice(array, start, end);
51266               }
51267               /**
51268                * Uses a binary search to determine the lowest index at which `value`
51269                * should be inserted into `array` in order to maintain its sort order.
51270                *
51271                * @static
51272                * @memberOf _
51273                * @since 0.1.0
51274                * @category Array
51275                * @param {Array} array The sorted array to inspect.
51276                * @param {*} value The value to evaluate.
51277                * @returns {number} Returns the index at which `value` should be inserted
51278                *  into `array`.
51279                * @example
51280                *
51281                * _.sortedIndex([30, 50], 40);
51282                * // => 1
51283                */
51284
51285
51286               function sortedIndex(array, value) {
51287                 return baseSortedIndex(array, value);
51288               }
51289               /**
51290                * This method is like `_.sortedIndex` except that it accepts `iteratee`
51291                * which is invoked for `value` and each element of `array` to compute their
51292                * sort ranking. The iteratee is invoked with one argument: (value).
51293                *
51294                * @static
51295                * @memberOf _
51296                * @since 4.0.0
51297                * @category Array
51298                * @param {Array} array The sorted array to inspect.
51299                * @param {*} value The value to evaluate.
51300                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51301                * @returns {number} Returns the index at which `value` should be inserted
51302                *  into `array`.
51303                * @example
51304                *
51305                * var objects = [{ 'x': 4 }, { 'x': 5 }];
51306                *
51307                * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
51308                * // => 0
51309                *
51310                * // The `_.property` iteratee shorthand.
51311                * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
51312                * // => 0
51313                */
51314
51315
51316               function sortedIndexBy(array, value, iteratee) {
51317                 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
51318               }
51319               /**
51320                * This method is like `_.indexOf` except that it performs a binary
51321                * search on a sorted `array`.
51322                *
51323                * @static
51324                * @memberOf _
51325                * @since 4.0.0
51326                * @category Array
51327                * @param {Array} array The array to inspect.
51328                * @param {*} value The value to search for.
51329                * @returns {number} Returns the index of the matched value, else `-1`.
51330                * @example
51331                *
51332                * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
51333                * // => 1
51334                */
51335
51336
51337               function sortedIndexOf(array, value) {
51338                 var length = array == null ? 0 : array.length;
51339
51340                 if (length) {
51341                   var index = baseSortedIndex(array, value);
51342
51343                   if (index < length && eq(array[index], value)) {
51344                     return index;
51345                   }
51346                 }
51347
51348                 return -1;
51349               }
51350               /**
51351                * This method is like `_.sortedIndex` except that it returns the highest
51352                * index at which `value` should be inserted into `array` in order to
51353                * maintain its sort order.
51354                *
51355                * @static
51356                * @memberOf _
51357                * @since 3.0.0
51358                * @category Array
51359                * @param {Array} array The sorted array to inspect.
51360                * @param {*} value The value to evaluate.
51361                * @returns {number} Returns the index at which `value` should be inserted
51362                *  into `array`.
51363                * @example
51364                *
51365                * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
51366                * // => 4
51367                */
51368
51369
51370               function sortedLastIndex(array, value) {
51371                 return baseSortedIndex(array, value, true);
51372               }
51373               /**
51374                * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
51375                * which is invoked for `value` and each element of `array` to compute their
51376                * sort ranking. The iteratee is invoked with one argument: (value).
51377                *
51378                * @static
51379                * @memberOf _
51380                * @since 4.0.0
51381                * @category Array
51382                * @param {Array} array The sorted array to inspect.
51383                * @param {*} value The value to evaluate.
51384                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51385                * @returns {number} Returns the index at which `value` should be inserted
51386                *  into `array`.
51387                * @example
51388                *
51389                * var objects = [{ 'x': 4 }, { 'x': 5 }];
51390                *
51391                * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
51392                * // => 1
51393                *
51394                * // The `_.property` iteratee shorthand.
51395                * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
51396                * // => 1
51397                */
51398
51399
51400               function sortedLastIndexBy(array, value, iteratee) {
51401                 return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
51402               }
51403               /**
51404                * This method is like `_.lastIndexOf` except that it performs a binary
51405                * search on a sorted `array`.
51406                *
51407                * @static
51408                * @memberOf _
51409                * @since 4.0.0
51410                * @category Array
51411                * @param {Array} array The array to inspect.
51412                * @param {*} value The value to search for.
51413                * @returns {number} Returns the index of the matched value, else `-1`.
51414                * @example
51415                *
51416                * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
51417                * // => 3
51418                */
51419
51420
51421               function sortedLastIndexOf(array, value) {
51422                 var length = array == null ? 0 : array.length;
51423
51424                 if (length) {
51425                   var index = baseSortedIndex(array, value, true) - 1;
51426
51427                   if (eq(array[index], value)) {
51428                     return index;
51429                   }
51430                 }
51431
51432                 return -1;
51433               }
51434               /**
51435                * This method is like `_.uniq` except that it's designed and optimized
51436                * for sorted arrays.
51437                *
51438                * @static
51439                * @memberOf _
51440                * @since 4.0.0
51441                * @category Array
51442                * @param {Array} array The array to inspect.
51443                * @returns {Array} Returns the new duplicate free array.
51444                * @example
51445                *
51446                * _.sortedUniq([1, 1, 2]);
51447                * // => [1, 2]
51448                */
51449
51450
51451               function sortedUniq(array) {
51452                 return array && array.length ? baseSortedUniq(array) : [];
51453               }
51454               /**
51455                * This method is like `_.uniqBy` except that it's designed and optimized
51456                * for sorted arrays.
51457                *
51458                * @static
51459                * @memberOf _
51460                * @since 4.0.0
51461                * @category Array
51462                * @param {Array} array The array to inspect.
51463                * @param {Function} [iteratee] The iteratee invoked per element.
51464                * @returns {Array} Returns the new duplicate free array.
51465                * @example
51466                *
51467                * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
51468                * // => [1.1, 2.3]
51469                */
51470
51471
51472               function sortedUniqBy(array, iteratee) {
51473                 return array && array.length ? baseSortedUniq(array, getIteratee(iteratee, 2)) : [];
51474               }
51475               /**
51476                * Gets all but the first element of `array`.
51477                *
51478                * @static
51479                * @memberOf _
51480                * @since 4.0.0
51481                * @category Array
51482                * @param {Array} array The array to query.
51483                * @returns {Array} Returns the slice of `array`.
51484                * @example
51485                *
51486                * _.tail([1, 2, 3]);
51487                * // => [2, 3]
51488                */
51489
51490
51491               function tail(array) {
51492                 var length = array == null ? 0 : array.length;
51493                 return length ? baseSlice(array, 1, length) : [];
51494               }
51495               /**
51496                * Creates a slice of `array` with `n` elements taken from the beginning.
51497                *
51498                * @static
51499                * @memberOf _
51500                * @since 0.1.0
51501                * @category Array
51502                * @param {Array} array The array to query.
51503                * @param {number} [n=1] The number of elements to take.
51504                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
51505                * @returns {Array} Returns the slice of `array`.
51506                * @example
51507                *
51508                * _.take([1, 2, 3]);
51509                * // => [1]
51510                *
51511                * _.take([1, 2, 3], 2);
51512                * // => [1, 2]
51513                *
51514                * _.take([1, 2, 3], 5);
51515                * // => [1, 2, 3]
51516                *
51517                * _.take([1, 2, 3], 0);
51518                * // => []
51519                */
51520
51521
51522               function take(array, n, guard) {
51523                 if (!(array && array.length)) {
51524                   return [];
51525                 }
51526
51527                 n = guard || n === undefined$1 ? 1 : toInteger(n);
51528                 return baseSlice(array, 0, n < 0 ? 0 : n);
51529               }
51530               /**
51531                * Creates a slice of `array` with `n` elements taken from the end.
51532                *
51533                * @static
51534                * @memberOf _
51535                * @since 3.0.0
51536                * @category Array
51537                * @param {Array} array The array to query.
51538                * @param {number} [n=1] The number of elements to take.
51539                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
51540                * @returns {Array} Returns the slice of `array`.
51541                * @example
51542                *
51543                * _.takeRight([1, 2, 3]);
51544                * // => [3]
51545                *
51546                * _.takeRight([1, 2, 3], 2);
51547                * // => [2, 3]
51548                *
51549                * _.takeRight([1, 2, 3], 5);
51550                * // => [1, 2, 3]
51551                *
51552                * _.takeRight([1, 2, 3], 0);
51553                * // => []
51554                */
51555
51556
51557               function takeRight(array, n, guard) {
51558                 var length = array == null ? 0 : array.length;
51559
51560                 if (!length) {
51561                   return [];
51562                 }
51563
51564                 n = guard || n === undefined$1 ? 1 : toInteger(n);
51565                 n = length - n;
51566                 return baseSlice(array, n < 0 ? 0 : n, length);
51567               }
51568               /**
51569                * Creates a slice of `array` with elements taken from the end. Elements are
51570                * taken until `predicate` returns falsey. The predicate is invoked with
51571                * three arguments: (value, index, array).
51572                *
51573                * @static
51574                * @memberOf _
51575                * @since 3.0.0
51576                * @category Array
51577                * @param {Array} array The array to query.
51578                * @param {Function} [predicate=_.identity] The function invoked per iteration.
51579                * @returns {Array} Returns the slice of `array`.
51580                * @example
51581                *
51582                * var users = [
51583                *   { 'user': 'barney',  'active': true },
51584                *   { 'user': 'fred',    'active': false },
51585                *   { 'user': 'pebbles', 'active': false }
51586                * ];
51587                *
51588                * _.takeRightWhile(users, function(o) { return !o.active; });
51589                * // => objects for ['fred', 'pebbles']
51590                *
51591                * // The `_.matches` iteratee shorthand.
51592                * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
51593                * // => objects for ['pebbles']
51594                *
51595                * // The `_.matchesProperty` iteratee shorthand.
51596                * _.takeRightWhile(users, ['active', false]);
51597                * // => objects for ['fred', 'pebbles']
51598                *
51599                * // The `_.property` iteratee shorthand.
51600                * _.takeRightWhile(users, 'active');
51601                * // => []
51602                */
51603
51604
51605               function takeRightWhile(array, predicate) {
51606                 return array && array.length ? baseWhile(array, getIteratee(predicate, 3), false, true) : [];
51607               }
51608               /**
51609                * Creates a slice of `array` with elements taken from the beginning. Elements
51610                * are taken until `predicate` returns falsey. The predicate is invoked with
51611                * three arguments: (value, index, array).
51612                *
51613                * @static
51614                * @memberOf _
51615                * @since 3.0.0
51616                * @category Array
51617                * @param {Array} array The array to query.
51618                * @param {Function} [predicate=_.identity] The function invoked per iteration.
51619                * @returns {Array} Returns the slice of `array`.
51620                * @example
51621                *
51622                * var users = [
51623                *   { 'user': 'barney',  'active': false },
51624                *   { 'user': 'fred',    'active': false },
51625                *   { 'user': 'pebbles', 'active': true }
51626                * ];
51627                *
51628                * _.takeWhile(users, function(o) { return !o.active; });
51629                * // => objects for ['barney', 'fred']
51630                *
51631                * // The `_.matches` iteratee shorthand.
51632                * _.takeWhile(users, { 'user': 'barney', 'active': false });
51633                * // => objects for ['barney']
51634                *
51635                * // The `_.matchesProperty` iteratee shorthand.
51636                * _.takeWhile(users, ['active', false]);
51637                * // => objects for ['barney', 'fred']
51638                *
51639                * // The `_.property` iteratee shorthand.
51640                * _.takeWhile(users, 'active');
51641                * // => []
51642                */
51643
51644
51645               function takeWhile(array, predicate) {
51646                 return array && array.length ? baseWhile(array, getIteratee(predicate, 3)) : [];
51647               }
51648               /**
51649                * Creates an array of unique values, in order, from all given arrays using
51650                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
51651                * for equality comparisons.
51652                *
51653                * @static
51654                * @memberOf _
51655                * @since 0.1.0
51656                * @category Array
51657                * @param {...Array} [arrays] The arrays to inspect.
51658                * @returns {Array} Returns the new array of combined values.
51659                * @example
51660                *
51661                * _.union([2], [1, 2]);
51662                * // => [2, 1]
51663                */
51664
51665
51666               var union = baseRest(function (arrays) {
51667                 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
51668               });
51669               /**
51670                * This method is like `_.union` except that it accepts `iteratee` which is
51671                * invoked for each element of each `arrays` to generate the criterion by
51672                * which uniqueness is computed. Result values are chosen from the first
51673                * array in which the value occurs. The iteratee is invoked with one argument:
51674                * (value).
51675                *
51676                * @static
51677                * @memberOf _
51678                * @since 4.0.0
51679                * @category Array
51680                * @param {...Array} [arrays] The arrays to inspect.
51681                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51682                * @returns {Array} Returns the new array of combined values.
51683                * @example
51684                *
51685                * _.unionBy([2.1], [1.2, 2.3], Math.floor);
51686                * // => [2.1, 1.2]
51687                *
51688                * // The `_.property` iteratee shorthand.
51689                * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
51690                * // => [{ 'x': 1 }, { 'x': 2 }]
51691                */
51692
51693               var unionBy = baseRest(function (arrays) {
51694                 var iteratee = last(arrays);
51695
51696                 if (isArrayLikeObject(iteratee)) {
51697                   iteratee = undefined$1;
51698                 }
51699
51700                 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
51701               });
51702               /**
51703                * This method is like `_.union` except that it accepts `comparator` which
51704                * is invoked to compare elements of `arrays`. Result values are chosen from
51705                * the first array in which the value occurs. The comparator is invoked
51706                * with two arguments: (arrVal, othVal).
51707                *
51708                * @static
51709                * @memberOf _
51710                * @since 4.0.0
51711                * @category Array
51712                * @param {...Array} [arrays] The arrays to inspect.
51713                * @param {Function} [comparator] The comparator invoked per element.
51714                * @returns {Array} Returns the new array of combined values.
51715                * @example
51716                *
51717                * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
51718                * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
51719                *
51720                * _.unionWith(objects, others, _.isEqual);
51721                * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
51722                */
51723
51724               var unionWith = baseRest(function (arrays) {
51725                 var comparator = last(arrays);
51726                 comparator = typeof comparator == 'function' ? comparator : undefined$1;
51727                 return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined$1, comparator);
51728               });
51729               /**
51730                * Creates a duplicate-free version of an array, using
51731                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
51732                * for equality comparisons, in which only the first occurrence of each element
51733                * is kept. The order of result values is determined by the order they occur
51734                * in the array.
51735                *
51736                * @static
51737                * @memberOf _
51738                * @since 0.1.0
51739                * @category Array
51740                * @param {Array} array The array to inspect.
51741                * @returns {Array} Returns the new duplicate free array.
51742                * @example
51743                *
51744                * _.uniq([2, 1, 2]);
51745                * // => [2, 1]
51746                */
51747
51748               function uniq(array) {
51749                 return array && array.length ? baseUniq(array) : [];
51750               }
51751               /**
51752                * This method is like `_.uniq` except that it accepts `iteratee` which is
51753                * invoked for each element in `array` to generate the criterion by which
51754                * uniqueness is computed. The order of result values is determined by the
51755                * order they occur in the array. The iteratee is invoked with one argument:
51756                * (value).
51757                *
51758                * @static
51759                * @memberOf _
51760                * @since 4.0.0
51761                * @category Array
51762                * @param {Array} array The array to inspect.
51763                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51764                * @returns {Array} Returns the new duplicate free array.
51765                * @example
51766                *
51767                * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
51768                * // => [2.1, 1.2]
51769                *
51770                * // The `_.property` iteratee shorthand.
51771                * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
51772                * // => [{ 'x': 1 }, { 'x': 2 }]
51773                */
51774
51775
51776               function uniqBy(array, iteratee) {
51777                 return array && array.length ? baseUniq(array, getIteratee(iteratee, 2)) : [];
51778               }
51779               /**
51780                * This method is like `_.uniq` except that it accepts `comparator` which
51781                * is invoked to compare elements of `array`. The order of result values is
51782                * determined by the order they occur in the array.The comparator is invoked
51783                * with two arguments: (arrVal, othVal).
51784                *
51785                * @static
51786                * @memberOf _
51787                * @since 4.0.0
51788                * @category Array
51789                * @param {Array} array The array to inspect.
51790                * @param {Function} [comparator] The comparator invoked per element.
51791                * @returns {Array} Returns the new duplicate free array.
51792                * @example
51793                *
51794                * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
51795                *
51796                * _.uniqWith(objects, _.isEqual);
51797                * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
51798                */
51799
51800
51801               function uniqWith(array, comparator) {
51802                 comparator = typeof comparator == 'function' ? comparator : undefined$1;
51803                 return array && array.length ? baseUniq(array, undefined$1, comparator) : [];
51804               }
51805               /**
51806                * This method is like `_.zip` except that it accepts an array of grouped
51807                * elements and creates an array regrouping the elements to their pre-zip
51808                * configuration.
51809                *
51810                * @static
51811                * @memberOf _
51812                * @since 1.2.0
51813                * @category Array
51814                * @param {Array} array The array of grouped elements to process.
51815                * @returns {Array} Returns the new array of regrouped elements.
51816                * @example
51817                *
51818                * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
51819                * // => [['a', 1, true], ['b', 2, false]]
51820                *
51821                * _.unzip(zipped);
51822                * // => [['a', 'b'], [1, 2], [true, false]]
51823                */
51824
51825
51826               function unzip(array) {
51827                 if (!(array && array.length)) {
51828                   return [];
51829                 }
51830
51831                 var length = 0;
51832                 array = arrayFilter(array, function (group) {
51833                   if (isArrayLikeObject(group)) {
51834                     length = nativeMax(group.length, length);
51835                     return true;
51836                   }
51837                 });
51838                 return baseTimes(length, function (index) {
51839                   return arrayMap(array, baseProperty(index));
51840                 });
51841               }
51842               /**
51843                * This method is like `_.unzip` except that it accepts `iteratee` to specify
51844                * how regrouped values should be combined. The iteratee is invoked with the
51845                * elements of each group: (...group).
51846                *
51847                * @static
51848                * @memberOf _
51849                * @since 3.8.0
51850                * @category Array
51851                * @param {Array} array The array of grouped elements to process.
51852                * @param {Function} [iteratee=_.identity] The function to combine
51853                *  regrouped values.
51854                * @returns {Array} Returns the new array of regrouped elements.
51855                * @example
51856                *
51857                * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
51858                * // => [[1, 10, 100], [2, 20, 200]]
51859                *
51860                * _.unzipWith(zipped, _.add);
51861                * // => [3, 30, 300]
51862                */
51863
51864
51865               function unzipWith(array, iteratee) {
51866                 if (!(array && array.length)) {
51867                   return [];
51868                 }
51869
51870                 var result = unzip(array);
51871
51872                 if (iteratee == null) {
51873                   return result;
51874                 }
51875
51876                 return arrayMap(result, function (group) {
51877                   return apply(iteratee, undefined$1, group);
51878                 });
51879               }
51880               /**
51881                * Creates an array excluding all given values using
51882                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
51883                * for equality comparisons.
51884                *
51885                * **Note:** Unlike `_.pull`, this method returns a new array.
51886                *
51887                * @static
51888                * @memberOf _
51889                * @since 0.1.0
51890                * @category Array
51891                * @param {Array} array The array to inspect.
51892                * @param {...*} [values] The values to exclude.
51893                * @returns {Array} Returns the new array of filtered values.
51894                * @see _.difference, _.xor
51895                * @example
51896                *
51897                * _.without([2, 1, 2, 3], 1, 2);
51898                * // => [3]
51899                */
51900
51901
51902               var without = baseRest(function (array, values) {
51903                 return isArrayLikeObject(array) ? baseDifference(array, values) : [];
51904               });
51905               /**
51906                * Creates an array of unique values that is the
51907                * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
51908                * of the given arrays. The order of result values is determined by the order
51909                * they occur in the arrays.
51910                *
51911                * @static
51912                * @memberOf _
51913                * @since 2.4.0
51914                * @category Array
51915                * @param {...Array} [arrays] The arrays to inspect.
51916                * @returns {Array} Returns the new array of filtered values.
51917                * @see _.difference, _.without
51918                * @example
51919                *
51920                * _.xor([2, 1], [2, 3]);
51921                * // => [1, 3]
51922                */
51923
51924               var xor = baseRest(function (arrays) {
51925                 return baseXor(arrayFilter(arrays, isArrayLikeObject));
51926               });
51927               /**
51928                * This method is like `_.xor` except that it accepts `iteratee` which is
51929                * invoked for each element of each `arrays` to generate the criterion by
51930                * which by which they're compared. The order of result values is determined
51931                * by the order they occur in the arrays. The iteratee is invoked with one
51932                * argument: (value).
51933                *
51934                * @static
51935                * @memberOf _
51936                * @since 4.0.0
51937                * @category Array
51938                * @param {...Array} [arrays] The arrays to inspect.
51939                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
51940                * @returns {Array} Returns the new array of filtered values.
51941                * @example
51942                *
51943                * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
51944                * // => [1.2, 3.4]
51945                *
51946                * // The `_.property` iteratee shorthand.
51947                * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
51948                * // => [{ 'x': 2 }]
51949                */
51950
51951               var xorBy = baseRest(function (arrays) {
51952                 var iteratee = last(arrays);
51953
51954                 if (isArrayLikeObject(iteratee)) {
51955                   iteratee = undefined$1;
51956                 }
51957
51958                 return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
51959               });
51960               /**
51961                * This method is like `_.xor` except that it accepts `comparator` which is
51962                * invoked to compare elements of `arrays`. The order of result values is
51963                * determined by the order they occur in the arrays. The comparator is invoked
51964                * with two arguments: (arrVal, othVal).
51965                *
51966                * @static
51967                * @memberOf _
51968                * @since 4.0.0
51969                * @category Array
51970                * @param {...Array} [arrays] The arrays to inspect.
51971                * @param {Function} [comparator] The comparator invoked per element.
51972                * @returns {Array} Returns the new array of filtered values.
51973                * @example
51974                *
51975                * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
51976                * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
51977                *
51978                * _.xorWith(objects, others, _.isEqual);
51979                * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
51980                */
51981
51982               var xorWith = baseRest(function (arrays) {
51983                 var comparator = last(arrays);
51984                 comparator = typeof comparator == 'function' ? comparator : undefined$1;
51985                 return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined$1, comparator);
51986               });
51987               /**
51988                * Creates an array of grouped elements, the first of which contains the
51989                * first elements of the given arrays, the second of which contains the
51990                * second elements of the given arrays, and so on.
51991                *
51992                * @static
51993                * @memberOf _
51994                * @since 0.1.0
51995                * @category Array
51996                * @param {...Array} [arrays] The arrays to process.
51997                * @returns {Array} Returns the new array of grouped elements.
51998                * @example
51999                *
52000                * _.zip(['a', 'b'], [1, 2], [true, false]);
52001                * // => [['a', 1, true], ['b', 2, false]]
52002                */
52003
52004               var zip = baseRest(unzip);
52005               /**
52006                * This method is like `_.fromPairs` except that it accepts two arrays,
52007                * one of property identifiers and one of corresponding values.
52008                *
52009                * @static
52010                * @memberOf _
52011                * @since 0.4.0
52012                * @category Array
52013                * @param {Array} [props=[]] The property identifiers.
52014                * @param {Array} [values=[]] The property values.
52015                * @returns {Object} Returns the new object.
52016                * @example
52017                *
52018                * _.zipObject(['a', 'b'], [1, 2]);
52019                * // => { 'a': 1, 'b': 2 }
52020                */
52021
52022               function zipObject(props, values) {
52023                 return baseZipObject(props || [], values || [], assignValue);
52024               }
52025               /**
52026                * This method is like `_.zipObject` except that it supports property paths.
52027                *
52028                * @static
52029                * @memberOf _
52030                * @since 4.1.0
52031                * @category Array
52032                * @param {Array} [props=[]] The property identifiers.
52033                * @param {Array} [values=[]] The property values.
52034                * @returns {Object} Returns the new object.
52035                * @example
52036                *
52037                * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
52038                * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
52039                */
52040
52041
52042               function zipObjectDeep(props, values) {
52043                 return baseZipObject(props || [], values || [], baseSet);
52044               }
52045               /**
52046                * This method is like `_.zip` except that it accepts `iteratee` to specify
52047                * how grouped values should be combined. The iteratee is invoked with the
52048                * elements of each group: (...group).
52049                *
52050                * @static
52051                * @memberOf _
52052                * @since 3.8.0
52053                * @category Array
52054                * @param {...Array} [arrays] The arrays to process.
52055                * @param {Function} [iteratee=_.identity] The function to combine
52056                *  grouped values.
52057                * @returns {Array} Returns the new array of grouped elements.
52058                * @example
52059                *
52060                * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
52061                *   return a + b + c;
52062                * });
52063                * // => [111, 222]
52064                */
52065
52066
52067               var zipWith = baseRest(function (arrays) {
52068                 var length = arrays.length,
52069                     iteratee = length > 1 ? arrays[length - 1] : undefined$1;
52070                 iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined$1;
52071                 return unzipWith(arrays, iteratee);
52072               });
52073               /*------------------------------------------------------------------------*/
52074
52075               /**
52076                * Creates a `lodash` wrapper instance that wraps `value` with explicit method
52077                * chain sequences enabled. The result of such sequences must be unwrapped
52078                * with `_#value`.
52079                *
52080                * @static
52081                * @memberOf _
52082                * @since 1.3.0
52083                * @category Seq
52084                * @param {*} value The value to wrap.
52085                * @returns {Object} Returns the new `lodash` wrapper instance.
52086                * @example
52087                *
52088                * var users = [
52089                *   { 'user': 'barney',  'age': 36 },
52090                *   { 'user': 'fred',    'age': 40 },
52091                *   { 'user': 'pebbles', 'age': 1 }
52092                * ];
52093                *
52094                * var youngest = _
52095                *   .chain(users)
52096                *   .sortBy('age')
52097                *   .map(function(o) {
52098                *     return o.user + ' is ' + o.age;
52099                *   })
52100                *   .head()
52101                *   .value();
52102                * // => 'pebbles is 1'
52103                */
52104
52105               function chain(value) {
52106                 var result = lodash(value);
52107                 result.__chain__ = true;
52108                 return result;
52109               }
52110               /**
52111                * This method invokes `interceptor` and returns `value`. The interceptor
52112                * is invoked with one argument; (value). The purpose of this method is to
52113                * "tap into" a method chain sequence in order to modify intermediate results.
52114                *
52115                * @static
52116                * @memberOf _
52117                * @since 0.1.0
52118                * @category Seq
52119                * @param {*} value The value to provide to `interceptor`.
52120                * @param {Function} interceptor The function to invoke.
52121                * @returns {*} Returns `value`.
52122                * @example
52123                *
52124                * _([1, 2, 3])
52125                *  .tap(function(array) {
52126                *    // Mutate input array.
52127                *    array.pop();
52128                *  })
52129                *  .reverse()
52130                *  .value();
52131                * // => [2, 1]
52132                */
52133
52134
52135               function tap(value, interceptor) {
52136                 interceptor(value);
52137                 return value;
52138               }
52139               /**
52140                * This method is like `_.tap` except that it returns the result of `interceptor`.
52141                * The purpose of this method is to "pass thru" values replacing intermediate
52142                * results in a method chain sequence.
52143                *
52144                * @static
52145                * @memberOf _
52146                * @since 3.0.0
52147                * @category Seq
52148                * @param {*} value The value to provide to `interceptor`.
52149                * @param {Function} interceptor The function to invoke.
52150                * @returns {*} Returns the result of `interceptor`.
52151                * @example
52152                *
52153                * _('  abc  ')
52154                *  .chain()
52155                *  .trim()
52156                *  .thru(function(value) {
52157                *    return [value];
52158                *  })
52159                *  .value();
52160                * // => ['abc']
52161                */
52162
52163
52164               function thru(value, interceptor) {
52165                 return interceptor(value);
52166               }
52167               /**
52168                * This method is the wrapper version of `_.at`.
52169                *
52170                * @name at
52171                * @memberOf _
52172                * @since 1.0.0
52173                * @category Seq
52174                * @param {...(string|string[])} [paths] The property paths to pick.
52175                * @returns {Object} Returns the new `lodash` wrapper instance.
52176                * @example
52177                *
52178                * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
52179                *
52180                * _(object).at(['a[0].b.c', 'a[1]']).value();
52181                * // => [3, 4]
52182                */
52183
52184
52185               var wrapperAt = flatRest(function (paths) {
52186                 var length = paths.length,
52187                     start = length ? paths[0] : 0,
52188                     value = this.__wrapped__,
52189                     interceptor = function interceptor(object) {
52190                   return baseAt(object, paths);
52191                 };
52192
52193                 if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) {
52194                   return this.thru(interceptor);
52195                 }
52196
52197                 value = value.slice(start, +start + (length ? 1 : 0));
52198
52199                 value.__actions__.push({
52200                   'func': thru,
52201                   'args': [interceptor],
52202                   'thisArg': undefined$1
52203                 });
52204
52205                 return new LodashWrapper(value, this.__chain__).thru(function (array) {
52206                   if (length && !array.length) {
52207                     array.push(undefined$1);
52208                   }
52209
52210                   return array;
52211                 });
52212               });
52213               /**
52214                * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
52215                *
52216                * @name chain
52217                * @memberOf _
52218                * @since 0.1.0
52219                * @category Seq
52220                * @returns {Object} Returns the new `lodash` wrapper instance.
52221                * @example
52222                *
52223                * var users = [
52224                *   { 'user': 'barney', 'age': 36 },
52225                *   { 'user': 'fred',   'age': 40 }
52226                * ];
52227                *
52228                * // A sequence without explicit chaining.
52229                * _(users).head();
52230                * // => { 'user': 'barney', 'age': 36 }
52231                *
52232                * // A sequence with explicit chaining.
52233                * _(users)
52234                *   .chain()
52235                *   .head()
52236                *   .pick('user')
52237                *   .value();
52238                * // => { 'user': 'barney' }
52239                */
52240
52241               function wrapperChain() {
52242                 return chain(this);
52243               }
52244               /**
52245                * Executes the chain sequence and returns the wrapped result.
52246                *
52247                * @name commit
52248                * @memberOf _
52249                * @since 3.2.0
52250                * @category Seq
52251                * @returns {Object} Returns the new `lodash` wrapper instance.
52252                * @example
52253                *
52254                * var array = [1, 2];
52255                * var wrapped = _(array).push(3);
52256                *
52257                * console.log(array);
52258                * // => [1, 2]
52259                *
52260                * wrapped = wrapped.commit();
52261                * console.log(array);
52262                * // => [1, 2, 3]
52263                *
52264                * wrapped.last();
52265                * // => 3
52266                *
52267                * console.log(array);
52268                * // => [1, 2, 3]
52269                */
52270
52271
52272               function wrapperCommit() {
52273                 return new LodashWrapper(this.value(), this.__chain__);
52274               }
52275               /**
52276                * Gets the next value on a wrapped object following the
52277                * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
52278                *
52279                * @name next
52280                * @memberOf _
52281                * @since 4.0.0
52282                * @category Seq
52283                * @returns {Object} Returns the next iterator value.
52284                * @example
52285                *
52286                * var wrapped = _([1, 2]);
52287                *
52288                * wrapped.next();
52289                * // => { 'done': false, 'value': 1 }
52290                *
52291                * wrapped.next();
52292                * // => { 'done': false, 'value': 2 }
52293                *
52294                * wrapped.next();
52295                * // => { 'done': true, 'value': undefined }
52296                */
52297
52298
52299               function wrapperNext() {
52300                 if (this.__values__ === undefined$1) {
52301                   this.__values__ = toArray(this.value());
52302                 }
52303
52304                 var done = this.__index__ >= this.__values__.length,
52305                     value = done ? undefined$1 : this.__values__[this.__index__++];
52306                 return {
52307                   'done': done,
52308                   'value': value
52309                 };
52310               }
52311               /**
52312                * Enables the wrapper to be iterable.
52313                *
52314                * @name Symbol.iterator
52315                * @memberOf _
52316                * @since 4.0.0
52317                * @category Seq
52318                * @returns {Object} Returns the wrapper object.
52319                * @example
52320                *
52321                * var wrapped = _([1, 2]);
52322                *
52323                * wrapped[Symbol.iterator]() === wrapped;
52324                * // => true
52325                *
52326                * Array.from(wrapped);
52327                * // => [1, 2]
52328                */
52329
52330
52331               function wrapperToIterator() {
52332                 return this;
52333               }
52334               /**
52335                * Creates a clone of the chain sequence planting `value` as the wrapped value.
52336                *
52337                * @name plant
52338                * @memberOf _
52339                * @since 3.2.0
52340                * @category Seq
52341                * @param {*} value The value to plant.
52342                * @returns {Object} Returns the new `lodash` wrapper instance.
52343                * @example
52344                *
52345                * function square(n) {
52346                *   return n * n;
52347                * }
52348                *
52349                * var wrapped = _([1, 2]).map(square);
52350                * var other = wrapped.plant([3, 4]);
52351                *
52352                * other.value();
52353                * // => [9, 16]
52354                *
52355                * wrapped.value();
52356                * // => [1, 4]
52357                */
52358
52359
52360               function wrapperPlant(value) {
52361                 var result,
52362                     parent = this;
52363
52364                 while (parent instanceof baseLodash) {
52365                   var clone = wrapperClone(parent);
52366                   clone.__index__ = 0;
52367                   clone.__values__ = undefined$1;
52368
52369                   if (result) {
52370                     previous.__wrapped__ = clone;
52371                   } else {
52372                     result = clone;
52373                   }
52374
52375                   var previous = clone;
52376                   parent = parent.__wrapped__;
52377                 }
52378
52379                 previous.__wrapped__ = value;
52380                 return result;
52381               }
52382               /**
52383                * This method is the wrapper version of `_.reverse`.
52384                *
52385                * **Note:** This method mutates the wrapped array.
52386                *
52387                * @name reverse
52388                * @memberOf _
52389                * @since 0.1.0
52390                * @category Seq
52391                * @returns {Object} Returns the new `lodash` wrapper instance.
52392                * @example
52393                *
52394                * var array = [1, 2, 3];
52395                *
52396                * _(array).reverse().value()
52397                * // => [3, 2, 1]
52398                *
52399                * console.log(array);
52400                * // => [3, 2, 1]
52401                */
52402
52403
52404               function wrapperReverse() {
52405                 var value = this.__wrapped__;
52406
52407                 if (value instanceof LazyWrapper) {
52408                   var wrapped = value;
52409
52410                   if (this.__actions__.length) {
52411                     wrapped = new LazyWrapper(this);
52412                   }
52413
52414                   wrapped = wrapped.reverse();
52415
52416                   wrapped.__actions__.push({
52417                     'func': thru,
52418                     'args': [reverse],
52419                     'thisArg': undefined$1
52420                   });
52421
52422                   return new LodashWrapper(wrapped, this.__chain__);
52423                 }
52424
52425                 return this.thru(reverse);
52426               }
52427               /**
52428                * Executes the chain sequence to resolve the unwrapped value.
52429                *
52430                * @name value
52431                * @memberOf _
52432                * @since 0.1.0
52433                * @alias toJSON, valueOf
52434                * @category Seq
52435                * @returns {*} Returns the resolved unwrapped value.
52436                * @example
52437                *
52438                * _([1, 2, 3]).value();
52439                * // => [1, 2, 3]
52440                */
52441
52442
52443               function wrapperValue() {
52444                 return baseWrapperValue(this.__wrapped__, this.__actions__);
52445               }
52446               /*------------------------------------------------------------------------*/
52447
52448               /**
52449                * Creates an object composed of keys generated from the results of running
52450                * each element of `collection` thru `iteratee`. The corresponding value of
52451                * each key is the number of times the key was returned by `iteratee`. The
52452                * iteratee is invoked with one argument: (value).
52453                *
52454                * @static
52455                * @memberOf _
52456                * @since 0.5.0
52457                * @category Collection
52458                * @param {Array|Object} collection The collection to iterate over.
52459                * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
52460                * @returns {Object} Returns the composed aggregate object.
52461                * @example
52462                *
52463                * _.countBy([6.1, 4.2, 6.3], Math.floor);
52464                * // => { '4': 1, '6': 2 }
52465                *
52466                * // The `_.property` iteratee shorthand.
52467                * _.countBy(['one', 'two', 'three'], 'length');
52468                * // => { '3': 2, '5': 1 }
52469                */
52470
52471
52472               var countBy = createAggregator(function (result, value, key) {
52473                 if (hasOwnProperty.call(result, key)) {
52474                   ++result[key];
52475                 } else {
52476                   baseAssignValue(result, key, 1);
52477                 }
52478               });
52479               /**
52480                * Checks if `predicate` returns truthy for **all** elements of `collection`.
52481                * Iteration is stopped once `predicate` returns falsey. The predicate is
52482                * invoked with three arguments: (value, index|key, collection).
52483                *
52484                * **Note:** This method returns `true` for
52485                * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
52486                * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
52487                * elements of empty collections.
52488                *
52489                * @static
52490                * @memberOf _
52491                * @since 0.1.0
52492                * @category Collection
52493                * @param {Array|Object} collection The collection to iterate over.
52494                * @param {Function} [predicate=_.identity] The function invoked per iteration.
52495                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
52496                * @returns {boolean} Returns `true` if all elements pass the predicate check,
52497                *  else `false`.
52498                * @example
52499                *
52500                * _.every([true, 1, null, 'yes'], Boolean);
52501                * // => false
52502                *
52503                * var users = [
52504                *   { 'user': 'barney', 'age': 36, 'active': false },
52505                *   { 'user': 'fred',   'age': 40, 'active': false }
52506                * ];
52507                *
52508                * // The `_.matches` iteratee shorthand.
52509                * _.every(users, { 'user': 'barney', 'active': false });
52510                * // => false
52511                *
52512                * // The `_.matchesProperty` iteratee shorthand.
52513                * _.every(users, ['active', false]);
52514                * // => true
52515                *
52516                * // The `_.property` iteratee shorthand.
52517                * _.every(users, 'active');
52518                * // => false
52519                */
52520
52521               function every(collection, predicate, guard) {
52522                 var func = isArray(collection) ? arrayEvery : baseEvery;
52523
52524                 if (guard && isIterateeCall(collection, predicate, guard)) {
52525                   predicate = undefined$1;
52526                 }
52527
52528                 return func(collection, getIteratee(predicate, 3));
52529               }
52530               /**
52531                * Iterates over elements of `collection`, returning an array of all elements
52532                * `predicate` returns truthy for. The predicate is invoked with three
52533                * arguments: (value, index|key, collection).
52534                *
52535                * **Note:** Unlike `_.remove`, this method returns a new array.
52536                *
52537                * @static
52538                * @memberOf _
52539                * @since 0.1.0
52540                * @category Collection
52541                * @param {Array|Object} collection The collection to iterate over.
52542                * @param {Function} [predicate=_.identity] The function invoked per iteration.
52543                * @returns {Array} Returns the new filtered array.
52544                * @see _.reject
52545                * @example
52546                *
52547                * var users = [
52548                *   { 'user': 'barney', 'age': 36, 'active': true },
52549                *   { 'user': 'fred',   'age': 40, 'active': false }
52550                * ];
52551                *
52552                * _.filter(users, function(o) { return !o.active; });
52553                * // => objects for ['fred']
52554                *
52555                * // The `_.matches` iteratee shorthand.
52556                * _.filter(users, { 'age': 36, 'active': true });
52557                * // => objects for ['barney']
52558                *
52559                * // The `_.matchesProperty` iteratee shorthand.
52560                * _.filter(users, ['active', false]);
52561                * // => objects for ['fred']
52562                *
52563                * // The `_.property` iteratee shorthand.
52564                * _.filter(users, 'active');
52565                * // => objects for ['barney']
52566                *
52567                * // Combining several predicates using `_.overEvery` or `_.overSome`.
52568                * _.filter(users, _.overSome([{ 'age': 36 }, ['age', 40]]));
52569                * // => objects for ['fred', 'barney']
52570                */
52571
52572
52573               function filter(collection, predicate) {
52574                 var func = isArray(collection) ? arrayFilter : baseFilter;
52575                 return func(collection, getIteratee(predicate, 3));
52576               }
52577               /**
52578                * Iterates over elements of `collection`, returning the first element
52579                * `predicate` returns truthy for. The predicate is invoked with three
52580                * arguments: (value, index|key, collection).
52581                *
52582                * @static
52583                * @memberOf _
52584                * @since 0.1.0
52585                * @category Collection
52586                * @param {Array|Object} collection The collection to inspect.
52587                * @param {Function} [predicate=_.identity] The function invoked per iteration.
52588                * @param {number} [fromIndex=0] The index to search from.
52589                * @returns {*} Returns the matched element, else `undefined`.
52590                * @example
52591                *
52592                * var users = [
52593                *   { 'user': 'barney',  'age': 36, 'active': true },
52594                *   { 'user': 'fred',    'age': 40, 'active': false },
52595                *   { 'user': 'pebbles', 'age': 1,  'active': true }
52596                * ];
52597                *
52598                * _.find(users, function(o) { return o.age < 40; });
52599                * // => object for 'barney'
52600                *
52601                * // The `_.matches` iteratee shorthand.
52602                * _.find(users, { 'age': 1, 'active': true });
52603                * // => object for 'pebbles'
52604                *
52605                * // The `_.matchesProperty` iteratee shorthand.
52606                * _.find(users, ['active', false]);
52607                * // => object for 'fred'
52608                *
52609                * // The `_.property` iteratee shorthand.
52610                * _.find(users, 'active');
52611                * // => object for 'barney'
52612                */
52613
52614
52615               var find = createFind(findIndex);
52616               /**
52617                * This method is like `_.find` except that it iterates over elements of
52618                * `collection` from right to left.
52619                *
52620                * @static
52621                * @memberOf _
52622                * @since 2.0.0
52623                * @category Collection
52624                * @param {Array|Object} collection The collection to inspect.
52625                * @param {Function} [predicate=_.identity] The function invoked per iteration.
52626                * @param {number} [fromIndex=collection.length-1] The index to search from.
52627                * @returns {*} Returns the matched element, else `undefined`.
52628                * @example
52629                *
52630                * _.findLast([1, 2, 3, 4], function(n) {
52631                *   return n % 2 == 1;
52632                * });
52633                * // => 3
52634                */
52635
52636               var findLast = createFind(findLastIndex);
52637               /**
52638                * Creates a flattened array of values by running each element in `collection`
52639                * thru `iteratee` and flattening the mapped results. The iteratee is invoked
52640                * with three arguments: (value, index|key, collection).
52641                *
52642                * @static
52643                * @memberOf _
52644                * @since 4.0.0
52645                * @category Collection
52646                * @param {Array|Object} collection The collection to iterate over.
52647                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52648                * @returns {Array} Returns the new flattened array.
52649                * @example
52650                *
52651                * function duplicate(n) {
52652                *   return [n, n];
52653                * }
52654                *
52655                * _.flatMap([1, 2], duplicate);
52656                * // => [1, 1, 2, 2]
52657                */
52658
52659               function flatMap(collection, iteratee) {
52660                 return baseFlatten(map(collection, iteratee), 1);
52661               }
52662               /**
52663                * This method is like `_.flatMap` except that it recursively flattens the
52664                * mapped results.
52665                *
52666                * @static
52667                * @memberOf _
52668                * @since 4.7.0
52669                * @category Collection
52670                * @param {Array|Object} collection The collection to iterate over.
52671                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52672                * @returns {Array} Returns the new flattened array.
52673                * @example
52674                *
52675                * function duplicate(n) {
52676                *   return [[[n, n]]];
52677                * }
52678                *
52679                * _.flatMapDeep([1, 2], duplicate);
52680                * // => [1, 1, 2, 2]
52681                */
52682
52683
52684               function flatMapDeep(collection, iteratee) {
52685                 return baseFlatten(map(collection, iteratee), INFINITY);
52686               }
52687               /**
52688                * This method is like `_.flatMap` except that it recursively flattens the
52689                * mapped results up to `depth` times.
52690                *
52691                * @static
52692                * @memberOf _
52693                * @since 4.7.0
52694                * @category Collection
52695                * @param {Array|Object} collection The collection to iterate over.
52696                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52697                * @param {number} [depth=1] The maximum recursion depth.
52698                * @returns {Array} Returns the new flattened array.
52699                * @example
52700                *
52701                * function duplicate(n) {
52702                *   return [[[n, n]]];
52703                * }
52704                *
52705                * _.flatMapDepth([1, 2], duplicate, 2);
52706                * // => [[1, 1], [2, 2]]
52707                */
52708
52709
52710               function flatMapDepth(collection, iteratee, depth) {
52711                 depth = depth === undefined$1 ? 1 : toInteger(depth);
52712                 return baseFlatten(map(collection, iteratee), depth);
52713               }
52714               /**
52715                * Iterates over elements of `collection` and invokes `iteratee` for each element.
52716                * The iteratee is invoked with three arguments: (value, index|key, collection).
52717                * Iteratee functions may exit iteration early by explicitly returning `false`.
52718                *
52719                * **Note:** As with other "Collections" methods, objects with a "length"
52720                * property are iterated like arrays. To avoid this behavior use `_.forIn`
52721                * or `_.forOwn` for object iteration.
52722                *
52723                * @static
52724                * @memberOf _
52725                * @since 0.1.0
52726                * @alias each
52727                * @category Collection
52728                * @param {Array|Object} collection The collection to iterate over.
52729                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52730                * @returns {Array|Object} Returns `collection`.
52731                * @see _.forEachRight
52732                * @example
52733                *
52734                * _.forEach([1, 2], function(value) {
52735                *   console.log(value);
52736                * });
52737                * // => Logs `1` then `2`.
52738                *
52739                * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
52740                *   console.log(key);
52741                * });
52742                * // => Logs 'a' then 'b' (iteration order is not guaranteed).
52743                */
52744
52745
52746               function forEach(collection, iteratee) {
52747                 var func = isArray(collection) ? arrayEach : baseEach;
52748                 return func(collection, getIteratee(iteratee, 3));
52749               }
52750               /**
52751                * This method is like `_.forEach` except that it iterates over elements of
52752                * `collection` from right to left.
52753                *
52754                * @static
52755                * @memberOf _
52756                * @since 2.0.0
52757                * @alias eachRight
52758                * @category Collection
52759                * @param {Array|Object} collection The collection to iterate over.
52760                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52761                * @returns {Array|Object} Returns `collection`.
52762                * @see _.forEach
52763                * @example
52764                *
52765                * _.forEachRight([1, 2], function(value) {
52766                *   console.log(value);
52767                * });
52768                * // => Logs `2` then `1`.
52769                */
52770
52771
52772               function forEachRight(collection, iteratee) {
52773                 var func = isArray(collection) ? arrayEachRight : baseEachRight;
52774                 return func(collection, getIteratee(iteratee, 3));
52775               }
52776               /**
52777                * Creates an object composed of keys generated from the results of running
52778                * each element of `collection` thru `iteratee`. The order of grouped values
52779                * is determined by the order they occur in `collection`. The corresponding
52780                * value of each key is an array of elements responsible for generating the
52781                * key. The iteratee is invoked with one argument: (value).
52782                *
52783                * @static
52784                * @memberOf _
52785                * @since 0.1.0
52786                * @category Collection
52787                * @param {Array|Object} collection The collection to iterate over.
52788                * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
52789                * @returns {Object} Returns the composed aggregate object.
52790                * @example
52791                *
52792                * _.groupBy([6.1, 4.2, 6.3], Math.floor);
52793                * // => { '4': [4.2], '6': [6.1, 6.3] }
52794                *
52795                * // The `_.property` iteratee shorthand.
52796                * _.groupBy(['one', 'two', 'three'], 'length');
52797                * // => { '3': ['one', 'two'], '5': ['three'] }
52798                */
52799
52800
52801               var groupBy = createAggregator(function (result, value, key) {
52802                 if (hasOwnProperty.call(result, key)) {
52803                   result[key].push(value);
52804                 } else {
52805                   baseAssignValue(result, key, [value]);
52806                 }
52807               });
52808               /**
52809                * Checks if `value` is in `collection`. If `collection` is a string, it's
52810                * checked for a substring of `value`, otherwise
52811                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
52812                * is used for equality comparisons. If `fromIndex` is negative, it's used as
52813                * the offset from the end of `collection`.
52814                *
52815                * @static
52816                * @memberOf _
52817                * @since 0.1.0
52818                * @category Collection
52819                * @param {Array|Object|string} collection The collection to inspect.
52820                * @param {*} value The value to search for.
52821                * @param {number} [fromIndex=0] The index to search from.
52822                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
52823                * @returns {boolean} Returns `true` if `value` is found, else `false`.
52824                * @example
52825                *
52826                * _.includes([1, 2, 3], 1);
52827                * // => true
52828                *
52829                * _.includes([1, 2, 3], 1, 2);
52830                * // => false
52831                *
52832                * _.includes({ 'a': 1, 'b': 2 }, 1);
52833                * // => true
52834                *
52835                * _.includes('abcd', 'bc');
52836                * // => true
52837                */
52838
52839               function includes(collection, value, fromIndex, guard) {
52840                 collection = isArrayLike(collection) ? collection : values(collection);
52841                 fromIndex = fromIndex && !guard ? toInteger(fromIndex) : 0;
52842                 var length = collection.length;
52843
52844                 if (fromIndex < 0) {
52845                   fromIndex = nativeMax(length + fromIndex, 0);
52846                 }
52847
52848                 return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1;
52849               }
52850               /**
52851                * Invokes the method at `path` of each element in `collection`, returning
52852                * an array of the results of each invoked method. Any additional arguments
52853                * are provided to each invoked method. If `path` is a function, it's invoked
52854                * for, and `this` bound to, each element in `collection`.
52855                *
52856                * @static
52857                * @memberOf _
52858                * @since 4.0.0
52859                * @category Collection
52860                * @param {Array|Object} collection The collection to iterate over.
52861                * @param {Array|Function|string} path The path of the method to invoke or
52862                *  the function invoked per iteration.
52863                * @param {...*} [args] The arguments to invoke each method with.
52864                * @returns {Array} Returns the array of results.
52865                * @example
52866                *
52867                * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
52868                * // => [[1, 5, 7], [1, 2, 3]]
52869                *
52870                * _.invokeMap([123, 456], String.prototype.split, '');
52871                * // => [['1', '2', '3'], ['4', '5', '6']]
52872                */
52873
52874
52875               var invokeMap = baseRest(function (collection, path, args) {
52876                 var index = -1,
52877                     isFunc = typeof path == 'function',
52878                     result = isArrayLike(collection) ? Array(collection.length) : [];
52879                 baseEach(collection, function (value) {
52880                   result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
52881                 });
52882                 return result;
52883               });
52884               /**
52885                * Creates an object composed of keys generated from the results of running
52886                * each element of `collection` thru `iteratee`. The corresponding value of
52887                * each key is the last element responsible for generating the key. The
52888                * iteratee is invoked with one argument: (value).
52889                *
52890                * @static
52891                * @memberOf _
52892                * @since 4.0.0
52893                * @category Collection
52894                * @param {Array|Object} collection The collection to iterate over.
52895                * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
52896                * @returns {Object} Returns the composed aggregate object.
52897                * @example
52898                *
52899                * var array = [
52900                *   { 'dir': 'left', 'code': 97 },
52901                *   { 'dir': 'right', 'code': 100 }
52902                * ];
52903                *
52904                * _.keyBy(array, function(o) {
52905                *   return String.fromCharCode(o.code);
52906                * });
52907                * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
52908                *
52909                * _.keyBy(array, 'dir');
52910                * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
52911                */
52912
52913               var keyBy = createAggregator(function (result, value, key) {
52914                 baseAssignValue(result, key, value);
52915               });
52916               /**
52917                * Creates an array of values by running each element in `collection` thru
52918                * `iteratee`. The iteratee is invoked with three arguments:
52919                * (value, index|key, collection).
52920                *
52921                * Many lodash methods are guarded to work as iteratees for methods like
52922                * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
52923                *
52924                * The guarded methods are:
52925                * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
52926                * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
52927                * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
52928                * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
52929                *
52930                * @static
52931                * @memberOf _
52932                * @since 0.1.0
52933                * @category Collection
52934                * @param {Array|Object} collection The collection to iterate over.
52935                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
52936                * @returns {Array} Returns the new mapped array.
52937                * @example
52938                *
52939                * function square(n) {
52940                *   return n * n;
52941                * }
52942                *
52943                * _.map([4, 8], square);
52944                * // => [16, 64]
52945                *
52946                * _.map({ 'a': 4, 'b': 8 }, square);
52947                * // => [16, 64] (iteration order is not guaranteed)
52948                *
52949                * var users = [
52950                *   { 'user': 'barney' },
52951                *   { 'user': 'fred' }
52952                * ];
52953                *
52954                * // The `_.property` iteratee shorthand.
52955                * _.map(users, 'user');
52956                * // => ['barney', 'fred']
52957                */
52958
52959               function map(collection, iteratee) {
52960                 var func = isArray(collection) ? arrayMap : baseMap;
52961                 return func(collection, getIteratee(iteratee, 3));
52962               }
52963               /**
52964                * This method is like `_.sortBy` except that it allows specifying the sort
52965                * orders of the iteratees to sort by. If `orders` is unspecified, all values
52966                * are sorted in ascending order. Otherwise, specify an order of "desc" for
52967                * descending or "asc" for ascending sort order of corresponding values.
52968                *
52969                * @static
52970                * @memberOf _
52971                * @since 4.0.0
52972                * @category Collection
52973                * @param {Array|Object} collection The collection to iterate over.
52974                * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
52975                *  The iteratees to sort by.
52976                * @param {string[]} [orders] The sort orders of `iteratees`.
52977                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
52978                * @returns {Array} Returns the new sorted array.
52979                * @example
52980                *
52981                * var users = [
52982                *   { 'user': 'fred',   'age': 48 },
52983                *   { 'user': 'barney', 'age': 34 },
52984                *   { 'user': 'fred',   'age': 40 },
52985                *   { 'user': 'barney', 'age': 36 }
52986                * ];
52987                *
52988                * // Sort by `user` in ascending order and by `age` in descending order.
52989                * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
52990                * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
52991                */
52992
52993
52994               function orderBy(collection, iteratees, orders, guard) {
52995                 if (collection == null) {
52996                   return [];
52997                 }
52998
52999                 if (!isArray(iteratees)) {
53000                   iteratees = iteratees == null ? [] : [iteratees];
53001                 }
53002
53003                 orders = guard ? undefined$1 : orders;
53004
53005                 if (!isArray(orders)) {
53006                   orders = orders == null ? [] : [orders];
53007                 }
53008
53009                 return baseOrderBy(collection, iteratees, orders);
53010               }
53011               /**
53012                * Creates an array of elements split into two groups, the first of which
53013                * contains elements `predicate` returns truthy for, the second of which
53014                * contains elements `predicate` returns falsey for. The predicate is
53015                * invoked with one argument: (value).
53016                *
53017                * @static
53018                * @memberOf _
53019                * @since 3.0.0
53020                * @category Collection
53021                * @param {Array|Object} collection The collection to iterate over.
53022                * @param {Function} [predicate=_.identity] The function invoked per iteration.
53023                * @returns {Array} Returns the array of grouped elements.
53024                * @example
53025                *
53026                * var users = [
53027                *   { 'user': 'barney',  'age': 36, 'active': false },
53028                *   { 'user': 'fred',    'age': 40, 'active': true },
53029                *   { 'user': 'pebbles', 'age': 1,  'active': false }
53030                * ];
53031                *
53032                * _.partition(users, function(o) { return o.active; });
53033                * // => objects for [['fred'], ['barney', 'pebbles']]
53034                *
53035                * // The `_.matches` iteratee shorthand.
53036                * _.partition(users, { 'age': 1, 'active': false });
53037                * // => objects for [['pebbles'], ['barney', 'fred']]
53038                *
53039                * // The `_.matchesProperty` iteratee shorthand.
53040                * _.partition(users, ['active', false]);
53041                * // => objects for [['barney', 'pebbles'], ['fred']]
53042                *
53043                * // The `_.property` iteratee shorthand.
53044                * _.partition(users, 'active');
53045                * // => objects for [['fred'], ['barney', 'pebbles']]
53046                */
53047
53048
53049               var partition = createAggregator(function (result, value, key) {
53050                 result[key ? 0 : 1].push(value);
53051               }, function () {
53052                 return [[], []];
53053               });
53054               /**
53055                * Reduces `collection` to a value which is the accumulated result of running
53056                * each element in `collection` thru `iteratee`, where each successive
53057                * invocation is supplied the return value of the previous. If `accumulator`
53058                * is not given, the first element of `collection` is used as the initial
53059                * value. The iteratee is invoked with four arguments:
53060                * (accumulator, value, index|key, collection).
53061                *
53062                * Many lodash methods are guarded to work as iteratees for methods like
53063                * `_.reduce`, `_.reduceRight`, and `_.transform`.
53064                *
53065                * The guarded methods are:
53066                * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
53067                * and `sortBy`
53068                *
53069                * @static
53070                * @memberOf _
53071                * @since 0.1.0
53072                * @category Collection
53073                * @param {Array|Object} collection The collection to iterate over.
53074                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
53075                * @param {*} [accumulator] The initial value.
53076                * @returns {*} Returns the accumulated value.
53077                * @see _.reduceRight
53078                * @example
53079                *
53080                * _.reduce([1, 2], function(sum, n) {
53081                *   return sum + n;
53082                * }, 0);
53083                * // => 3
53084                *
53085                * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
53086                *   (result[value] || (result[value] = [])).push(key);
53087                *   return result;
53088                * }, {});
53089                * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
53090                */
53091
53092               function reduce(collection, iteratee, accumulator) {
53093                 var func = isArray(collection) ? arrayReduce : baseReduce,
53094                     initAccum = arguments.length < 3;
53095                 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
53096               }
53097               /**
53098                * This method is like `_.reduce` except that it iterates over elements of
53099                * `collection` from right to left.
53100                *
53101                * @static
53102                * @memberOf _
53103                * @since 0.1.0
53104                * @category Collection
53105                * @param {Array|Object} collection The collection to iterate over.
53106                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
53107                * @param {*} [accumulator] The initial value.
53108                * @returns {*} Returns the accumulated value.
53109                * @see _.reduce
53110                * @example
53111                *
53112                * var array = [[0, 1], [2, 3], [4, 5]];
53113                *
53114                * _.reduceRight(array, function(flattened, other) {
53115                *   return flattened.concat(other);
53116                * }, []);
53117                * // => [4, 5, 2, 3, 0, 1]
53118                */
53119
53120
53121               function reduceRight(collection, iteratee, accumulator) {
53122                 var func = isArray(collection) ? arrayReduceRight : baseReduce,
53123                     initAccum = arguments.length < 3;
53124                 return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
53125               }
53126               /**
53127                * The opposite of `_.filter`; this method returns the elements of `collection`
53128                * that `predicate` does **not** return truthy for.
53129                *
53130                * @static
53131                * @memberOf _
53132                * @since 0.1.0
53133                * @category Collection
53134                * @param {Array|Object} collection The collection to iterate over.
53135                * @param {Function} [predicate=_.identity] The function invoked per iteration.
53136                * @returns {Array} Returns the new filtered array.
53137                * @see _.filter
53138                * @example
53139                *
53140                * var users = [
53141                *   { 'user': 'barney', 'age': 36, 'active': false },
53142                *   { 'user': 'fred',   'age': 40, 'active': true }
53143                * ];
53144                *
53145                * _.reject(users, function(o) { return !o.active; });
53146                * // => objects for ['fred']
53147                *
53148                * // The `_.matches` iteratee shorthand.
53149                * _.reject(users, { 'age': 40, 'active': true });
53150                * // => objects for ['barney']
53151                *
53152                * // The `_.matchesProperty` iteratee shorthand.
53153                * _.reject(users, ['active', false]);
53154                * // => objects for ['fred']
53155                *
53156                * // The `_.property` iteratee shorthand.
53157                * _.reject(users, 'active');
53158                * // => objects for ['barney']
53159                */
53160
53161
53162               function reject(collection, predicate) {
53163                 var func = isArray(collection) ? arrayFilter : baseFilter;
53164                 return func(collection, negate(getIteratee(predicate, 3)));
53165               }
53166               /**
53167                * Gets a random element from `collection`.
53168                *
53169                * @static
53170                * @memberOf _
53171                * @since 2.0.0
53172                * @category Collection
53173                * @param {Array|Object} collection The collection to sample.
53174                * @returns {*} Returns the random element.
53175                * @example
53176                *
53177                * _.sample([1, 2, 3, 4]);
53178                * // => 2
53179                */
53180
53181
53182               function sample(collection) {
53183                 var func = isArray(collection) ? arraySample : baseSample;
53184                 return func(collection);
53185               }
53186               /**
53187                * Gets `n` random elements at unique keys from `collection` up to the
53188                * size of `collection`.
53189                *
53190                * @static
53191                * @memberOf _
53192                * @since 4.0.0
53193                * @category Collection
53194                * @param {Array|Object} collection The collection to sample.
53195                * @param {number} [n=1] The number of elements to sample.
53196                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53197                * @returns {Array} Returns the random elements.
53198                * @example
53199                *
53200                * _.sampleSize([1, 2, 3], 2);
53201                * // => [3, 1]
53202                *
53203                * _.sampleSize([1, 2, 3], 4);
53204                * // => [2, 3, 1]
53205                */
53206
53207
53208               function sampleSize(collection, n, guard) {
53209                 if (guard ? isIterateeCall(collection, n, guard) : n === undefined$1) {
53210                   n = 1;
53211                 } else {
53212                   n = toInteger(n);
53213                 }
53214
53215                 var func = isArray(collection) ? arraySampleSize : baseSampleSize;
53216                 return func(collection, n);
53217               }
53218               /**
53219                * Creates an array of shuffled values, using a version of the
53220                * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
53221                *
53222                * @static
53223                * @memberOf _
53224                * @since 0.1.0
53225                * @category Collection
53226                * @param {Array|Object} collection The collection to shuffle.
53227                * @returns {Array} Returns the new shuffled array.
53228                * @example
53229                *
53230                * _.shuffle([1, 2, 3, 4]);
53231                * // => [4, 1, 3, 2]
53232                */
53233
53234
53235               function shuffle(collection) {
53236                 var func = isArray(collection) ? arrayShuffle : baseShuffle;
53237                 return func(collection);
53238               }
53239               /**
53240                * Gets the size of `collection` by returning its length for array-like
53241                * values or the number of own enumerable string keyed properties for objects.
53242                *
53243                * @static
53244                * @memberOf _
53245                * @since 0.1.0
53246                * @category Collection
53247                * @param {Array|Object|string} collection The collection to inspect.
53248                * @returns {number} Returns the collection size.
53249                * @example
53250                *
53251                * _.size([1, 2, 3]);
53252                * // => 3
53253                *
53254                * _.size({ 'a': 1, 'b': 2 });
53255                * // => 2
53256                *
53257                * _.size('pebbles');
53258                * // => 7
53259                */
53260
53261
53262               function size(collection) {
53263                 if (collection == null) {
53264                   return 0;
53265                 }
53266
53267                 if (isArrayLike(collection)) {
53268                   return isString(collection) ? stringSize(collection) : collection.length;
53269                 }
53270
53271                 var tag = getTag(collection);
53272
53273                 if (tag == mapTag || tag == setTag) {
53274                   return collection.size;
53275                 }
53276
53277                 return baseKeys(collection).length;
53278               }
53279               /**
53280                * Checks if `predicate` returns truthy for **any** element of `collection`.
53281                * Iteration is stopped once `predicate` returns truthy. The predicate is
53282                * invoked with three arguments: (value, index|key, collection).
53283                *
53284                * @static
53285                * @memberOf _
53286                * @since 0.1.0
53287                * @category Collection
53288                * @param {Array|Object} collection The collection to iterate over.
53289                * @param {Function} [predicate=_.identity] The function invoked per iteration.
53290                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53291                * @returns {boolean} Returns `true` if any element passes the predicate check,
53292                *  else `false`.
53293                * @example
53294                *
53295                * _.some([null, 0, 'yes', false], Boolean);
53296                * // => true
53297                *
53298                * var users = [
53299                *   { 'user': 'barney', 'active': true },
53300                *   { 'user': 'fred',   'active': false }
53301                * ];
53302                *
53303                * // The `_.matches` iteratee shorthand.
53304                * _.some(users, { 'user': 'barney', 'active': false });
53305                * // => false
53306                *
53307                * // The `_.matchesProperty` iteratee shorthand.
53308                * _.some(users, ['active', false]);
53309                * // => true
53310                *
53311                * // The `_.property` iteratee shorthand.
53312                * _.some(users, 'active');
53313                * // => true
53314                */
53315
53316
53317               function some(collection, predicate, guard) {
53318                 var func = isArray(collection) ? arraySome : baseSome;
53319
53320                 if (guard && isIterateeCall(collection, predicate, guard)) {
53321                   predicate = undefined$1;
53322                 }
53323
53324                 return func(collection, getIteratee(predicate, 3));
53325               }
53326               /**
53327                * Creates an array of elements, sorted in ascending order by the results of
53328                * running each element in a collection thru each iteratee. This method
53329                * performs a stable sort, that is, it preserves the original sort order of
53330                * equal elements. The iteratees are invoked with one argument: (value).
53331                *
53332                * @static
53333                * @memberOf _
53334                * @since 0.1.0
53335                * @category Collection
53336                * @param {Array|Object} collection The collection to iterate over.
53337                * @param {...(Function|Function[])} [iteratees=[_.identity]]
53338                *  The iteratees to sort by.
53339                * @returns {Array} Returns the new sorted array.
53340                * @example
53341                *
53342                * var users = [
53343                *   { 'user': 'fred',   'age': 48 },
53344                *   { 'user': 'barney', 'age': 36 },
53345                *   { 'user': 'fred',   'age': 30 },
53346                *   { 'user': 'barney', 'age': 34 }
53347                * ];
53348                *
53349                * _.sortBy(users, [function(o) { return o.user; }]);
53350                * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 30]]
53351                *
53352                * _.sortBy(users, ['user', 'age']);
53353                * // => objects for [['barney', 34], ['barney', 36], ['fred', 30], ['fred', 48]]
53354                */
53355
53356
53357               var sortBy = baseRest(function (collection, iteratees) {
53358                 if (collection == null) {
53359                   return [];
53360                 }
53361
53362                 var length = iteratees.length;
53363
53364                 if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
53365                   iteratees = [];
53366                 } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
53367                   iteratees = [iteratees[0]];
53368                 }
53369
53370                 return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
53371               });
53372               /*------------------------------------------------------------------------*/
53373
53374               /**
53375                * Gets the timestamp of the number of milliseconds that have elapsed since
53376                * the Unix epoch (1 January 1970 00:00:00 UTC).
53377                *
53378                * @static
53379                * @memberOf _
53380                * @since 2.4.0
53381                * @category Date
53382                * @returns {number} Returns the timestamp.
53383                * @example
53384                *
53385                * _.defer(function(stamp) {
53386                *   console.log(_.now() - stamp);
53387                * }, _.now());
53388                * // => Logs the number of milliseconds it took for the deferred invocation.
53389                */
53390
53391               var now = ctxNow || function () {
53392                 return root.Date.now();
53393               };
53394               /*------------------------------------------------------------------------*/
53395
53396               /**
53397                * The opposite of `_.before`; this method creates a function that invokes
53398                * `func` once it's called `n` or more times.
53399                *
53400                * @static
53401                * @memberOf _
53402                * @since 0.1.0
53403                * @category Function
53404                * @param {number} n The number of calls before `func` is invoked.
53405                * @param {Function} func The function to restrict.
53406                * @returns {Function} Returns the new restricted function.
53407                * @example
53408                *
53409                * var saves = ['profile', 'settings'];
53410                *
53411                * var done = _.after(saves.length, function() {
53412                *   console.log('done saving!');
53413                * });
53414                *
53415                * _.forEach(saves, function(type) {
53416                *   asyncSave({ 'type': type, 'complete': done });
53417                * });
53418                * // => Logs 'done saving!' after the two async saves have completed.
53419                */
53420
53421
53422               function after(n, func) {
53423                 if (typeof func != 'function') {
53424                   throw new TypeError(FUNC_ERROR_TEXT);
53425                 }
53426
53427                 n = toInteger(n);
53428                 return function () {
53429                   if (--n < 1) {
53430                     return func.apply(this, arguments);
53431                   }
53432                 };
53433               }
53434               /**
53435                * Creates a function that invokes `func`, with up to `n` arguments,
53436                * ignoring any additional arguments.
53437                *
53438                * @static
53439                * @memberOf _
53440                * @since 3.0.0
53441                * @category Function
53442                * @param {Function} func The function to cap arguments for.
53443                * @param {number} [n=func.length] The arity cap.
53444                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53445                * @returns {Function} Returns the new capped function.
53446                * @example
53447                *
53448                * _.map(['6', '8', '10'], _.ary(parseInt, 1));
53449                * // => [6, 8, 10]
53450                */
53451
53452
53453               function ary(func, n, guard) {
53454                 n = guard ? undefined$1 : n;
53455                 n = func && n == null ? func.length : n;
53456                 return createWrap(func, WRAP_ARY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, n);
53457               }
53458               /**
53459                * Creates a function that invokes `func`, with the `this` binding and arguments
53460                * of the created function, while it's called less than `n` times. Subsequent
53461                * calls to the created function return the result of the last `func` invocation.
53462                *
53463                * @static
53464                * @memberOf _
53465                * @since 3.0.0
53466                * @category Function
53467                * @param {number} n The number of calls at which `func` is no longer invoked.
53468                * @param {Function} func The function to restrict.
53469                * @returns {Function} Returns the new restricted function.
53470                * @example
53471                *
53472                * jQuery(element).on('click', _.before(5, addContactToList));
53473                * // => Allows adding up to 4 contacts to the list.
53474                */
53475
53476
53477               function before(n, func) {
53478                 var result;
53479
53480                 if (typeof func != 'function') {
53481                   throw new TypeError(FUNC_ERROR_TEXT);
53482                 }
53483
53484                 n = toInteger(n);
53485                 return function () {
53486                   if (--n > 0) {
53487                     result = func.apply(this, arguments);
53488                   }
53489
53490                   if (n <= 1) {
53491                     func = undefined$1;
53492                   }
53493
53494                   return result;
53495                 };
53496               }
53497               /**
53498                * Creates a function that invokes `func` with the `this` binding of `thisArg`
53499                * and `partials` prepended to the arguments it receives.
53500                *
53501                * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
53502                * may be used as a placeholder for partially applied arguments.
53503                *
53504                * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
53505                * property of bound functions.
53506                *
53507                * @static
53508                * @memberOf _
53509                * @since 0.1.0
53510                * @category Function
53511                * @param {Function} func The function to bind.
53512                * @param {*} thisArg The `this` binding of `func`.
53513                * @param {...*} [partials] The arguments to be partially applied.
53514                * @returns {Function} Returns the new bound function.
53515                * @example
53516                *
53517                * function greet(greeting, punctuation) {
53518                *   return greeting + ' ' + this.user + punctuation;
53519                * }
53520                *
53521                * var object = { 'user': 'fred' };
53522                *
53523                * var bound = _.bind(greet, object, 'hi');
53524                * bound('!');
53525                * // => 'hi fred!'
53526                *
53527                * // Bound with placeholders.
53528                * var bound = _.bind(greet, object, _, '!');
53529                * bound('hi');
53530                * // => 'hi fred!'
53531                */
53532
53533
53534               var bind = baseRest(function (func, thisArg, partials) {
53535                 var bitmask = WRAP_BIND_FLAG;
53536
53537                 if (partials.length) {
53538                   var holders = replaceHolders(partials, getHolder(bind));
53539                   bitmask |= WRAP_PARTIAL_FLAG;
53540                 }
53541
53542                 return createWrap(func, bitmask, thisArg, partials, holders);
53543               });
53544               /**
53545                * Creates a function that invokes the method at `object[key]` with `partials`
53546                * prepended to the arguments it receives.
53547                *
53548                * This method differs from `_.bind` by allowing bound functions to reference
53549                * methods that may be redefined or don't yet exist. See
53550                * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
53551                * for more details.
53552                *
53553                * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
53554                * builds, may be used as a placeholder for partially applied arguments.
53555                *
53556                * @static
53557                * @memberOf _
53558                * @since 0.10.0
53559                * @category Function
53560                * @param {Object} object The object to invoke the method on.
53561                * @param {string} key The key of the method.
53562                * @param {...*} [partials] The arguments to be partially applied.
53563                * @returns {Function} Returns the new bound function.
53564                * @example
53565                *
53566                * var object = {
53567                *   'user': 'fred',
53568                *   'greet': function(greeting, punctuation) {
53569                *     return greeting + ' ' + this.user + punctuation;
53570                *   }
53571                * };
53572                *
53573                * var bound = _.bindKey(object, 'greet', 'hi');
53574                * bound('!');
53575                * // => 'hi fred!'
53576                *
53577                * object.greet = function(greeting, punctuation) {
53578                *   return greeting + 'ya ' + this.user + punctuation;
53579                * };
53580                *
53581                * bound('!');
53582                * // => 'hiya fred!'
53583                *
53584                * // Bound with placeholders.
53585                * var bound = _.bindKey(object, 'greet', _, '!');
53586                * bound('hi');
53587                * // => 'hiya fred!'
53588                */
53589
53590               var bindKey = baseRest(function (object, key, partials) {
53591                 var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
53592
53593                 if (partials.length) {
53594                   var holders = replaceHolders(partials, getHolder(bindKey));
53595                   bitmask |= WRAP_PARTIAL_FLAG;
53596                 }
53597
53598                 return createWrap(key, bitmask, object, partials, holders);
53599               });
53600               /**
53601                * Creates a function that accepts arguments of `func` and either invokes
53602                * `func` returning its result, if at least `arity` number of arguments have
53603                * been provided, or returns a function that accepts the remaining `func`
53604                * arguments, and so on. The arity of `func` may be specified if `func.length`
53605                * is not sufficient.
53606                *
53607                * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
53608                * may be used as a placeholder for provided arguments.
53609                *
53610                * **Note:** This method doesn't set the "length" property of curried functions.
53611                *
53612                * @static
53613                * @memberOf _
53614                * @since 2.0.0
53615                * @category Function
53616                * @param {Function} func The function to curry.
53617                * @param {number} [arity=func.length] The arity of `func`.
53618                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53619                * @returns {Function} Returns the new curried function.
53620                * @example
53621                *
53622                * var abc = function(a, b, c) {
53623                *   return [a, b, c];
53624                * };
53625                *
53626                * var curried = _.curry(abc);
53627                *
53628                * curried(1)(2)(3);
53629                * // => [1, 2, 3]
53630                *
53631                * curried(1, 2)(3);
53632                * // => [1, 2, 3]
53633                *
53634                * curried(1, 2, 3);
53635                * // => [1, 2, 3]
53636                *
53637                * // Curried with placeholders.
53638                * curried(1)(_, 3)(2);
53639                * // => [1, 2, 3]
53640                */
53641
53642               function curry(func, arity, guard) {
53643                 arity = guard ? undefined$1 : arity;
53644                 var result = createWrap(func, WRAP_CURRY_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity);
53645                 result.placeholder = curry.placeholder;
53646                 return result;
53647               }
53648               /**
53649                * This method is like `_.curry` except that arguments are applied to `func`
53650                * in the manner of `_.partialRight` instead of `_.partial`.
53651                *
53652                * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
53653                * builds, may be used as a placeholder for provided arguments.
53654                *
53655                * **Note:** This method doesn't set the "length" property of curried functions.
53656                *
53657                * @static
53658                * @memberOf _
53659                * @since 3.0.0
53660                * @category Function
53661                * @param {Function} func The function to curry.
53662                * @param {number} [arity=func.length] The arity of `func`.
53663                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
53664                * @returns {Function} Returns the new curried function.
53665                * @example
53666                *
53667                * var abc = function(a, b, c) {
53668                *   return [a, b, c];
53669                * };
53670                *
53671                * var curried = _.curryRight(abc);
53672                *
53673                * curried(3)(2)(1);
53674                * // => [1, 2, 3]
53675                *
53676                * curried(2, 3)(1);
53677                * // => [1, 2, 3]
53678                *
53679                * curried(1, 2, 3);
53680                * // => [1, 2, 3]
53681                *
53682                * // Curried with placeholders.
53683                * curried(3)(1, _)(2);
53684                * // => [1, 2, 3]
53685                */
53686
53687
53688               function curryRight(func, arity, guard) {
53689                 arity = guard ? undefined$1 : arity;
53690                 var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined$1, undefined$1, undefined$1, undefined$1, undefined$1, arity);
53691                 result.placeholder = curryRight.placeholder;
53692                 return result;
53693               }
53694               /**
53695                * Creates a debounced function that delays invoking `func` until after `wait`
53696                * milliseconds have elapsed since the last time the debounced function was
53697                * invoked. The debounced function comes with a `cancel` method to cancel
53698                * delayed `func` invocations and a `flush` method to immediately invoke them.
53699                * Provide `options` to indicate whether `func` should be invoked on the
53700                * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
53701                * with the last arguments provided to the debounced function. Subsequent
53702                * calls to the debounced function return the result of the last `func`
53703                * invocation.
53704                *
53705                * **Note:** If `leading` and `trailing` options are `true`, `func` is
53706                * invoked on the trailing edge of the timeout only if the debounced function
53707                * is invoked more than once during the `wait` timeout.
53708                *
53709                * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
53710                * until to the next tick, similar to `setTimeout` with a timeout of `0`.
53711                *
53712                * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
53713                * for details over the differences between `_.debounce` and `_.throttle`.
53714                *
53715                * @static
53716                * @memberOf _
53717                * @since 0.1.0
53718                * @category Function
53719                * @param {Function} func The function to debounce.
53720                * @param {number} [wait=0] The number of milliseconds to delay.
53721                * @param {Object} [options={}] The options object.
53722                * @param {boolean} [options.leading=false]
53723                *  Specify invoking on the leading edge of the timeout.
53724                * @param {number} [options.maxWait]
53725                *  The maximum time `func` is allowed to be delayed before it's invoked.
53726                * @param {boolean} [options.trailing=true]
53727                *  Specify invoking on the trailing edge of the timeout.
53728                * @returns {Function} Returns the new debounced function.
53729                * @example
53730                *
53731                * // Avoid costly calculations while the window size is in flux.
53732                * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
53733                *
53734                * // Invoke `sendMail` when clicked, debouncing subsequent calls.
53735                * jQuery(element).on('click', _.debounce(sendMail, 300, {
53736                *   'leading': true,
53737                *   'trailing': false
53738                * }));
53739                *
53740                * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
53741                * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
53742                * var source = new EventSource('/stream');
53743                * jQuery(source).on('message', debounced);
53744                *
53745                * // Cancel the trailing debounced invocation.
53746                * jQuery(window).on('popstate', debounced.cancel);
53747                */
53748
53749
53750               function debounce(func, wait, options) {
53751                 var lastArgs,
53752                     lastThis,
53753                     maxWait,
53754                     result,
53755                     timerId,
53756                     lastCallTime,
53757                     lastInvokeTime = 0,
53758                     leading = false,
53759                     maxing = false,
53760                     trailing = true;
53761
53762                 if (typeof func != 'function') {
53763                   throw new TypeError(FUNC_ERROR_TEXT);
53764                 }
53765
53766                 wait = toNumber(wait) || 0;
53767
53768                 if (isObject(options)) {
53769                   leading = !!options.leading;
53770                   maxing = 'maxWait' in options;
53771                   maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
53772                   trailing = 'trailing' in options ? !!options.trailing : trailing;
53773                 }
53774
53775                 function invokeFunc(time) {
53776                   var args = lastArgs,
53777                       thisArg = lastThis;
53778                   lastArgs = lastThis = undefined$1;
53779                   lastInvokeTime = time;
53780                   result = func.apply(thisArg, args);
53781                   return result;
53782                 }
53783
53784                 function leadingEdge(time) {
53785                   // Reset any `maxWait` timer.
53786                   lastInvokeTime = time; // Start the timer for the trailing edge.
53787
53788                   timerId = setTimeout(timerExpired, wait); // Invoke the leading edge.
53789
53790                   return leading ? invokeFunc(time) : result;
53791                 }
53792
53793                 function remainingWait(time) {
53794                   var timeSinceLastCall = time - lastCallTime,
53795                       timeSinceLastInvoke = time - lastInvokeTime,
53796                       timeWaiting = wait - timeSinceLastCall;
53797                   return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
53798                 }
53799
53800                 function shouldInvoke(time) {
53801                   var timeSinceLastCall = time - lastCallTime,
53802                       timeSinceLastInvoke = time - lastInvokeTime; // Either this is the first call, activity has stopped and we're at the
53803                   // trailing edge, the system time has gone backwards and we're treating
53804                   // it as the trailing edge, or we've hit the `maxWait` limit.
53805
53806                   return lastCallTime === undefined$1 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
53807                 }
53808
53809                 function timerExpired() {
53810                   var time = now();
53811
53812                   if (shouldInvoke(time)) {
53813                     return trailingEdge(time);
53814                   } // Restart the timer.
53815
53816
53817                   timerId = setTimeout(timerExpired, remainingWait(time));
53818                 }
53819
53820                 function trailingEdge(time) {
53821                   timerId = undefined$1; // Only invoke if we have `lastArgs` which means `func` has been
53822                   // debounced at least once.
53823
53824                   if (trailing && lastArgs) {
53825                     return invokeFunc(time);
53826                   }
53827
53828                   lastArgs = lastThis = undefined$1;
53829                   return result;
53830                 }
53831
53832                 function cancel() {
53833                   if (timerId !== undefined$1) {
53834                     clearTimeout(timerId);
53835                   }
53836
53837                   lastInvokeTime = 0;
53838                   lastArgs = lastCallTime = lastThis = timerId = undefined$1;
53839                 }
53840
53841                 function flush() {
53842                   return timerId === undefined$1 ? result : trailingEdge(now());
53843                 }
53844
53845                 function debounced() {
53846                   var time = now(),
53847                       isInvoking = shouldInvoke(time);
53848                   lastArgs = arguments;
53849                   lastThis = this;
53850                   lastCallTime = time;
53851
53852                   if (isInvoking) {
53853                     if (timerId === undefined$1) {
53854                       return leadingEdge(lastCallTime);
53855                     }
53856
53857                     if (maxing) {
53858                       // Handle invocations in a tight loop.
53859                       clearTimeout(timerId);
53860                       timerId = setTimeout(timerExpired, wait);
53861                       return invokeFunc(lastCallTime);
53862                     }
53863                   }
53864
53865                   if (timerId === undefined$1) {
53866                     timerId = setTimeout(timerExpired, wait);
53867                   }
53868
53869                   return result;
53870                 }
53871
53872                 debounced.cancel = cancel;
53873                 debounced.flush = flush;
53874                 return debounced;
53875               }
53876               /**
53877                * Defers invoking the `func` until the current call stack has cleared. Any
53878                * additional arguments are provided to `func` when it's invoked.
53879                *
53880                * @static
53881                * @memberOf _
53882                * @since 0.1.0
53883                * @category Function
53884                * @param {Function} func The function to defer.
53885                * @param {...*} [args] The arguments to invoke `func` with.
53886                * @returns {number} Returns the timer id.
53887                * @example
53888                *
53889                * _.defer(function(text) {
53890                *   console.log(text);
53891                * }, 'deferred');
53892                * // => Logs 'deferred' after one millisecond.
53893                */
53894
53895
53896               var defer = baseRest(function (func, args) {
53897                 return baseDelay(func, 1, args);
53898               });
53899               /**
53900                * Invokes `func` after `wait` milliseconds. Any additional arguments are
53901                * provided to `func` when it's invoked.
53902                *
53903                * @static
53904                * @memberOf _
53905                * @since 0.1.0
53906                * @category Function
53907                * @param {Function} func The function to delay.
53908                * @param {number} wait The number of milliseconds to delay invocation.
53909                * @param {...*} [args] The arguments to invoke `func` with.
53910                * @returns {number} Returns the timer id.
53911                * @example
53912                *
53913                * _.delay(function(text) {
53914                *   console.log(text);
53915                * }, 1000, 'later');
53916                * // => Logs 'later' after one second.
53917                */
53918
53919               var delay = baseRest(function (func, wait, args) {
53920                 return baseDelay(func, toNumber(wait) || 0, args);
53921               });
53922               /**
53923                * Creates a function that invokes `func` with arguments reversed.
53924                *
53925                * @static
53926                * @memberOf _
53927                * @since 4.0.0
53928                * @category Function
53929                * @param {Function} func The function to flip arguments for.
53930                * @returns {Function} Returns the new flipped function.
53931                * @example
53932                *
53933                * var flipped = _.flip(function() {
53934                *   return _.toArray(arguments);
53935                * });
53936                *
53937                * flipped('a', 'b', 'c', 'd');
53938                * // => ['d', 'c', 'b', 'a']
53939                */
53940
53941               function flip(func) {
53942                 return createWrap(func, WRAP_FLIP_FLAG);
53943               }
53944               /**
53945                * Creates a function that memoizes the result of `func`. If `resolver` is
53946                * provided, it determines the cache key for storing the result based on the
53947                * arguments provided to the memoized function. By default, the first argument
53948                * provided to the memoized function is used as the map cache key. The `func`
53949                * is invoked with the `this` binding of the memoized function.
53950                *
53951                * **Note:** The cache is exposed as the `cache` property on the memoized
53952                * function. Its creation may be customized by replacing the `_.memoize.Cache`
53953                * constructor with one whose instances implement the
53954                * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
53955                * method interface of `clear`, `delete`, `get`, `has`, and `set`.
53956                *
53957                * @static
53958                * @memberOf _
53959                * @since 0.1.0
53960                * @category Function
53961                * @param {Function} func The function to have its output memoized.
53962                * @param {Function} [resolver] The function to resolve the cache key.
53963                * @returns {Function} Returns the new memoized function.
53964                * @example
53965                *
53966                * var object = { 'a': 1, 'b': 2 };
53967                * var other = { 'c': 3, 'd': 4 };
53968                *
53969                * var values = _.memoize(_.values);
53970                * values(object);
53971                * // => [1, 2]
53972                *
53973                * values(other);
53974                * // => [3, 4]
53975                *
53976                * object.a = 2;
53977                * values(object);
53978                * // => [1, 2]
53979                *
53980                * // Modify the result cache.
53981                * values.cache.set(object, ['a', 'b']);
53982                * values(object);
53983                * // => ['a', 'b']
53984                *
53985                * // Replace `_.memoize.Cache`.
53986                * _.memoize.Cache = WeakMap;
53987                */
53988
53989
53990               function memoize(func, resolver) {
53991                 if (typeof func != 'function' || resolver != null && typeof resolver != 'function') {
53992                   throw new TypeError(FUNC_ERROR_TEXT);
53993                 }
53994
53995                 var memoized = function memoized() {
53996                   var args = arguments,
53997                       key = resolver ? resolver.apply(this, args) : args[0],
53998                       cache = memoized.cache;
53999
54000                   if (cache.has(key)) {
54001                     return cache.get(key);
54002                   }
54003
54004                   var result = func.apply(this, args);
54005                   memoized.cache = cache.set(key, result) || cache;
54006                   return result;
54007                 };
54008
54009                 memoized.cache = new (memoize.Cache || MapCache)();
54010                 return memoized;
54011               } // Expose `MapCache`.
54012
54013
54014               memoize.Cache = MapCache;
54015               /**
54016                * Creates a function that negates the result of the predicate `func`. The
54017                * `func` predicate is invoked with the `this` binding and arguments of the
54018                * created function.
54019                *
54020                * @static
54021                * @memberOf _
54022                * @since 3.0.0
54023                * @category Function
54024                * @param {Function} predicate The predicate to negate.
54025                * @returns {Function} Returns the new negated function.
54026                * @example
54027                *
54028                * function isEven(n) {
54029                *   return n % 2 == 0;
54030                * }
54031                *
54032                * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
54033                * // => [1, 3, 5]
54034                */
54035
54036               function negate(predicate) {
54037                 if (typeof predicate != 'function') {
54038                   throw new TypeError(FUNC_ERROR_TEXT);
54039                 }
54040
54041                 return function () {
54042                   var args = arguments;
54043
54044                   switch (args.length) {
54045                     case 0:
54046                       return !predicate.call(this);
54047
54048                     case 1:
54049                       return !predicate.call(this, args[0]);
54050
54051                     case 2:
54052                       return !predicate.call(this, args[0], args[1]);
54053
54054                     case 3:
54055                       return !predicate.call(this, args[0], args[1], args[2]);
54056                   }
54057
54058                   return !predicate.apply(this, args);
54059                 };
54060               }
54061               /**
54062                * Creates a function that is restricted to invoking `func` once. Repeat calls
54063                * to the function return the value of the first invocation. The `func` is
54064                * invoked with the `this` binding and arguments of the created function.
54065                *
54066                * @static
54067                * @memberOf _
54068                * @since 0.1.0
54069                * @category Function
54070                * @param {Function} func The function to restrict.
54071                * @returns {Function} Returns the new restricted function.
54072                * @example
54073                *
54074                * var initialize = _.once(createApplication);
54075                * initialize();
54076                * initialize();
54077                * // => `createApplication` is invoked once
54078                */
54079
54080
54081               function once(func) {
54082                 return before(2, func);
54083               }
54084               /**
54085                * Creates a function that invokes `func` with its arguments transformed.
54086                *
54087                * @static
54088                * @since 4.0.0
54089                * @memberOf _
54090                * @category Function
54091                * @param {Function} func The function to wrap.
54092                * @param {...(Function|Function[])} [transforms=[_.identity]]
54093                *  The argument transforms.
54094                * @returns {Function} Returns the new function.
54095                * @example
54096                *
54097                * function doubled(n) {
54098                *   return n * 2;
54099                * }
54100                *
54101                * function square(n) {
54102                *   return n * n;
54103                * }
54104                *
54105                * var func = _.overArgs(function(x, y) {
54106                *   return [x, y];
54107                * }, [square, doubled]);
54108                *
54109                * func(9, 3);
54110                * // => [81, 6]
54111                *
54112                * func(10, 5);
54113                * // => [100, 10]
54114                */
54115
54116
54117               var overArgs = castRest(function (func, transforms) {
54118                 transforms = transforms.length == 1 && isArray(transforms[0]) ? arrayMap(transforms[0], baseUnary(getIteratee())) : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
54119                 var funcsLength = transforms.length;
54120                 return baseRest(function (args) {
54121                   var index = -1,
54122                       length = nativeMin(args.length, funcsLength);
54123
54124                   while (++index < length) {
54125                     args[index] = transforms[index].call(this, args[index]);
54126                   }
54127
54128                   return apply(func, this, args);
54129                 });
54130               });
54131               /**
54132                * Creates a function that invokes `func` with `partials` prepended to the
54133                * arguments it receives. This method is like `_.bind` except it does **not**
54134                * alter the `this` binding.
54135                *
54136                * The `_.partial.placeholder` value, which defaults to `_` in monolithic
54137                * builds, may be used as a placeholder for partially applied arguments.
54138                *
54139                * **Note:** This method doesn't set the "length" property of partially
54140                * applied functions.
54141                *
54142                * @static
54143                * @memberOf _
54144                * @since 0.2.0
54145                * @category Function
54146                * @param {Function} func The function to partially apply arguments to.
54147                * @param {...*} [partials] The arguments to be partially applied.
54148                * @returns {Function} Returns the new partially applied function.
54149                * @example
54150                *
54151                * function greet(greeting, name) {
54152                *   return greeting + ' ' + name;
54153                * }
54154                *
54155                * var sayHelloTo = _.partial(greet, 'hello');
54156                * sayHelloTo('fred');
54157                * // => 'hello fred'
54158                *
54159                * // Partially applied with placeholders.
54160                * var greetFred = _.partial(greet, _, 'fred');
54161                * greetFred('hi');
54162                * // => 'hi fred'
54163                */
54164
54165               var partial = baseRest(function (func, partials) {
54166                 var holders = replaceHolders(partials, getHolder(partial));
54167                 return createWrap(func, WRAP_PARTIAL_FLAG, undefined$1, partials, holders);
54168               });
54169               /**
54170                * This method is like `_.partial` except that partially applied arguments
54171                * are appended to the arguments it receives.
54172                *
54173                * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
54174                * builds, may be used as a placeholder for partially applied arguments.
54175                *
54176                * **Note:** This method doesn't set the "length" property of partially
54177                * applied functions.
54178                *
54179                * @static
54180                * @memberOf _
54181                * @since 1.0.0
54182                * @category Function
54183                * @param {Function} func The function to partially apply arguments to.
54184                * @param {...*} [partials] The arguments to be partially applied.
54185                * @returns {Function} Returns the new partially applied function.
54186                * @example
54187                *
54188                * function greet(greeting, name) {
54189                *   return greeting + ' ' + name;
54190                * }
54191                *
54192                * var greetFred = _.partialRight(greet, 'fred');
54193                * greetFred('hi');
54194                * // => 'hi fred'
54195                *
54196                * // Partially applied with placeholders.
54197                * var sayHelloTo = _.partialRight(greet, 'hello', _);
54198                * sayHelloTo('fred');
54199                * // => 'hello fred'
54200                */
54201
54202               var partialRight = baseRest(function (func, partials) {
54203                 var holders = replaceHolders(partials, getHolder(partialRight));
54204                 return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined$1, partials, holders);
54205               });
54206               /**
54207                * Creates a function that invokes `func` with arguments arranged according
54208                * to the specified `indexes` where the argument value at the first index is
54209                * provided as the first argument, the argument value at the second index is
54210                * provided as the second argument, and so on.
54211                *
54212                * @static
54213                * @memberOf _
54214                * @since 3.0.0
54215                * @category Function
54216                * @param {Function} func The function to rearrange arguments for.
54217                * @param {...(number|number[])} indexes The arranged argument indexes.
54218                * @returns {Function} Returns the new function.
54219                * @example
54220                *
54221                * var rearged = _.rearg(function(a, b, c) {
54222                *   return [a, b, c];
54223                * }, [2, 0, 1]);
54224                *
54225                * rearged('b', 'c', 'a')
54226                * // => ['a', 'b', 'c']
54227                */
54228
54229               var rearg = flatRest(function (func, indexes) {
54230                 return createWrap(func, WRAP_REARG_FLAG, undefined$1, undefined$1, undefined$1, indexes);
54231               });
54232               /**
54233                * Creates a function that invokes `func` with the `this` binding of the
54234                * created function and arguments from `start` and beyond provided as
54235                * an array.
54236                *
54237                * **Note:** This method is based on the
54238                * [rest parameter](https://mdn.io/rest_parameters).
54239                *
54240                * @static
54241                * @memberOf _
54242                * @since 4.0.0
54243                * @category Function
54244                * @param {Function} func The function to apply a rest parameter to.
54245                * @param {number} [start=func.length-1] The start position of the rest parameter.
54246                * @returns {Function} Returns the new function.
54247                * @example
54248                *
54249                * var say = _.rest(function(what, names) {
54250                *   return what + ' ' + _.initial(names).join(', ') +
54251                *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
54252                * });
54253                *
54254                * say('hello', 'fred', 'barney', 'pebbles');
54255                * // => 'hello fred, barney, & pebbles'
54256                */
54257
54258               function rest(func, start) {
54259                 if (typeof func != 'function') {
54260                   throw new TypeError(FUNC_ERROR_TEXT);
54261                 }
54262
54263                 start = start === undefined$1 ? start : toInteger(start);
54264                 return baseRest(func, start);
54265               }
54266               /**
54267                * Creates a function that invokes `func` with the `this` binding of the
54268                * create function and an array of arguments much like
54269                * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
54270                *
54271                * **Note:** This method is based on the
54272                * [spread operator](https://mdn.io/spread_operator).
54273                *
54274                * @static
54275                * @memberOf _
54276                * @since 3.2.0
54277                * @category Function
54278                * @param {Function} func The function to spread arguments over.
54279                * @param {number} [start=0] The start position of the spread.
54280                * @returns {Function} Returns the new function.
54281                * @example
54282                *
54283                * var say = _.spread(function(who, what) {
54284                *   return who + ' says ' + what;
54285                * });
54286                *
54287                * say(['fred', 'hello']);
54288                * // => 'fred says hello'
54289                *
54290                * var numbers = Promise.all([
54291                *   Promise.resolve(40),
54292                *   Promise.resolve(36)
54293                * ]);
54294                *
54295                * numbers.then(_.spread(function(x, y) {
54296                *   return x + y;
54297                * }));
54298                * // => a Promise of 76
54299                */
54300
54301
54302               function spread(func, start) {
54303                 if (typeof func != 'function') {
54304                   throw new TypeError(FUNC_ERROR_TEXT);
54305                 }
54306
54307                 start = start == null ? 0 : nativeMax(toInteger(start), 0);
54308                 return baseRest(function (args) {
54309                   var array = args[start],
54310                       otherArgs = castSlice(args, 0, start);
54311
54312                   if (array) {
54313                     arrayPush(otherArgs, array);
54314                   }
54315
54316                   return apply(func, this, otherArgs);
54317                 });
54318               }
54319               /**
54320                * Creates a throttled function that only invokes `func` at most once per
54321                * every `wait` milliseconds. The throttled function comes with a `cancel`
54322                * method to cancel delayed `func` invocations and a `flush` method to
54323                * immediately invoke them. Provide `options` to indicate whether `func`
54324                * should be invoked on the leading and/or trailing edge of the `wait`
54325                * timeout. The `func` is invoked with the last arguments provided to the
54326                * throttled function. Subsequent calls to the throttled function return the
54327                * result of the last `func` invocation.
54328                *
54329                * **Note:** If `leading` and `trailing` options are `true`, `func` is
54330                * invoked on the trailing edge of the timeout only if the throttled function
54331                * is invoked more than once during the `wait` timeout.
54332                *
54333                * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
54334                * until to the next tick, similar to `setTimeout` with a timeout of `0`.
54335                *
54336                * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
54337                * for details over the differences between `_.throttle` and `_.debounce`.
54338                *
54339                * @static
54340                * @memberOf _
54341                * @since 0.1.0
54342                * @category Function
54343                * @param {Function} func The function to throttle.
54344                * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
54345                * @param {Object} [options={}] The options object.
54346                * @param {boolean} [options.leading=true]
54347                *  Specify invoking on the leading edge of the timeout.
54348                * @param {boolean} [options.trailing=true]
54349                *  Specify invoking on the trailing edge of the timeout.
54350                * @returns {Function} Returns the new throttled function.
54351                * @example
54352                *
54353                * // Avoid excessively updating the position while scrolling.
54354                * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
54355                *
54356                * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
54357                * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
54358                * jQuery(element).on('click', throttled);
54359                *
54360                * // Cancel the trailing throttled invocation.
54361                * jQuery(window).on('popstate', throttled.cancel);
54362                */
54363
54364
54365               function throttle(func, wait, options) {
54366                 var leading = true,
54367                     trailing = true;
54368
54369                 if (typeof func != 'function') {
54370                   throw new TypeError(FUNC_ERROR_TEXT);
54371                 }
54372
54373                 if (isObject(options)) {
54374                   leading = 'leading' in options ? !!options.leading : leading;
54375                   trailing = 'trailing' in options ? !!options.trailing : trailing;
54376                 }
54377
54378                 return debounce(func, wait, {
54379                   'leading': leading,
54380                   'maxWait': wait,
54381                   'trailing': trailing
54382                 });
54383               }
54384               /**
54385                * Creates a function that accepts up to one argument, ignoring any
54386                * additional arguments.
54387                *
54388                * @static
54389                * @memberOf _
54390                * @since 4.0.0
54391                * @category Function
54392                * @param {Function} func The function to cap arguments for.
54393                * @returns {Function} Returns the new capped function.
54394                * @example
54395                *
54396                * _.map(['6', '8', '10'], _.unary(parseInt));
54397                * // => [6, 8, 10]
54398                */
54399
54400
54401               function unary(func) {
54402                 return ary(func, 1);
54403               }
54404               /**
54405                * Creates a function that provides `value` to `wrapper` as its first
54406                * argument. Any additional arguments provided to the function are appended
54407                * to those provided to the `wrapper`. The wrapper is invoked with the `this`
54408                * binding of the created function.
54409                *
54410                * @static
54411                * @memberOf _
54412                * @since 0.1.0
54413                * @category Function
54414                * @param {*} value The value to wrap.
54415                * @param {Function} [wrapper=identity] The wrapper function.
54416                * @returns {Function} Returns the new function.
54417                * @example
54418                *
54419                * var p = _.wrap(_.escape, function(func, text) {
54420                *   return '<p>' + func(text) + '</p>';
54421                * });
54422                *
54423                * p('fred, barney, & pebbles');
54424                * // => '<p>fred, barney, &amp; pebbles</p>'
54425                */
54426
54427
54428               function wrap(value, wrapper) {
54429                 return partial(castFunction(wrapper), value);
54430               }
54431               /*------------------------------------------------------------------------*/
54432
54433               /**
54434                * Casts `value` as an array if it's not one.
54435                *
54436                * @static
54437                * @memberOf _
54438                * @since 4.4.0
54439                * @category Lang
54440                * @param {*} value The value to inspect.
54441                * @returns {Array} Returns the cast array.
54442                * @example
54443                *
54444                * _.castArray(1);
54445                * // => [1]
54446                *
54447                * _.castArray({ 'a': 1 });
54448                * // => [{ 'a': 1 }]
54449                *
54450                * _.castArray('abc');
54451                * // => ['abc']
54452                *
54453                * _.castArray(null);
54454                * // => [null]
54455                *
54456                * _.castArray(undefined);
54457                * // => [undefined]
54458                *
54459                * _.castArray();
54460                * // => []
54461                *
54462                * var array = [1, 2, 3];
54463                * console.log(_.castArray(array) === array);
54464                * // => true
54465                */
54466
54467
54468               function castArray() {
54469                 if (!arguments.length) {
54470                   return [];
54471                 }
54472
54473                 var value = arguments[0];
54474                 return isArray(value) ? value : [value];
54475               }
54476               /**
54477                * Creates a shallow clone of `value`.
54478                *
54479                * **Note:** This method is loosely based on the
54480                * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
54481                * and supports cloning arrays, array buffers, booleans, date objects, maps,
54482                * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
54483                * arrays. The own enumerable properties of `arguments` objects are cloned
54484                * as plain objects. An empty object is returned for uncloneable values such
54485                * as error objects, functions, DOM nodes, and WeakMaps.
54486                *
54487                * @static
54488                * @memberOf _
54489                * @since 0.1.0
54490                * @category Lang
54491                * @param {*} value The value to clone.
54492                * @returns {*} Returns the cloned value.
54493                * @see _.cloneDeep
54494                * @example
54495                *
54496                * var objects = [{ 'a': 1 }, { 'b': 2 }];
54497                *
54498                * var shallow = _.clone(objects);
54499                * console.log(shallow[0] === objects[0]);
54500                * // => true
54501                */
54502
54503
54504               function clone(value) {
54505                 return baseClone(value, CLONE_SYMBOLS_FLAG);
54506               }
54507               /**
54508                * This method is like `_.clone` except that it accepts `customizer` which
54509                * is invoked to produce the cloned value. If `customizer` returns `undefined`,
54510                * cloning is handled by the method instead. The `customizer` is invoked with
54511                * up to four arguments; (value [, index|key, object, stack]).
54512                *
54513                * @static
54514                * @memberOf _
54515                * @since 4.0.0
54516                * @category Lang
54517                * @param {*} value The value to clone.
54518                * @param {Function} [customizer] The function to customize cloning.
54519                * @returns {*} Returns the cloned value.
54520                * @see _.cloneDeepWith
54521                * @example
54522                *
54523                * function customizer(value) {
54524                *   if (_.isElement(value)) {
54525                *     return value.cloneNode(false);
54526                *   }
54527                * }
54528                *
54529                * var el = _.cloneWith(document.body, customizer);
54530                *
54531                * console.log(el === document.body);
54532                * // => false
54533                * console.log(el.nodeName);
54534                * // => 'BODY'
54535                * console.log(el.childNodes.length);
54536                * // => 0
54537                */
54538
54539
54540               function cloneWith(value, customizer) {
54541                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
54542                 return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
54543               }
54544               /**
54545                * This method is like `_.clone` except that it recursively clones `value`.
54546                *
54547                * @static
54548                * @memberOf _
54549                * @since 1.0.0
54550                * @category Lang
54551                * @param {*} value The value to recursively clone.
54552                * @returns {*} Returns the deep cloned value.
54553                * @see _.clone
54554                * @example
54555                *
54556                * var objects = [{ 'a': 1 }, { 'b': 2 }];
54557                *
54558                * var deep = _.cloneDeep(objects);
54559                * console.log(deep[0] === objects[0]);
54560                * // => false
54561                */
54562
54563
54564               function cloneDeep(value) {
54565                 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
54566               }
54567               /**
54568                * This method is like `_.cloneWith` except that it recursively clones `value`.
54569                *
54570                * @static
54571                * @memberOf _
54572                * @since 4.0.0
54573                * @category Lang
54574                * @param {*} value The value to recursively clone.
54575                * @param {Function} [customizer] The function to customize cloning.
54576                * @returns {*} Returns the deep cloned value.
54577                * @see _.cloneWith
54578                * @example
54579                *
54580                * function customizer(value) {
54581                *   if (_.isElement(value)) {
54582                *     return value.cloneNode(true);
54583                *   }
54584                * }
54585                *
54586                * var el = _.cloneDeepWith(document.body, customizer);
54587                *
54588                * console.log(el === document.body);
54589                * // => false
54590                * console.log(el.nodeName);
54591                * // => 'BODY'
54592                * console.log(el.childNodes.length);
54593                * // => 20
54594                */
54595
54596
54597               function cloneDeepWith(value, customizer) {
54598                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
54599                 return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
54600               }
54601               /**
54602                * Checks if `object` conforms to `source` by invoking the predicate
54603                * properties of `source` with the corresponding property values of `object`.
54604                *
54605                * **Note:** This method is equivalent to `_.conforms` when `source` is
54606                * partially applied.
54607                *
54608                * @static
54609                * @memberOf _
54610                * @since 4.14.0
54611                * @category Lang
54612                * @param {Object} object The object to inspect.
54613                * @param {Object} source The object of property predicates to conform to.
54614                * @returns {boolean} Returns `true` if `object` conforms, else `false`.
54615                * @example
54616                *
54617                * var object = { 'a': 1, 'b': 2 };
54618                *
54619                * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
54620                * // => true
54621                *
54622                * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
54623                * // => false
54624                */
54625
54626
54627               function conformsTo(object, source) {
54628                 return source == null || baseConformsTo(object, source, keys(source));
54629               }
54630               /**
54631                * Performs a
54632                * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
54633                * comparison between two values to determine if they are equivalent.
54634                *
54635                * @static
54636                * @memberOf _
54637                * @since 4.0.0
54638                * @category Lang
54639                * @param {*} value The value to compare.
54640                * @param {*} other The other value to compare.
54641                * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
54642                * @example
54643                *
54644                * var object = { 'a': 1 };
54645                * var other = { 'a': 1 };
54646                *
54647                * _.eq(object, object);
54648                * // => true
54649                *
54650                * _.eq(object, other);
54651                * // => false
54652                *
54653                * _.eq('a', 'a');
54654                * // => true
54655                *
54656                * _.eq('a', Object('a'));
54657                * // => false
54658                *
54659                * _.eq(NaN, NaN);
54660                * // => true
54661                */
54662
54663
54664               function eq(value, other) {
54665                 return value === other || value !== value && other !== other;
54666               }
54667               /**
54668                * Checks if `value` is greater than `other`.
54669                *
54670                * @static
54671                * @memberOf _
54672                * @since 3.9.0
54673                * @category Lang
54674                * @param {*} value The value to compare.
54675                * @param {*} other The other value to compare.
54676                * @returns {boolean} Returns `true` if `value` is greater than `other`,
54677                *  else `false`.
54678                * @see _.lt
54679                * @example
54680                *
54681                * _.gt(3, 1);
54682                * // => true
54683                *
54684                * _.gt(3, 3);
54685                * // => false
54686                *
54687                * _.gt(1, 3);
54688                * // => false
54689                */
54690
54691
54692               var gt = createRelationalOperation(baseGt);
54693               /**
54694                * Checks if `value` is greater than or equal to `other`.
54695                *
54696                * @static
54697                * @memberOf _
54698                * @since 3.9.0
54699                * @category Lang
54700                * @param {*} value The value to compare.
54701                * @param {*} other The other value to compare.
54702                * @returns {boolean} Returns `true` if `value` is greater than or equal to
54703                *  `other`, else `false`.
54704                * @see _.lte
54705                * @example
54706                *
54707                * _.gte(3, 1);
54708                * // => true
54709                *
54710                * _.gte(3, 3);
54711                * // => true
54712                *
54713                * _.gte(1, 3);
54714                * // => false
54715                */
54716
54717               var gte = createRelationalOperation(function (value, other) {
54718                 return value >= other;
54719               });
54720               /**
54721                * Checks if `value` is likely an `arguments` object.
54722                *
54723                * @static
54724                * @memberOf _
54725                * @since 0.1.0
54726                * @category Lang
54727                * @param {*} value The value to check.
54728                * @returns {boolean} Returns `true` if `value` is an `arguments` object,
54729                *  else `false`.
54730                * @example
54731                *
54732                * _.isArguments(function() { return arguments; }());
54733                * // => true
54734                *
54735                * _.isArguments([1, 2, 3]);
54736                * // => false
54737                */
54738
54739               var isArguments = baseIsArguments(function () {
54740                 return arguments;
54741               }()) ? baseIsArguments : function (value) {
54742                 return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
54743               };
54744               /**
54745                * Checks if `value` is classified as an `Array` object.
54746                *
54747                * @static
54748                * @memberOf _
54749                * @since 0.1.0
54750                * @category Lang
54751                * @param {*} value The value to check.
54752                * @returns {boolean} Returns `true` if `value` is an array, else `false`.
54753                * @example
54754                *
54755                * _.isArray([1, 2, 3]);
54756                * // => true
54757                *
54758                * _.isArray(document.body.children);
54759                * // => false
54760                *
54761                * _.isArray('abc');
54762                * // => false
54763                *
54764                * _.isArray(_.noop);
54765                * // => false
54766                */
54767
54768               var isArray = Array.isArray;
54769               /**
54770                * Checks if `value` is classified as an `ArrayBuffer` object.
54771                *
54772                * @static
54773                * @memberOf _
54774                * @since 4.3.0
54775                * @category Lang
54776                * @param {*} value The value to check.
54777                * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
54778                * @example
54779                *
54780                * _.isArrayBuffer(new ArrayBuffer(2));
54781                * // => true
54782                *
54783                * _.isArrayBuffer(new Array(2));
54784                * // => false
54785                */
54786
54787               var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
54788               /**
54789                * Checks if `value` is array-like. A value is considered array-like if it's
54790                * not a function and has a `value.length` that's an integer greater than or
54791                * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
54792                *
54793                * @static
54794                * @memberOf _
54795                * @since 4.0.0
54796                * @category Lang
54797                * @param {*} value The value to check.
54798                * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
54799                * @example
54800                *
54801                * _.isArrayLike([1, 2, 3]);
54802                * // => true
54803                *
54804                * _.isArrayLike(document.body.children);
54805                * // => true
54806                *
54807                * _.isArrayLike('abc');
54808                * // => true
54809                *
54810                * _.isArrayLike(_.noop);
54811                * // => false
54812                */
54813
54814               function isArrayLike(value) {
54815                 return value != null && isLength(value.length) && !isFunction(value);
54816               }
54817               /**
54818                * This method is like `_.isArrayLike` except that it also checks if `value`
54819                * is an object.
54820                *
54821                * @static
54822                * @memberOf _
54823                * @since 4.0.0
54824                * @category Lang
54825                * @param {*} value The value to check.
54826                * @returns {boolean} Returns `true` if `value` is an array-like object,
54827                *  else `false`.
54828                * @example
54829                *
54830                * _.isArrayLikeObject([1, 2, 3]);
54831                * // => true
54832                *
54833                * _.isArrayLikeObject(document.body.children);
54834                * // => true
54835                *
54836                * _.isArrayLikeObject('abc');
54837                * // => false
54838                *
54839                * _.isArrayLikeObject(_.noop);
54840                * // => false
54841                */
54842
54843
54844               function isArrayLikeObject(value) {
54845                 return isObjectLike(value) && isArrayLike(value);
54846               }
54847               /**
54848                * Checks if `value` is classified as a boolean primitive or object.
54849                *
54850                * @static
54851                * @memberOf _
54852                * @since 0.1.0
54853                * @category Lang
54854                * @param {*} value The value to check.
54855                * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
54856                * @example
54857                *
54858                * _.isBoolean(false);
54859                * // => true
54860                *
54861                * _.isBoolean(null);
54862                * // => false
54863                */
54864
54865
54866               function isBoolean(value) {
54867                 return value === true || value === false || isObjectLike(value) && baseGetTag(value) == boolTag;
54868               }
54869               /**
54870                * Checks if `value` is a buffer.
54871                *
54872                * @static
54873                * @memberOf _
54874                * @since 4.3.0
54875                * @category Lang
54876                * @param {*} value The value to check.
54877                * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
54878                * @example
54879                *
54880                * _.isBuffer(new Buffer(2));
54881                * // => true
54882                *
54883                * _.isBuffer(new Uint8Array(2));
54884                * // => false
54885                */
54886
54887
54888               var isBuffer = nativeIsBuffer || stubFalse;
54889               /**
54890                * Checks if `value` is classified as a `Date` object.
54891                *
54892                * @static
54893                * @memberOf _
54894                * @since 0.1.0
54895                * @category Lang
54896                * @param {*} value The value to check.
54897                * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
54898                * @example
54899                *
54900                * _.isDate(new Date);
54901                * // => true
54902                *
54903                * _.isDate('Mon April 23 2012');
54904                * // => false
54905                */
54906
54907               var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
54908               /**
54909                * Checks if `value` is likely a DOM element.
54910                *
54911                * @static
54912                * @memberOf _
54913                * @since 0.1.0
54914                * @category Lang
54915                * @param {*} value The value to check.
54916                * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
54917                * @example
54918                *
54919                * _.isElement(document.body);
54920                * // => true
54921                *
54922                * _.isElement('<body>');
54923                * // => false
54924                */
54925
54926               function isElement(value) {
54927                 return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
54928               }
54929               /**
54930                * Checks if `value` is an empty object, collection, map, or set.
54931                *
54932                * Objects are considered empty if they have no own enumerable string keyed
54933                * properties.
54934                *
54935                * Array-like values such as `arguments` objects, arrays, buffers, strings, or
54936                * jQuery-like collections are considered empty if they have a `length` of `0`.
54937                * Similarly, maps and sets are considered empty if they have a `size` of `0`.
54938                *
54939                * @static
54940                * @memberOf _
54941                * @since 0.1.0
54942                * @category Lang
54943                * @param {*} value The value to check.
54944                * @returns {boolean} Returns `true` if `value` is empty, else `false`.
54945                * @example
54946                *
54947                * _.isEmpty(null);
54948                * // => true
54949                *
54950                * _.isEmpty(true);
54951                * // => true
54952                *
54953                * _.isEmpty(1);
54954                * // => true
54955                *
54956                * _.isEmpty([1, 2, 3]);
54957                * // => false
54958                *
54959                * _.isEmpty({ 'a': 1 });
54960                * // => false
54961                */
54962
54963
54964               function isEmpty(value) {
54965                 if (value == null) {
54966                   return true;
54967                 }
54968
54969                 if (isArrayLike(value) && (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || isBuffer(value) || isTypedArray(value) || isArguments(value))) {
54970                   return !value.length;
54971                 }
54972
54973                 var tag = getTag(value);
54974
54975                 if (tag == mapTag || tag == setTag) {
54976                   return !value.size;
54977                 }
54978
54979                 if (isPrototype(value)) {
54980                   return !baseKeys(value).length;
54981                 }
54982
54983                 for (var key in value) {
54984                   if (hasOwnProperty.call(value, key)) {
54985                     return false;
54986                   }
54987                 }
54988
54989                 return true;
54990               }
54991               /**
54992                * Performs a deep comparison between two values to determine if they are
54993                * equivalent.
54994                *
54995                * **Note:** This method supports comparing arrays, array buffers, booleans,
54996                * date objects, error objects, maps, numbers, `Object` objects, regexes,
54997                * sets, strings, symbols, and typed arrays. `Object` objects are compared
54998                * by their own, not inherited, enumerable properties. Functions and DOM
54999                * nodes are compared by strict equality, i.e. `===`.
55000                *
55001                * @static
55002                * @memberOf _
55003                * @since 0.1.0
55004                * @category Lang
55005                * @param {*} value The value to compare.
55006                * @param {*} other The other value to compare.
55007                * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
55008                * @example
55009                *
55010                * var object = { 'a': 1 };
55011                * var other = { 'a': 1 };
55012                *
55013                * _.isEqual(object, other);
55014                * // => true
55015                *
55016                * object === other;
55017                * // => false
55018                */
55019
55020
55021               function isEqual(value, other) {
55022                 return baseIsEqual(value, other);
55023               }
55024               /**
55025                * This method is like `_.isEqual` except that it accepts `customizer` which
55026                * is invoked to compare values. If `customizer` returns `undefined`, comparisons
55027                * are handled by the method instead. The `customizer` is invoked with up to
55028                * six arguments: (objValue, othValue [, index|key, object, other, stack]).
55029                *
55030                * @static
55031                * @memberOf _
55032                * @since 4.0.0
55033                * @category Lang
55034                * @param {*} value The value to compare.
55035                * @param {*} other The other value to compare.
55036                * @param {Function} [customizer] The function to customize comparisons.
55037                * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
55038                * @example
55039                *
55040                * function isGreeting(value) {
55041                *   return /^h(?:i|ello)$/.test(value);
55042                * }
55043                *
55044                * function customizer(objValue, othValue) {
55045                *   if (isGreeting(objValue) && isGreeting(othValue)) {
55046                *     return true;
55047                *   }
55048                * }
55049                *
55050                * var array = ['hello', 'goodbye'];
55051                * var other = ['hi', 'goodbye'];
55052                *
55053                * _.isEqualWith(array, other, customizer);
55054                * // => true
55055                */
55056
55057
55058               function isEqualWith(value, other, customizer) {
55059                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
55060                 var result = customizer ? customizer(value, other) : undefined$1;
55061                 return result === undefined$1 ? baseIsEqual(value, other, undefined$1, customizer) : !!result;
55062               }
55063               /**
55064                * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
55065                * `SyntaxError`, `TypeError`, or `URIError` object.
55066                *
55067                * @static
55068                * @memberOf _
55069                * @since 3.0.0
55070                * @category Lang
55071                * @param {*} value The value to check.
55072                * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
55073                * @example
55074                *
55075                * _.isError(new Error);
55076                * // => true
55077                *
55078                * _.isError(Error);
55079                * // => false
55080                */
55081
55082
55083               function isError(value) {
55084                 if (!isObjectLike(value)) {
55085                   return false;
55086                 }
55087
55088                 var tag = baseGetTag(value);
55089                 return tag == errorTag || tag == domExcTag || typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value);
55090               }
55091               /**
55092                * Checks if `value` is a finite primitive number.
55093                *
55094                * **Note:** This method is based on
55095                * [`Number.isFinite`](https://mdn.io/Number/isFinite).
55096                *
55097                * @static
55098                * @memberOf _
55099                * @since 0.1.0
55100                * @category Lang
55101                * @param {*} value The value to check.
55102                * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
55103                * @example
55104                *
55105                * _.isFinite(3);
55106                * // => true
55107                *
55108                * _.isFinite(Number.MIN_VALUE);
55109                * // => true
55110                *
55111                * _.isFinite(Infinity);
55112                * // => false
55113                *
55114                * _.isFinite('3');
55115                * // => false
55116                */
55117
55118
55119               function isFinite(value) {
55120                 return typeof value == 'number' && nativeIsFinite(value);
55121               }
55122               /**
55123                * Checks if `value` is classified as a `Function` object.
55124                *
55125                * @static
55126                * @memberOf _
55127                * @since 0.1.0
55128                * @category Lang
55129                * @param {*} value The value to check.
55130                * @returns {boolean} Returns `true` if `value` is a function, else `false`.
55131                * @example
55132                *
55133                * _.isFunction(_);
55134                * // => true
55135                *
55136                * _.isFunction(/abc/);
55137                * // => false
55138                */
55139
55140
55141               function isFunction(value) {
55142                 if (!isObject(value)) {
55143                   return false;
55144                 } // The use of `Object#toString` avoids issues with the `typeof` operator
55145                 // in Safari 9 which returns 'object' for typed arrays and other constructors.
55146
55147
55148                 var tag = baseGetTag(value);
55149                 return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
55150               }
55151               /**
55152                * Checks if `value` is an integer.
55153                *
55154                * **Note:** This method is based on
55155                * [`Number.isInteger`](https://mdn.io/Number/isInteger).
55156                *
55157                * @static
55158                * @memberOf _
55159                * @since 4.0.0
55160                * @category Lang
55161                * @param {*} value The value to check.
55162                * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
55163                * @example
55164                *
55165                * _.isInteger(3);
55166                * // => true
55167                *
55168                * _.isInteger(Number.MIN_VALUE);
55169                * // => false
55170                *
55171                * _.isInteger(Infinity);
55172                * // => false
55173                *
55174                * _.isInteger('3');
55175                * // => false
55176                */
55177
55178
55179               function isInteger(value) {
55180                 return typeof value == 'number' && value == toInteger(value);
55181               }
55182               /**
55183                * Checks if `value` is a valid array-like length.
55184                *
55185                * **Note:** This method is loosely based on
55186                * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
55187                *
55188                * @static
55189                * @memberOf _
55190                * @since 4.0.0
55191                * @category Lang
55192                * @param {*} value The value to check.
55193                * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
55194                * @example
55195                *
55196                * _.isLength(3);
55197                * // => true
55198                *
55199                * _.isLength(Number.MIN_VALUE);
55200                * // => false
55201                *
55202                * _.isLength(Infinity);
55203                * // => false
55204                *
55205                * _.isLength('3');
55206                * // => false
55207                */
55208
55209
55210               function isLength(value) {
55211                 return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
55212               }
55213               /**
55214                * Checks if `value` is the
55215                * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
55216                * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
55217                *
55218                * @static
55219                * @memberOf _
55220                * @since 0.1.0
55221                * @category Lang
55222                * @param {*} value The value to check.
55223                * @returns {boolean} Returns `true` if `value` is an object, else `false`.
55224                * @example
55225                *
55226                * _.isObject({});
55227                * // => true
55228                *
55229                * _.isObject([1, 2, 3]);
55230                * // => true
55231                *
55232                * _.isObject(_.noop);
55233                * // => true
55234                *
55235                * _.isObject(null);
55236                * // => false
55237                */
55238
55239
55240               function isObject(value) {
55241                 var type = _typeof(value);
55242
55243                 return value != null && (type == 'object' || type == 'function');
55244               }
55245               /**
55246                * Checks if `value` is object-like. A value is object-like if it's not `null`
55247                * and has a `typeof` result of "object".
55248                *
55249                * @static
55250                * @memberOf _
55251                * @since 4.0.0
55252                * @category Lang
55253                * @param {*} value The value to check.
55254                * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
55255                * @example
55256                *
55257                * _.isObjectLike({});
55258                * // => true
55259                *
55260                * _.isObjectLike([1, 2, 3]);
55261                * // => true
55262                *
55263                * _.isObjectLike(_.noop);
55264                * // => false
55265                *
55266                * _.isObjectLike(null);
55267                * // => false
55268                */
55269
55270
55271               function isObjectLike(value) {
55272                 return value != null && _typeof(value) == 'object';
55273               }
55274               /**
55275                * Checks if `value` is classified as a `Map` object.
55276                *
55277                * @static
55278                * @memberOf _
55279                * @since 4.3.0
55280                * @category Lang
55281                * @param {*} value The value to check.
55282                * @returns {boolean} Returns `true` if `value` is a map, else `false`.
55283                * @example
55284                *
55285                * _.isMap(new Map);
55286                * // => true
55287                *
55288                * _.isMap(new WeakMap);
55289                * // => false
55290                */
55291
55292
55293               var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
55294               /**
55295                * Performs a partial deep comparison between `object` and `source` to
55296                * determine if `object` contains equivalent property values.
55297                *
55298                * **Note:** This method is equivalent to `_.matches` when `source` is
55299                * partially applied.
55300                *
55301                * Partial comparisons will match empty array and empty object `source`
55302                * values against any array or object value, respectively. See `_.isEqual`
55303                * for a list of supported value comparisons.
55304                *
55305                * @static
55306                * @memberOf _
55307                * @since 3.0.0
55308                * @category Lang
55309                * @param {Object} object The object to inspect.
55310                * @param {Object} source The object of property values to match.
55311                * @returns {boolean} Returns `true` if `object` is a match, else `false`.
55312                * @example
55313                *
55314                * var object = { 'a': 1, 'b': 2 };
55315                *
55316                * _.isMatch(object, { 'b': 2 });
55317                * // => true
55318                *
55319                * _.isMatch(object, { 'b': 1 });
55320                * // => false
55321                */
55322
55323               function isMatch(object, source) {
55324                 return object === source || baseIsMatch(object, source, getMatchData(source));
55325               }
55326               /**
55327                * This method is like `_.isMatch` except that it accepts `customizer` which
55328                * is invoked to compare values. If `customizer` returns `undefined`, comparisons
55329                * are handled by the method instead. The `customizer` is invoked with five
55330                * arguments: (objValue, srcValue, index|key, object, source).
55331                *
55332                * @static
55333                * @memberOf _
55334                * @since 4.0.0
55335                * @category Lang
55336                * @param {Object} object The object to inspect.
55337                * @param {Object} source The object of property values to match.
55338                * @param {Function} [customizer] The function to customize comparisons.
55339                * @returns {boolean} Returns `true` if `object` is a match, else `false`.
55340                * @example
55341                *
55342                * function isGreeting(value) {
55343                *   return /^h(?:i|ello)$/.test(value);
55344                * }
55345                *
55346                * function customizer(objValue, srcValue) {
55347                *   if (isGreeting(objValue) && isGreeting(srcValue)) {
55348                *     return true;
55349                *   }
55350                * }
55351                *
55352                * var object = { 'greeting': 'hello' };
55353                * var source = { 'greeting': 'hi' };
55354                *
55355                * _.isMatchWith(object, source, customizer);
55356                * // => true
55357                */
55358
55359
55360               function isMatchWith(object, source, customizer) {
55361                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
55362                 return baseIsMatch(object, source, getMatchData(source), customizer);
55363               }
55364               /**
55365                * Checks if `value` is `NaN`.
55366                *
55367                * **Note:** This method is based on
55368                * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
55369                * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
55370                * `undefined` and other non-number values.
55371                *
55372                * @static
55373                * @memberOf _
55374                * @since 0.1.0
55375                * @category Lang
55376                * @param {*} value The value to check.
55377                * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
55378                * @example
55379                *
55380                * _.isNaN(NaN);
55381                * // => true
55382                *
55383                * _.isNaN(new Number(NaN));
55384                * // => true
55385                *
55386                * isNaN(undefined);
55387                * // => true
55388                *
55389                * _.isNaN(undefined);
55390                * // => false
55391                */
55392
55393
55394               function isNaN(value) {
55395                 // An `NaN` primitive is the only value that is not equal to itself.
55396                 // Perform the `toStringTag` check first to avoid errors with some
55397                 // ActiveX objects in IE.
55398                 return isNumber(value) && value != +value;
55399               }
55400               /**
55401                * Checks if `value` is a pristine native function.
55402                *
55403                * **Note:** This method can't reliably detect native functions in the presence
55404                * of the core-js package because core-js circumvents this kind of detection.
55405                * Despite multiple requests, the core-js maintainer has made it clear: any
55406                * attempt to fix the detection will be obstructed. As a result, we're left
55407                * with little choice but to throw an error. Unfortunately, this also affects
55408                * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
55409                * which rely on core-js.
55410                *
55411                * @static
55412                * @memberOf _
55413                * @since 3.0.0
55414                * @category Lang
55415                * @param {*} value The value to check.
55416                * @returns {boolean} Returns `true` if `value` is a native function,
55417                *  else `false`.
55418                * @example
55419                *
55420                * _.isNative(Array.prototype.push);
55421                * // => true
55422                *
55423                * _.isNative(_);
55424                * // => false
55425                */
55426
55427
55428               function isNative(value) {
55429                 if (isMaskable(value)) {
55430                   throw new Error(CORE_ERROR_TEXT);
55431                 }
55432
55433                 return baseIsNative(value);
55434               }
55435               /**
55436                * Checks if `value` is `null`.
55437                *
55438                * @static
55439                * @memberOf _
55440                * @since 0.1.0
55441                * @category Lang
55442                * @param {*} value The value to check.
55443                * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
55444                * @example
55445                *
55446                * _.isNull(null);
55447                * // => true
55448                *
55449                * _.isNull(void 0);
55450                * // => false
55451                */
55452
55453
55454               function isNull(value) {
55455                 return value === null;
55456               }
55457               /**
55458                * Checks if `value` is `null` or `undefined`.
55459                *
55460                * @static
55461                * @memberOf _
55462                * @since 4.0.0
55463                * @category Lang
55464                * @param {*} value The value to check.
55465                * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
55466                * @example
55467                *
55468                * _.isNil(null);
55469                * // => true
55470                *
55471                * _.isNil(void 0);
55472                * // => true
55473                *
55474                * _.isNil(NaN);
55475                * // => false
55476                */
55477
55478
55479               function isNil(value) {
55480                 return value == null;
55481               }
55482               /**
55483                * Checks if `value` is classified as a `Number` primitive or object.
55484                *
55485                * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
55486                * classified as numbers, use the `_.isFinite` method.
55487                *
55488                * @static
55489                * @memberOf _
55490                * @since 0.1.0
55491                * @category Lang
55492                * @param {*} value The value to check.
55493                * @returns {boolean} Returns `true` if `value` is a number, else `false`.
55494                * @example
55495                *
55496                * _.isNumber(3);
55497                * // => true
55498                *
55499                * _.isNumber(Number.MIN_VALUE);
55500                * // => true
55501                *
55502                * _.isNumber(Infinity);
55503                * // => true
55504                *
55505                * _.isNumber('3');
55506                * // => false
55507                */
55508
55509
55510               function isNumber(value) {
55511                 return typeof value == 'number' || isObjectLike(value) && baseGetTag(value) == numberTag;
55512               }
55513               /**
55514                * Checks if `value` is a plain object, that is, an object created by the
55515                * `Object` constructor or one with a `[[Prototype]]` of `null`.
55516                *
55517                * @static
55518                * @memberOf _
55519                * @since 0.8.0
55520                * @category Lang
55521                * @param {*} value The value to check.
55522                * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
55523                * @example
55524                *
55525                * function Foo() {
55526                *   this.a = 1;
55527                * }
55528                *
55529                * _.isPlainObject(new Foo);
55530                * // => false
55531                *
55532                * _.isPlainObject([1, 2, 3]);
55533                * // => false
55534                *
55535                * _.isPlainObject({ 'x': 0, 'y': 0 });
55536                * // => true
55537                *
55538                * _.isPlainObject(Object.create(null));
55539                * // => true
55540                */
55541
55542
55543               function isPlainObject(value) {
55544                 if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
55545                   return false;
55546                 }
55547
55548                 var proto = getPrototype(value);
55549
55550                 if (proto === null) {
55551                   return true;
55552                 }
55553
55554                 var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
55555                 return typeof Ctor == 'function' && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
55556               }
55557               /**
55558                * Checks if `value` is classified as a `RegExp` object.
55559                *
55560                * @static
55561                * @memberOf _
55562                * @since 0.1.0
55563                * @category Lang
55564                * @param {*} value The value to check.
55565                * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
55566                * @example
55567                *
55568                * _.isRegExp(/abc/);
55569                * // => true
55570                *
55571                * _.isRegExp('/abc/');
55572                * // => false
55573                */
55574
55575
55576               var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
55577               /**
55578                * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
55579                * double precision number which isn't the result of a rounded unsafe integer.
55580                *
55581                * **Note:** This method is based on
55582                * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
55583                *
55584                * @static
55585                * @memberOf _
55586                * @since 4.0.0
55587                * @category Lang
55588                * @param {*} value The value to check.
55589                * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
55590                * @example
55591                *
55592                * _.isSafeInteger(3);
55593                * // => true
55594                *
55595                * _.isSafeInteger(Number.MIN_VALUE);
55596                * // => false
55597                *
55598                * _.isSafeInteger(Infinity);
55599                * // => false
55600                *
55601                * _.isSafeInteger('3');
55602                * // => false
55603                */
55604
55605               function isSafeInteger(value) {
55606                 return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
55607               }
55608               /**
55609                * Checks if `value` is classified as a `Set` object.
55610                *
55611                * @static
55612                * @memberOf _
55613                * @since 4.3.0
55614                * @category Lang
55615                * @param {*} value The value to check.
55616                * @returns {boolean} Returns `true` if `value` is a set, else `false`.
55617                * @example
55618                *
55619                * _.isSet(new Set);
55620                * // => true
55621                *
55622                * _.isSet(new WeakSet);
55623                * // => false
55624                */
55625
55626
55627               var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
55628               /**
55629                * Checks if `value` is classified as a `String` primitive or object.
55630                *
55631                * @static
55632                * @since 0.1.0
55633                * @memberOf _
55634                * @category Lang
55635                * @param {*} value The value to check.
55636                * @returns {boolean} Returns `true` if `value` is a string, else `false`.
55637                * @example
55638                *
55639                * _.isString('abc');
55640                * // => true
55641                *
55642                * _.isString(1);
55643                * // => false
55644                */
55645
55646               function isString(value) {
55647                 return typeof value == 'string' || !isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag;
55648               }
55649               /**
55650                * Checks if `value` is classified as a `Symbol` primitive or object.
55651                *
55652                * @static
55653                * @memberOf _
55654                * @since 4.0.0
55655                * @category Lang
55656                * @param {*} value The value to check.
55657                * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
55658                * @example
55659                *
55660                * _.isSymbol(Symbol.iterator);
55661                * // => true
55662                *
55663                * _.isSymbol('abc');
55664                * // => false
55665                */
55666
55667
55668               function isSymbol(value) {
55669                 return _typeof(value) == 'symbol' || isObjectLike(value) && baseGetTag(value) == symbolTag;
55670               }
55671               /**
55672                * Checks if `value` is classified as a typed array.
55673                *
55674                * @static
55675                * @memberOf _
55676                * @since 3.0.0
55677                * @category Lang
55678                * @param {*} value The value to check.
55679                * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
55680                * @example
55681                *
55682                * _.isTypedArray(new Uint8Array);
55683                * // => true
55684                *
55685                * _.isTypedArray([]);
55686                * // => false
55687                */
55688
55689
55690               var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
55691               /**
55692                * Checks if `value` is `undefined`.
55693                *
55694                * @static
55695                * @since 0.1.0
55696                * @memberOf _
55697                * @category Lang
55698                * @param {*} value The value to check.
55699                * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
55700                * @example
55701                *
55702                * _.isUndefined(void 0);
55703                * // => true
55704                *
55705                * _.isUndefined(null);
55706                * // => false
55707                */
55708
55709               function isUndefined(value) {
55710                 return value === undefined$1;
55711               }
55712               /**
55713                * Checks if `value` is classified as a `WeakMap` object.
55714                *
55715                * @static
55716                * @memberOf _
55717                * @since 4.3.0
55718                * @category Lang
55719                * @param {*} value The value to check.
55720                * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
55721                * @example
55722                *
55723                * _.isWeakMap(new WeakMap);
55724                * // => true
55725                *
55726                * _.isWeakMap(new Map);
55727                * // => false
55728                */
55729
55730
55731               function isWeakMap(value) {
55732                 return isObjectLike(value) && getTag(value) == weakMapTag;
55733               }
55734               /**
55735                * Checks if `value` is classified as a `WeakSet` object.
55736                *
55737                * @static
55738                * @memberOf _
55739                * @since 4.3.0
55740                * @category Lang
55741                * @param {*} value The value to check.
55742                * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
55743                * @example
55744                *
55745                * _.isWeakSet(new WeakSet);
55746                * // => true
55747                *
55748                * _.isWeakSet(new Set);
55749                * // => false
55750                */
55751
55752
55753               function isWeakSet(value) {
55754                 return isObjectLike(value) && baseGetTag(value) == weakSetTag;
55755               }
55756               /**
55757                * Checks if `value` is less than `other`.
55758                *
55759                * @static
55760                * @memberOf _
55761                * @since 3.9.0
55762                * @category Lang
55763                * @param {*} value The value to compare.
55764                * @param {*} other The other value to compare.
55765                * @returns {boolean} Returns `true` if `value` is less than `other`,
55766                *  else `false`.
55767                * @see _.gt
55768                * @example
55769                *
55770                * _.lt(1, 3);
55771                * // => true
55772                *
55773                * _.lt(3, 3);
55774                * // => false
55775                *
55776                * _.lt(3, 1);
55777                * // => false
55778                */
55779
55780
55781               var lt = createRelationalOperation(baseLt);
55782               /**
55783                * Checks if `value` is less than or equal to `other`.
55784                *
55785                * @static
55786                * @memberOf _
55787                * @since 3.9.0
55788                * @category Lang
55789                * @param {*} value The value to compare.
55790                * @param {*} other The other value to compare.
55791                * @returns {boolean} Returns `true` if `value` is less than or equal to
55792                *  `other`, else `false`.
55793                * @see _.gte
55794                * @example
55795                *
55796                * _.lte(1, 3);
55797                * // => true
55798                *
55799                * _.lte(3, 3);
55800                * // => true
55801                *
55802                * _.lte(3, 1);
55803                * // => false
55804                */
55805
55806               var lte = createRelationalOperation(function (value, other) {
55807                 return value <= other;
55808               });
55809               /**
55810                * Converts `value` to an array.
55811                *
55812                * @static
55813                * @since 0.1.0
55814                * @memberOf _
55815                * @category Lang
55816                * @param {*} value The value to convert.
55817                * @returns {Array} Returns the converted array.
55818                * @example
55819                *
55820                * _.toArray({ 'a': 1, 'b': 2 });
55821                * // => [1, 2]
55822                *
55823                * _.toArray('abc');
55824                * // => ['a', 'b', 'c']
55825                *
55826                * _.toArray(1);
55827                * // => []
55828                *
55829                * _.toArray(null);
55830                * // => []
55831                */
55832
55833               function toArray(value) {
55834                 if (!value) {
55835                   return [];
55836                 }
55837
55838                 if (isArrayLike(value)) {
55839                   return isString(value) ? stringToArray(value) : copyArray(value);
55840                 }
55841
55842                 if (symIterator && value[symIterator]) {
55843                   return iteratorToArray(value[symIterator]());
55844                 }
55845
55846                 var tag = getTag(value),
55847                     func = tag == mapTag ? mapToArray : tag == setTag ? setToArray : values;
55848                 return func(value);
55849               }
55850               /**
55851                * Converts `value` to a finite number.
55852                *
55853                * @static
55854                * @memberOf _
55855                * @since 4.12.0
55856                * @category Lang
55857                * @param {*} value The value to convert.
55858                * @returns {number} Returns the converted number.
55859                * @example
55860                *
55861                * _.toFinite(3.2);
55862                * // => 3.2
55863                *
55864                * _.toFinite(Number.MIN_VALUE);
55865                * // => 5e-324
55866                *
55867                * _.toFinite(Infinity);
55868                * // => 1.7976931348623157e+308
55869                *
55870                * _.toFinite('3.2');
55871                * // => 3.2
55872                */
55873
55874
55875               function toFinite(value) {
55876                 if (!value) {
55877                   return value === 0 ? value : 0;
55878                 }
55879
55880                 value = toNumber(value);
55881
55882                 if (value === INFINITY || value === -INFINITY) {
55883                   var sign = value < 0 ? -1 : 1;
55884                   return sign * MAX_INTEGER;
55885                 }
55886
55887                 return value === value ? value : 0;
55888               }
55889               /**
55890                * Converts `value` to an integer.
55891                *
55892                * **Note:** This method is loosely based on
55893                * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
55894                *
55895                * @static
55896                * @memberOf _
55897                * @since 4.0.0
55898                * @category Lang
55899                * @param {*} value The value to convert.
55900                * @returns {number} Returns the converted integer.
55901                * @example
55902                *
55903                * _.toInteger(3.2);
55904                * // => 3
55905                *
55906                * _.toInteger(Number.MIN_VALUE);
55907                * // => 0
55908                *
55909                * _.toInteger(Infinity);
55910                * // => 1.7976931348623157e+308
55911                *
55912                * _.toInteger('3.2');
55913                * // => 3
55914                */
55915
55916
55917               function toInteger(value) {
55918                 var result = toFinite(value),
55919                     remainder = result % 1;
55920                 return result === result ? remainder ? result - remainder : result : 0;
55921               }
55922               /**
55923                * Converts `value` to an integer suitable for use as the length of an
55924                * array-like object.
55925                *
55926                * **Note:** This method is based on
55927                * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
55928                *
55929                * @static
55930                * @memberOf _
55931                * @since 4.0.0
55932                * @category Lang
55933                * @param {*} value The value to convert.
55934                * @returns {number} Returns the converted integer.
55935                * @example
55936                *
55937                * _.toLength(3.2);
55938                * // => 3
55939                *
55940                * _.toLength(Number.MIN_VALUE);
55941                * // => 0
55942                *
55943                * _.toLength(Infinity);
55944                * // => 4294967295
55945                *
55946                * _.toLength('3.2');
55947                * // => 3
55948                */
55949
55950
55951               function toLength(value) {
55952                 return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
55953               }
55954               /**
55955                * Converts `value` to a number.
55956                *
55957                * @static
55958                * @memberOf _
55959                * @since 4.0.0
55960                * @category Lang
55961                * @param {*} value The value to process.
55962                * @returns {number} Returns the number.
55963                * @example
55964                *
55965                * _.toNumber(3.2);
55966                * // => 3.2
55967                *
55968                * _.toNumber(Number.MIN_VALUE);
55969                * // => 5e-324
55970                *
55971                * _.toNumber(Infinity);
55972                * // => Infinity
55973                *
55974                * _.toNumber('3.2');
55975                * // => 3.2
55976                */
55977
55978
55979               function toNumber(value) {
55980                 if (typeof value == 'number') {
55981                   return value;
55982                 }
55983
55984                 if (isSymbol(value)) {
55985                   return NAN;
55986                 }
55987
55988                 if (isObject(value)) {
55989                   var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
55990                   value = isObject(other) ? other + '' : other;
55991                 }
55992
55993                 if (typeof value != 'string') {
55994                   return value === 0 ? value : +value;
55995                 }
55996
55997                 value = baseTrim(value);
55998                 var isBinary = reIsBinary.test(value);
55999                 return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
56000               }
56001               /**
56002                * Converts `value` to a plain object flattening inherited enumerable string
56003                * keyed properties of `value` to own properties of the plain object.
56004                *
56005                * @static
56006                * @memberOf _
56007                * @since 3.0.0
56008                * @category Lang
56009                * @param {*} value The value to convert.
56010                * @returns {Object} Returns the converted plain object.
56011                * @example
56012                *
56013                * function Foo() {
56014                *   this.b = 2;
56015                * }
56016                *
56017                * Foo.prototype.c = 3;
56018                *
56019                * _.assign({ 'a': 1 }, new Foo);
56020                * // => { 'a': 1, 'b': 2 }
56021                *
56022                * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
56023                * // => { 'a': 1, 'b': 2, 'c': 3 }
56024                */
56025
56026
56027               function toPlainObject(value) {
56028                 return copyObject(value, keysIn(value));
56029               }
56030               /**
56031                * Converts `value` to a safe integer. A safe integer can be compared and
56032                * represented correctly.
56033                *
56034                * @static
56035                * @memberOf _
56036                * @since 4.0.0
56037                * @category Lang
56038                * @param {*} value The value to convert.
56039                * @returns {number} Returns the converted integer.
56040                * @example
56041                *
56042                * _.toSafeInteger(3.2);
56043                * // => 3
56044                *
56045                * _.toSafeInteger(Number.MIN_VALUE);
56046                * // => 0
56047                *
56048                * _.toSafeInteger(Infinity);
56049                * // => 9007199254740991
56050                *
56051                * _.toSafeInteger('3.2');
56052                * // => 3
56053                */
56054
56055
56056               function toSafeInteger(value) {
56057                 return value ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) : value === 0 ? value : 0;
56058               }
56059               /**
56060                * Converts `value` to a string. An empty string is returned for `null`
56061                * and `undefined` values. The sign of `-0` is preserved.
56062                *
56063                * @static
56064                * @memberOf _
56065                * @since 4.0.0
56066                * @category Lang
56067                * @param {*} value The value to convert.
56068                * @returns {string} Returns the converted string.
56069                * @example
56070                *
56071                * _.toString(null);
56072                * // => ''
56073                *
56074                * _.toString(-0);
56075                * // => '-0'
56076                *
56077                * _.toString([1, 2, 3]);
56078                * // => '1,2,3'
56079                */
56080
56081
56082               function toString(value) {
56083                 return value == null ? '' : baseToString(value);
56084               }
56085               /*------------------------------------------------------------------------*/
56086
56087               /**
56088                * Assigns own enumerable string keyed properties of source objects to the
56089                * destination object. Source objects are applied from left to right.
56090                * Subsequent sources overwrite property assignments of previous sources.
56091                *
56092                * **Note:** This method mutates `object` and is loosely based on
56093                * [`Object.assign`](https://mdn.io/Object/assign).
56094                *
56095                * @static
56096                * @memberOf _
56097                * @since 0.10.0
56098                * @category Object
56099                * @param {Object} object The destination object.
56100                * @param {...Object} [sources] The source objects.
56101                * @returns {Object} Returns `object`.
56102                * @see _.assignIn
56103                * @example
56104                *
56105                * function Foo() {
56106                *   this.a = 1;
56107                * }
56108                *
56109                * function Bar() {
56110                *   this.c = 3;
56111                * }
56112                *
56113                * Foo.prototype.b = 2;
56114                * Bar.prototype.d = 4;
56115                *
56116                * _.assign({ 'a': 0 }, new Foo, new Bar);
56117                * // => { 'a': 1, 'c': 3 }
56118                */
56119
56120
56121               var assign = createAssigner(function (object, source) {
56122                 if (isPrototype(source) || isArrayLike(source)) {
56123                   copyObject(source, keys(source), object);
56124                   return;
56125                 }
56126
56127                 for (var key in source) {
56128                   if (hasOwnProperty.call(source, key)) {
56129                     assignValue(object, key, source[key]);
56130                   }
56131                 }
56132               });
56133               /**
56134                * This method is like `_.assign` except that it iterates over own and
56135                * inherited source properties.
56136                *
56137                * **Note:** This method mutates `object`.
56138                *
56139                * @static
56140                * @memberOf _
56141                * @since 4.0.0
56142                * @alias extend
56143                * @category Object
56144                * @param {Object} object The destination object.
56145                * @param {...Object} [sources] The source objects.
56146                * @returns {Object} Returns `object`.
56147                * @see _.assign
56148                * @example
56149                *
56150                * function Foo() {
56151                *   this.a = 1;
56152                * }
56153                *
56154                * function Bar() {
56155                *   this.c = 3;
56156                * }
56157                *
56158                * Foo.prototype.b = 2;
56159                * Bar.prototype.d = 4;
56160                *
56161                * _.assignIn({ 'a': 0 }, new Foo, new Bar);
56162                * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
56163                */
56164
56165               var assignIn = createAssigner(function (object, source) {
56166                 copyObject(source, keysIn(source), object);
56167               });
56168               /**
56169                * This method is like `_.assignIn` except that it accepts `customizer`
56170                * which is invoked to produce the assigned values. If `customizer` returns
56171                * `undefined`, assignment is handled by the method instead. The `customizer`
56172                * is invoked with five arguments: (objValue, srcValue, key, object, source).
56173                *
56174                * **Note:** This method mutates `object`.
56175                *
56176                * @static
56177                * @memberOf _
56178                * @since 4.0.0
56179                * @alias extendWith
56180                * @category Object
56181                * @param {Object} object The destination object.
56182                * @param {...Object} sources The source objects.
56183                * @param {Function} [customizer] The function to customize assigned values.
56184                * @returns {Object} Returns `object`.
56185                * @see _.assignWith
56186                * @example
56187                *
56188                * function customizer(objValue, srcValue) {
56189                *   return _.isUndefined(objValue) ? srcValue : objValue;
56190                * }
56191                *
56192                * var defaults = _.partialRight(_.assignInWith, customizer);
56193                *
56194                * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
56195                * // => { 'a': 1, 'b': 2 }
56196                */
56197
56198               var assignInWith = createAssigner(function (object, source, srcIndex, customizer) {
56199                 copyObject(source, keysIn(source), object, customizer);
56200               });
56201               /**
56202                * This method is like `_.assign` except that it accepts `customizer`
56203                * which is invoked to produce the assigned values. If `customizer` returns
56204                * `undefined`, assignment is handled by the method instead. The `customizer`
56205                * is invoked with five arguments: (objValue, srcValue, key, object, source).
56206                *
56207                * **Note:** This method mutates `object`.
56208                *
56209                * @static
56210                * @memberOf _
56211                * @since 4.0.0
56212                * @category Object
56213                * @param {Object} object The destination object.
56214                * @param {...Object} sources The source objects.
56215                * @param {Function} [customizer] The function to customize assigned values.
56216                * @returns {Object} Returns `object`.
56217                * @see _.assignInWith
56218                * @example
56219                *
56220                * function customizer(objValue, srcValue) {
56221                *   return _.isUndefined(objValue) ? srcValue : objValue;
56222                * }
56223                *
56224                * var defaults = _.partialRight(_.assignWith, customizer);
56225                *
56226                * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
56227                * // => { 'a': 1, 'b': 2 }
56228                */
56229
56230               var assignWith = createAssigner(function (object, source, srcIndex, customizer) {
56231                 copyObject(source, keys(source), object, customizer);
56232               });
56233               /**
56234                * Creates an array of values corresponding to `paths` of `object`.
56235                *
56236                * @static
56237                * @memberOf _
56238                * @since 1.0.0
56239                * @category Object
56240                * @param {Object} object The object to iterate over.
56241                * @param {...(string|string[])} [paths] The property paths to pick.
56242                * @returns {Array} Returns the picked values.
56243                * @example
56244                *
56245                * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
56246                *
56247                * _.at(object, ['a[0].b.c', 'a[1]']);
56248                * // => [3, 4]
56249                */
56250
56251               var at = flatRest(baseAt);
56252               /**
56253                * Creates an object that inherits from the `prototype` object. If a
56254                * `properties` object is given, its own enumerable string keyed properties
56255                * are assigned to the created object.
56256                *
56257                * @static
56258                * @memberOf _
56259                * @since 2.3.0
56260                * @category Object
56261                * @param {Object} prototype The object to inherit from.
56262                * @param {Object} [properties] The properties to assign to the object.
56263                * @returns {Object} Returns the new object.
56264                * @example
56265                *
56266                * function Shape() {
56267                *   this.x = 0;
56268                *   this.y = 0;
56269                * }
56270                *
56271                * function Circle() {
56272                *   Shape.call(this);
56273                * }
56274                *
56275                * Circle.prototype = _.create(Shape.prototype, {
56276                *   'constructor': Circle
56277                * });
56278                *
56279                * var circle = new Circle;
56280                * circle instanceof Circle;
56281                * // => true
56282                *
56283                * circle instanceof Shape;
56284                * // => true
56285                */
56286
56287               function create(prototype, properties) {
56288                 var result = baseCreate(prototype);
56289                 return properties == null ? result : baseAssign(result, properties);
56290               }
56291               /**
56292                * Assigns own and inherited enumerable string keyed properties of source
56293                * objects to the destination object for all destination properties that
56294                * resolve to `undefined`. Source objects are applied from left to right.
56295                * Once a property is set, additional values of the same property are ignored.
56296                *
56297                * **Note:** This method mutates `object`.
56298                *
56299                * @static
56300                * @since 0.1.0
56301                * @memberOf _
56302                * @category Object
56303                * @param {Object} object The destination object.
56304                * @param {...Object} [sources] The source objects.
56305                * @returns {Object} Returns `object`.
56306                * @see _.defaultsDeep
56307                * @example
56308                *
56309                * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
56310                * // => { 'a': 1, 'b': 2 }
56311                */
56312
56313
56314               var defaults = baseRest(function (object, sources) {
56315                 object = Object(object);
56316                 var index = -1;
56317                 var length = sources.length;
56318                 var guard = length > 2 ? sources[2] : undefined$1;
56319
56320                 if (guard && isIterateeCall(sources[0], sources[1], guard)) {
56321                   length = 1;
56322                 }
56323
56324                 while (++index < length) {
56325                   var source = sources[index];
56326                   var props = keysIn(source);
56327                   var propsIndex = -1;
56328                   var propsLength = props.length;
56329
56330                   while (++propsIndex < propsLength) {
56331                     var key = props[propsIndex];
56332                     var value = object[key];
56333
56334                     if (value === undefined$1 || eq(value, objectProto[key]) && !hasOwnProperty.call(object, key)) {
56335                       object[key] = source[key];
56336                     }
56337                   }
56338                 }
56339
56340                 return object;
56341               });
56342               /**
56343                * This method is like `_.defaults` except that it recursively assigns
56344                * default properties.
56345                *
56346                * **Note:** This method mutates `object`.
56347                *
56348                * @static
56349                * @memberOf _
56350                * @since 3.10.0
56351                * @category Object
56352                * @param {Object} object The destination object.
56353                * @param {...Object} [sources] The source objects.
56354                * @returns {Object} Returns `object`.
56355                * @see _.defaults
56356                * @example
56357                *
56358                * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
56359                * // => { 'a': { 'b': 2, 'c': 3 } }
56360                */
56361
56362               var defaultsDeep = baseRest(function (args) {
56363                 args.push(undefined$1, customDefaultsMerge);
56364                 return apply(mergeWith, undefined$1, args);
56365               });
56366               /**
56367                * This method is like `_.find` except that it returns the key of the first
56368                * element `predicate` returns truthy for instead of the element itself.
56369                *
56370                * @static
56371                * @memberOf _
56372                * @since 1.1.0
56373                * @category Object
56374                * @param {Object} object The object to inspect.
56375                * @param {Function} [predicate=_.identity] The function invoked per iteration.
56376                * @returns {string|undefined} Returns the key of the matched element,
56377                *  else `undefined`.
56378                * @example
56379                *
56380                * var users = {
56381                *   'barney':  { 'age': 36, 'active': true },
56382                *   'fred':    { 'age': 40, 'active': false },
56383                *   'pebbles': { 'age': 1,  'active': true }
56384                * };
56385                *
56386                * _.findKey(users, function(o) { return o.age < 40; });
56387                * // => 'barney' (iteration order is not guaranteed)
56388                *
56389                * // The `_.matches` iteratee shorthand.
56390                * _.findKey(users, { 'age': 1, 'active': true });
56391                * // => 'pebbles'
56392                *
56393                * // The `_.matchesProperty` iteratee shorthand.
56394                * _.findKey(users, ['active', false]);
56395                * // => 'fred'
56396                *
56397                * // The `_.property` iteratee shorthand.
56398                * _.findKey(users, 'active');
56399                * // => 'barney'
56400                */
56401
56402               function findKey(object, predicate) {
56403                 return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
56404               }
56405               /**
56406                * This method is like `_.findKey` except that it iterates over elements of
56407                * a collection in the opposite order.
56408                *
56409                * @static
56410                * @memberOf _
56411                * @since 2.0.0
56412                * @category Object
56413                * @param {Object} object The object to inspect.
56414                * @param {Function} [predicate=_.identity] The function invoked per iteration.
56415                * @returns {string|undefined} Returns the key of the matched element,
56416                *  else `undefined`.
56417                * @example
56418                *
56419                * var users = {
56420                *   'barney':  { 'age': 36, 'active': true },
56421                *   'fred':    { 'age': 40, 'active': false },
56422                *   'pebbles': { 'age': 1,  'active': true }
56423                * };
56424                *
56425                * _.findLastKey(users, function(o) { return o.age < 40; });
56426                * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
56427                *
56428                * // The `_.matches` iteratee shorthand.
56429                * _.findLastKey(users, { 'age': 36, 'active': true });
56430                * // => 'barney'
56431                *
56432                * // The `_.matchesProperty` iteratee shorthand.
56433                * _.findLastKey(users, ['active', false]);
56434                * // => 'fred'
56435                *
56436                * // The `_.property` iteratee shorthand.
56437                * _.findLastKey(users, 'active');
56438                * // => 'pebbles'
56439                */
56440
56441
56442               function findLastKey(object, predicate) {
56443                 return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
56444               }
56445               /**
56446                * Iterates over own and inherited enumerable string keyed properties of an
56447                * object and invokes `iteratee` for each property. The iteratee is invoked
56448                * with three arguments: (value, key, object). Iteratee functions may exit
56449                * iteration early by explicitly returning `false`.
56450                *
56451                * @static
56452                * @memberOf _
56453                * @since 0.3.0
56454                * @category Object
56455                * @param {Object} object The object to iterate over.
56456                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56457                * @returns {Object} Returns `object`.
56458                * @see _.forInRight
56459                * @example
56460                *
56461                * function Foo() {
56462                *   this.a = 1;
56463                *   this.b = 2;
56464                * }
56465                *
56466                * Foo.prototype.c = 3;
56467                *
56468                * _.forIn(new Foo, function(value, key) {
56469                *   console.log(key);
56470                * });
56471                * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
56472                */
56473
56474
56475               function forIn(object, iteratee) {
56476                 return object == null ? object : baseFor(object, getIteratee(iteratee, 3), keysIn);
56477               }
56478               /**
56479                * This method is like `_.forIn` except that it iterates over properties of
56480                * `object` in the opposite order.
56481                *
56482                * @static
56483                * @memberOf _
56484                * @since 2.0.0
56485                * @category Object
56486                * @param {Object} object The object to iterate over.
56487                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56488                * @returns {Object} Returns `object`.
56489                * @see _.forIn
56490                * @example
56491                *
56492                * function Foo() {
56493                *   this.a = 1;
56494                *   this.b = 2;
56495                * }
56496                *
56497                * Foo.prototype.c = 3;
56498                *
56499                * _.forInRight(new Foo, function(value, key) {
56500                *   console.log(key);
56501                * });
56502                * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
56503                */
56504
56505
56506               function forInRight(object, iteratee) {
56507                 return object == null ? object : baseForRight(object, getIteratee(iteratee, 3), keysIn);
56508               }
56509               /**
56510                * Iterates over own enumerable string keyed properties of an object and
56511                * invokes `iteratee` for each property. The iteratee is invoked with three
56512                * arguments: (value, key, object). Iteratee functions may exit iteration
56513                * early by explicitly returning `false`.
56514                *
56515                * @static
56516                * @memberOf _
56517                * @since 0.3.0
56518                * @category Object
56519                * @param {Object} object The object to iterate over.
56520                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56521                * @returns {Object} Returns `object`.
56522                * @see _.forOwnRight
56523                * @example
56524                *
56525                * function Foo() {
56526                *   this.a = 1;
56527                *   this.b = 2;
56528                * }
56529                *
56530                * Foo.prototype.c = 3;
56531                *
56532                * _.forOwn(new Foo, function(value, key) {
56533                *   console.log(key);
56534                * });
56535                * // => Logs 'a' then 'b' (iteration order is not guaranteed).
56536                */
56537
56538
56539               function forOwn(object, iteratee) {
56540                 return object && baseForOwn(object, getIteratee(iteratee, 3));
56541               }
56542               /**
56543                * This method is like `_.forOwn` except that it iterates over properties of
56544                * `object` in the opposite order.
56545                *
56546                * @static
56547                * @memberOf _
56548                * @since 2.0.0
56549                * @category Object
56550                * @param {Object} object The object to iterate over.
56551                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56552                * @returns {Object} Returns `object`.
56553                * @see _.forOwn
56554                * @example
56555                *
56556                * function Foo() {
56557                *   this.a = 1;
56558                *   this.b = 2;
56559                * }
56560                *
56561                * Foo.prototype.c = 3;
56562                *
56563                * _.forOwnRight(new Foo, function(value, key) {
56564                *   console.log(key);
56565                * });
56566                * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
56567                */
56568
56569
56570               function forOwnRight(object, iteratee) {
56571                 return object && baseForOwnRight(object, getIteratee(iteratee, 3));
56572               }
56573               /**
56574                * Creates an array of function property names from own enumerable properties
56575                * of `object`.
56576                *
56577                * @static
56578                * @since 0.1.0
56579                * @memberOf _
56580                * @category Object
56581                * @param {Object} object The object to inspect.
56582                * @returns {Array} Returns the function names.
56583                * @see _.functionsIn
56584                * @example
56585                *
56586                * function Foo() {
56587                *   this.a = _.constant('a');
56588                *   this.b = _.constant('b');
56589                * }
56590                *
56591                * Foo.prototype.c = _.constant('c');
56592                *
56593                * _.functions(new Foo);
56594                * // => ['a', 'b']
56595                */
56596
56597
56598               function functions(object) {
56599                 return object == null ? [] : baseFunctions(object, keys(object));
56600               }
56601               /**
56602                * Creates an array of function property names from own and inherited
56603                * enumerable properties of `object`.
56604                *
56605                * @static
56606                * @memberOf _
56607                * @since 4.0.0
56608                * @category Object
56609                * @param {Object} object The object to inspect.
56610                * @returns {Array} Returns the function names.
56611                * @see _.functions
56612                * @example
56613                *
56614                * function Foo() {
56615                *   this.a = _.constant('a');
56616                *   this.b = _.constant('b');
56617                * }
56618                *
56619                * Foo.prototype.c = _.constant('c');
56620                *
56621                * _.functionsIn(new Foo);
56622                * // => ['a', 'b', 'c']
56623                */
56624
56625
56626               function functionsIn(object) {
56627                 return object == null ? [] : baseFunctions(object, keysIn(object));
56628               }
56629               /**
56630                * Gets the value at `path` of `object`. If the resolved value is
56631                * `undefined`, the `defaultValue` is returned in its place.
56632                *
56633                * @static
56634                * @memberOf _
56635                * @since 3.7.0
56636                * @category Object
56637                * @param {Object} object The object to query.
56638                * @param {Array|string} path The path of the property to get.
56639                * @param {*} [defaultValue] The value returned for `undefined` resolved values.
56640                * @returns {*} Returns the resolved value.
56641                * @example
56642                *
56643                * var object = { 'a': [{ 'b': { 'c': 3 } }] };
56644                *
56645                * _.get(object, 'a[0].b.c');
56646                * // => 3
56647                *
56648                * _.get(object, ['a', '0', 'b', 'c']);
56649                * // => 3
56650                *
56651                * _.get(object, 'a.b.c', 'default');
56652                * // => 'default'
56653                */
56654
56655
56656               function get(object, path, defaultValue) {
56657                 var result = object == null ? undefined$1 : baseGet(object, path);
56658                 return result === undefined$1 ? defaultValue : result;
56659               }
56660               /**
56661                * Checks if `path` is a direct property of `object`.
56662                *
56663                * @static
56664                * @since 0.1.0
56665                * @memberOf _
56666                * @category Object
56667                * @param {Object} object The object to query.
56668                * @param {Array|string} path The path to check.
56669                * @returns {boolean} Returns `true` if `path` exists, else `false`.
56670                * @example
56671                *
56672                * var object = { 'a': { 'b': 2 } };
56673                * var other = _.create({ 'a': _.create({ 'b': 2 }) });
56674                *
56675                * _.has(object, 'a');
56676                * // => true
56677                *
56678                * _.has(object, 'a.b');
56679                * // => true
56680                *
56681                * _.has(object, ['a', 'b']);
56682                * // => true
56683                *
56684                * _.has(other, 'a');
56685                * // => false
56686                */
56687
56688
56689               function has(object, path) {
56690                 return object != null && hasPath(object, path, baseHas);
56691               }
56692               /**
56693                * Checks if `path` is a direct or inherited property of `object`.
56694                *
56695                * @static
56696                * @memberOf _
56697                * @since 4.0.0
56698                * @category Object
56699                * @param {Object} object The object to query.
56700                * @param {Array|string} path The path to check.
56701                * @returns {boolean} Returns `true` if `path` exists, else `false`.
56702                * @example
56703                *
56704                * var object = _.create({ 'a': _.create({ 'b': 2 }) });
56705                *
56706                * _.hasIn(object, 'a');
56707                * // => true
56708                *
56709                * _.hasIn(object, 'a.b');
56710                * // => true
56711                *
56712                * _.hasIn(object, ['a', 'b']);
56713                * // => true
56714                *
56715                * _.hasIn(object, 'b');
56716                * // => false
56717                */
56718
56719
56720               function hasIn(object, path) {
56721                 return object != null && hasPath(object, path, baseHasIn);
56722               }
56723               /**
56724                * Creates an object composed of the inverted keys and values of `object`.
56725                * If `object` contains duplicate values, subsequent values overwrite
56726                * property assignments of previous values.
56727                *
56728                * @static
56729                * @memberOf _
56730                * @since 0.7.0
56731                * @category Object
56732                * @param {Object} object The object to invert.
56733                * @returns {Object} Returns the new inverted object.
56734                * @example
56735                *
56736                * var object = { 'a': 1, 'b': 2, 'c': 1 };
56737                *
56738                * _.invert(object);
56739                * // => { '1': 'c', '2': 'b' }
56740                */
56741
56742
56743               var invert = createInverter(function (result, value, key) {
56744                 if (value != null && typeof value.toString != 'function') {
56745                   value = nativeObjectToString.call(value);
56746                 }
56747
56748                 result[value] = key;
56749               }, constant(identity));
56750               /**
56751                * This method is like `_.invert` except that the inverted object is generated
56752                * from the results of running each element of `object` thru `iteratee`. The
56753                * corresponding inverted value of each inverted key is an array of keys
56754                * responsible for generating the inverted value. The iteratee is invoked
56755                * with one argument: (value).
56756                *
56757                * @static
56758                * @memberOf _
56759                * @since 4.1.0
56760                * @category Object
56761                * @param {Object} object The object to invert.
56762                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
56763                * @returns {Object} Returns the new inverted object.
56764                * @example
56765                *
56766                * var object = { 'a': 1, 'b': 2, 'c': 1 };
56767                *
56768                * _.invertBy(object);
56769                * // => { '1': ['a', 'c'], '2': ['b'] }
56770                *
56771                * _.invertBy(object, function(value) {
56772                *   return 'group' + value;
56773                * });
56774                * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
56775                */
56776
56777               var invertBy = createInverter(function (result, value, key) {
56778                 if (value != null && typeof value.toString != 'function') {
56779                   value = nativeObjectToString.call(value);
56780                 }
56781
56782                 if (hasOwnProperty.call(result, value)) {
56783                   result[value].push(key);
56784                 } else {
56785                   result[value] = [key];
56786                 }
56787               }, getIteratee);
56788               /**
56789                * Invokes the method at `path` of `object`.
56790                *
56791                * @static
56792                * @memberOf _
56793                * @since 4.0.0
56794                * @category Object
56795                * @param {Object} object The object to query.
56796                * @param {Array|string} path The path of the method to invoke.
56797                * @param {...*} [args] The arguments to invoke the method with.
56798                * @returns {*} Returns the result of the invoked method.
56799                * @example
56800                *
56801                * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
56802                *
56803                * _.invoke(object, 'a[0].b.c.slice', 1, 3);
56804                * // => [2, 3]
56805                */
56806
56807               var invoke = baseRest(baseInvoke);
56808               /**
56809                * Creates an array of the own enumerable property names of `object`.
56810                *
56811                * **Note:** Non-object values are coerced to objects. See the
56812                * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
56813                * for more details.
56814                *
56815                * @static
56816                * @since 0.1.0
56817                * @memberOf _
56818                * @category Object
56819                * @param {Object} object The object to query.
56820                * @returns {Array} Returns the array of property names.
56821                * @example
56822                *
56823                * function Foo() {
56824                *   this.a = 1;
56825                *   this.b = 2;
56826                * }
56827                *
56828                * Foo.prototype.c = 3;
56829                *
56830                * _.keys(new Foo);
56831                * // => ['a', 'b'] (iteration order is not guaranteed)
56832                *
56833                * _.keys('hi');
56834                * // => ['0', '1']
56835                */
56836
56837               function keys(object) {
56838                 return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
56839               }
56840               /**
56841                * Creates an array of the own and inherited enumerable property names of `object`.
56842                *
56843                * **Note:** Non-object values are coerced to objects.
56844                *
56845                * @static
56846                * @memberOf _
56847                * @since 3.0.0
56848                * @category Object
56849                * @param {Object} object The object to query.
56850                * @returns {Array} Returns the array of property names.
56851                * @example
56852                *
56853                * function Foo() {
56854                *   this.a = 1;
56855                *   this.b = 2;
56856                * }
56857                *
56858                * Foo.prototype.c = 3;
56859                *
56860                * _.keysIn(new Foo);
56861                * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
56862                */
56863
56864
56865               function keysIn(object) {
56866                 return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
56867               }
56868               /**
56869                * The opposite of `_.mapValues`; this method creates an object with the
56870                * same values as `object` and keys generated by running each own enumerable
56871                * string keyed property of `object` thru `iteratee`. The iteratee is invoked
56872                * with three arguments: (value, key, object).
56873                *
56874                * @static
56875                * @memberOf _
56876                * @since 3.8.0
56877                * @category Object
56878                * @param {Object} object The object to iterate over.
56879                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56880                * @returns {Object} Returns the new mapped object.
56881                * @see _.mapValues
56882                * @example
56883                *
56884                * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
56885                *   return key + value;
56886                * });
56887                * // => { 'a1': 1, 'b2': 2 }
56888                */
56889
56890
56891               function mapKeys(object, iteratee) {
56892                 var result = {};
56893                 iteratee = getIteratee(iteratee, 3);
56894                 baseForOwn(object, function (value, key, object) {
56895                   baseAssignValue(result, iteratee(value, key, object), value);
56896                 });
56897                 return result;
56898               }
56899               /**
56900                * Creates an object with the same keys as `object` and values generated
56901                * by running each own enumerable string keyed property of `object` thru
56902                * `iteratee`. The iteratee is invoked with three arguments:
56903                * (value, key, object).
56904                *
56905                * @static
56906                * @memberOf _
56907                * @since 2.4.0
56908                * @category Object
56909                * @param {Object} object The object to iterate over.
56910                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
56911                * @returns {Object} Returns the new mapped object.
56912                * @see _.mapKeys
56913                * @example
56914                *
56915                * var users = {
56916                *   'fred':    { 'user': 'fred',    'age': 40 },
56917                *   'pebbles': { 'user': 'pebbles', 'age': 1 }
56918                * };
56919                *
56920                * _.mapValues(users, function(o) { return o.age; });
56921                * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
56922                *
56923                * // The `_.property` iteratee shorthand.
56924                * _.mapValues(users, 'age');
56925                * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
56926                */
56927
56928
56929               function mapValues(object, iteratee) {
56930                 var result = {};
56931                 iteratee = getIteratee(iteratee, 3);
56932                 baseForOwn(object, function (value, key, object) {
56933                   baseAssignValue(result, key, iteratee(value, key, object));
56934                 });
56935                 return result;
56936               }
56937               /**
56938                * This method is like `_.assign` except that it recursively merges own and
56939                * inherited enumerable string keyed properties of source objects into the
56940                * destination object. Source properties that resolve to `undefined` are
56941                * skipped if a destination value exists. Array and plain object properties
56942                * are merged recursively. Other objects and value types are overridden by
56943                * assignment. Source objects are applied from left to right. Subsequent
56944                * sources overwrite property assignments of previous sources.
56945                *
56946                * **Note:** This method mutates `object`.
56947                *
56948                * @static
56949                * @memberOf _
56950                * @since 0.5.0
56951                * @category Object
56952                * @param {Object} object The destination object.
56953                * @param {...Object} [sources] The source objects.
56954                * @returns {Object} Returns `object`.
56955                * @example
56956                *
56957                * var object = {
56958                *   'a': [{ 'b': 2 }, { 'd': 4 }]
56959                * };
56960                *
56961                * var other = {
56962                *   'a': [{ 'c': 3 }, { 'e': 5 }]
56963                * };
56964                *
56965                * _.merge(object, other);
56966                * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
56967                */
56968
56969
56970               var merge = createAssigner(function (object, source, srcIndex) {
56971                 baseMerge(object, source, srcIndex);
56972               });
56973               /**
56974                * This method is like `_.merge` except that it accepts `customizer` which
56975                * is invoked to produce the merged values of the destination and source
56976                * properties. If `customizer` returns `undefined`, merging is handled by the
56977                * method instead. The `customizer` is invoked with six arguments:
56978                * (objValue, srcValue, key, object, source, stack).
56979                *
56980                * **Note:** This method mutates `object`.
56981                *
56982                * @static
56983                * @memberOf _
56984                * @since 4.0.0
56985                * @category Object
56986                * @param {Object} object The destination object.
56987                * @param {...Object} sources The source objects.
56988                * @param {Function} customizer The function to customize assigned values.
56989                * @returns {Object} Returns `object`.
56990                * @example
56991                *
56992                * function customizer(objValue, srcValue) {
56993                *   if (_.isArray(objValue)) {
56994                *     return objValue.concat(srcValue);
56995                *   }
56996                * }
56997                *
56998                * var object = { 'a': [1], 'b': [2] };
56999                * var other = { 'a': [3], 'b': [4] };
57000                *
57001                * _.mergeWith(object, other, customizer);
57002                * // => { 'a': [1, 3], 'b': [2, 4] }
57003                */
57004
57005               var mergeWith = createAssigner(function (object, source, srcIndex, customizer) {
57006                 baseMerge(object, source, srcIndex, customizer);
57007               });
57008               /**
57009                * The opposite of `_.pick`; this method creates an object composed of the
57010                * own and inherited enumerable property paths of `object` that are not omitted.
57011                *
57012                * **Note:** This method is considerably slower than `_.pick`.
57013                *
57014                * @static
57015                * @since 0.1.0
57016                * @memberOf _
57017                * @category Object
57018                * @param {Object} object The source object.
57019                * @param {...(string|string[])} [paths] The property paths to omit.
57020                * @returns {Object} Returns the new object.
57021                * @example
57022                *
57023                * var object = { 'a': 1, 'b': '2', 'c': 3 };
57024                *
57025                * _.omit(object, ['a', 'c']);
57026                * // => { 'b': '2' }
57027                */
57028
57029               var omit = flatRest(function (object, paths) {
57030                 var result = {};
57031
57032                 if (object == null) {
57033                   return result;
57034                 }
57035
57036                 var isDeep = false;
57037                 paths = arrayMap(paths, function (path) {
57038                   path = castPath(path, object);
57039                   isDeep || (isDeep = path.length > 1);
57040                   return path;
57041                 });
57042                 copyObject(object, getAllKeysIn(object), result);
57043
57044                 if (isDeep) {
57045                   result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
57046                 }
57047
57048                 var length = paths.length;
57049
57050                 while (length--) {
57051                   baseUnset(result, paths[length]);
57052                 }
57053
57054                 return result;
57055               });
57056               /**
57057                * The opposite of `_.pickBy`; this method creates an object composed of
57058                * the own and inherited enumerable string keyed properties of `object` that
57059                * `predicate` doesn't return truthy for. The predicate is invoked with two
57060                * arguments: (value, key).
57061                *
57062                * @static
57063                * @memberOf _
57064                * @since 4.0.0
57065                * @category Object
57066                * @param {Object} object The source object.
57067                * @param {Function} [predicate=_.identity] The function invoked per property.
57068                * @returns {Object} Returns the new object.
57069                * @example
57070                *
57071                * var object = { 'a': 1, 'b': '2', 'c': 3 };
57072                *
57073                * _.omitBy(object, _.isNumber);
57074                * // => { 'b': '2' }
57075                */
57076
57077               function omitBy(object, predicate) {
57078                 return pickBy(object, negate(getIteratee(predicate)));
57079               }
57080               /**
57081                * Creates an object composed of the picked `object` properties.
57082                *
57083                * @static
57084                * @since 0.1.0
57085                * @memberOf _
57086                * @category Object
57087                * @param {Object} object The source object.
57088                * @param {...(string|string[])} [paths] The property paths to pick.
57089                * @returns {Object} Returns the new object.
57090                * @example
57091                *
57092                * var object = { 'a': 1, 'b': '2', 'c': 3 };
57093                *
57094                * _.pick(object, ['a', 'c']);
57095                * // => { 'a': 1, 'c': 3 }
57096                */
57097
57098
57099               var pick = flatRest(function (object, paths) {
57100                 return object == null ? {} : basePick(object, paths);
57101               });
57102               /**
57103                * Creates an object composed of the `object` properties `predicate` returns
57104                * truthy for. The predicate is invoked with two arguments: (value, key).
57105                *
57106                * @static
57107                * @memberOf _
57108                * @since 4.0.0
57109                * @category Object
57110                * @param {Object} object The source object.
57111                * @param {Function} [predicate=_.identity] The function invoked per property.
57112                * @returns {Object} Returns the new object.
57113                * @example
57114                *
57115                * var object = { 'a': 1, 'b': '2', 'c': 3 };
57116                *
57117                * _.pickBy(object, _.isNumber);
57118                * // => { 'a': 1, 'c': 3 }
57119                */
57120
57121               function pickBy(object, predicate) {
57122                 if (object == null) {
57123                   return {};
57124                 }
57125
57126                 var props = arrayMap(getAllKeysIn(object), function (prop) {
57127                   return [prop];
57128                 });
57129                 predicate = getIteratee(predicate);
57130                 return basePickBy(object, props, function (value, path) {
57131                   return predicate(value, path[0]);
57132                 });
57133               }
57134               /**
57135                * This method is like `_.get` except that if the resolved value is a
57136                * function it's invoked with the `this` binding of its parent object and
57137                * its result is returned.
57138                *
57139                * @static
57140                * @since 0.1.0
57141                * @memberOf _
57142                * @category Object
57143                * @param {Object} object The object to query.
57144                * @param {Array|string} path The path of the property to resolve.
57145                * @param {*} [defaultValue] The value returned for `undefined` resolved values.
57146                * @returns {*} Returns the resolved value.
57147                * @example
57148                *
57149                * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
57150                *
57151                * _.result(object, 'a[0].b.c1');
57152                * // => 3
57153                *
57154                * _.result(object, 'a[0].b.c2');
57155                * // => 4
57156                *
57157                * _.result(object, 'a[0].b.c3', 'default');
57158                * // => 'default'
57159                *
57160                * _.result(object, 'a[0].b.c3', _.constant('default'));
57161                * // => 'default'
57162                */
57163
57164
57165               function result(object, path, defaultValue) {
57166                 path = castPath(path, object);
57167                 var index = -1,
57168                     length = path.length; // Ensure the loop is entered when path is empty.
57169
57170                 if (!length) {
57171                   length = 1;
57172                   object = undefined$1;
57173                 }
57174
57175                 while (++index < length) {
57176                   var value = object == null ? undefined$1 : object[toKey(path[index])];
57177
57178                   if (value === undefined$1) {
57179                     index = length;
57180                     value = defaultValue;
57181                   }
57182
57183                   object = isFunction(value) ? value.call(object) : value;
57184                 }
57185
57186                 return object;
57187               }
57188               /**
57189                * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
57190                * it's created. Arrays are created for missing index properties while objects
57191                * are created for all other missing properties. Use `_.setWith` to customize
57192                * `path` creation.
57193                *
57194                * **Note:** This method mutates `object`.
57195                *
57196                * @static
57197                * @memberOf _
57198                * @since 3.7.0
57199                * @category Object
57200                * @param {Object} object The object to modify.
57201                * @param {Array|string} path The path of the property to set.
57202                * @param {*} value The value to set.
57203                * @returns {Object} Returns `object`.
57204                * @example
57205                *
57206                * var object = { 'a': [{ 'b': { 'c': 3 } }] };
57207                *
57208                * _.set(object, 'a[0].b.c', 4);
57209                * console.log(object.a[0].b.c);
57210                * // => 4
57211                *
57212                * _.set(object, ['x', '0', 'y', 'z'], 5);
57213                * console.log(object.x[0].y.z);
57214                * // => 5
57215                */
57216
57217
57218               function set(object, path, value) {
57219                 return object == null ? object : baseSet(object, path, value);
57220               }
57221               /**
57222                * This method is like `_.set` except that it accepts `customizer` which is
57223                * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
57224                * path creation is handled by the method instead. The `customizer` is invoked
57225                * with three arguments: (nsValue, key, nsObject).
57226                *
57227                * **Note:** This method mutates `object`.
57228                *
57229                * @static
57230                * @memberOf _
57231                * @since 4.0.0
57232                * @category Object
57233                * @param {Object} object The object to modify.
57234                * @param {Array|string} path The path of the property to set.
57235                * @param {*} value The value to set.
57236                * @param {Function} [customizer] The function to customize assigned values.
57237                * @returns {Object} Returns `object`.
57238                * @example
57239                *
57240                * var object = {};
57241                *
57242                * _.setWith(object, '[0][1]', 'a', Object);
57243                * // => { '0': { '1': 'a' } }
57244                */
57245
57246
57247               function setWith(object, path, value, customizer) {
57248                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
57249                 return object == null ? object : baseSet(object, path, value, customizer);
57250               }
57251               /**
57252                * Creates an array of own enumerable string keyed-value pairs for `object`
57253                * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
57254                * entries are returned.
57255                *
57256                * @static
57257                * @memberOf _
57258                * @since 4.0.0
57259                * @alias entries
57260                * @category Object
57261                * @param {Object} object The object to query.
57262                * @returns {Array} Returns the key-value pairs.
57263                * @example
57264                *
57265                * function Foo() {
57266                *   this.a = 1;
57267                *   this.b = 2;
57268                * }
57269                *
57270                * Foo.prototype.c = 3;
57271                *
57272                * _.toPairs(new Foo);
57273                * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
57274                */
57275
57276
57277               var toPairs = createToPairs(keys);
57278               /**
57279                * Creates an array of own and inherited enumerable string keyed-value pairs
57280                * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
57281                * or set, its entries are returned.
57282                *
57283                * @static
57284                * @memberOf _
57285                * @since 4.0.0
57286                * @alias entriesIn
57287                * @category Object
57288                * @param {Object} object The object to query.
57289                * @returns {Array} Returns the key-value pairs.
57290                * @example
57291                *
57292                * function Foo() {
57293                *   this.a = 1;
57294                *   this.b = 2;
57295                * }
57296                *
57297                * Foo.prototype.c = 3;
57298                *
57299                * _.toPairsIn(new Foo);
57300                * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
57301                */
57302
57303               var toPairsIn = createToPairs(keysIn);
57304               /**
57305                * An alternative to `_.reduce`; this method transforms `object` to a new
57306                * `accumulator` object which is the result of running each of its own
57307                * enumerable string keyed properties thru `iteratee`, with each invocation
57308                * potentially mutating the `accumulator` object. If `accumulator` is not
57309                * provided, a new object with the same `[[Prototype]]` will be used. The
57310                * iteratee is invoked with four arguments: (accumulator, value, key, object).
57311                * Iteratee functions may exit iteration early by explicitly returning `false`.
57312                *
57313                * @static
57314                * @memberOf _
57315                * @since 1.3.0
57316                * @category Object
57317                * @param {Object} object The object to iterate over.
57318                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
57319                * @param {*} [accumulator] The custom accumulator value.
57320                * @returns {*} Returns the accumulated value.
57321                * @example
57322                *
57323                * _.transform([2, 3, 4], function(result, n) {
57324                *   result.push(n *= n);
57325                *   return n % 2 == 0;
57326                * }, []);
57327                * // => [4, 9]
57328                *
57329                * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
57330                *   (result[value] || (result[value] = [])).push(key);
57331                * }, {});
57332                * // => { '1': ['a', 'c'], '2': ['b'] }
57333                */
57334
57335               function transform(object, iteratee, accumulator) {
57336                 var isArr = isArray(object),
57337                     isArrLike = isArr || isBuffer(object) || isTypedArray(object);
57338                 iteratee = getIteratee(iteratee, 4);
57339
57340                 if (accumulator == null) {
57341                   var Ctor = object && object.constructor;
57342
57343                   if (isArrLike) {
57344                     accumulator = isArr ? new Ctor() : [];
57345                   } else if (isObject(object)) {
57346                     accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
57347                   } else {
57348                     accumulator = {};
57349                   }
57350                 }
57351
57352                 (isArrLike ? arrayEach : baseForOwn)(object, function (value, index, object) {
57353                   return iteratee(accumulator, value, index, object);
57354                 });
57355                 return accumulator;
57356               }
57357               /**
57358                * Removes the property at `path` of `object`.
57359                *
57360                * **Note:** This method mutates `object`.
57361                *
57362                * @static
57363                * @memberOf _
57364                * @since 4.0.0
57365                * @category Object
57366                * @param {Object} object The object to modify.
57367                * @param {Array|string} path The path of the property to unset.
57368                * @returns {boolean} Returns `true` if the property is deleted, else `false`.
57369                * @example
57370                *
57371                * var object = { 'a': [{ 'b': { 'c': 7 } }] };
57372                * _.unset(object, 'a[0].b.c');
57373                * // => true
57374                *
57375                * console.log(object);
57376                * // => { 'a': [{ 'b': {} }] };
57377                *
57378                * _.unset(object, ['a', '0', 'b', 'c']);
57379                * // => true
57380                *
57381                * console.log(object);
57382                * // => { 'a': [{ 'b': {} }] };
57383                */
57384
57385
57386               function unset(object, path) {
57387                 return object == null ? true : baseUnset(object, path);
57388               }
57389               /**
57390                * This method is like `_.set` except that accepts `updater` to produce the
57391                * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
57392                * is invoked with one argument: (value).
57393                *
57394                * **Note:** This method mutates `object`.
57395                *
57396                * @static
57397                * @memberOf _
57398                * @since 4.6.0
57399                * @category Object
57400                * @param {Object} object The object to modify.
57401                * @param {Array|string} path The path of the property to set.
57402                * @param {Function} updater The function to produce the updated value.
57403                * @returns {Object} Returns `object`.
57404                * @example
57405                *
57406                * var object = { 'a': [{ 'b': { 'c': 3 } }] };
57407                *
57408                * _.update(object, 'a[0].b.c', function(n) { return n * n; });
57409                * console.log(object.a[0].b.c);
57410                * // => 9
57411                *
57412                * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
57413                * console.log(object.x[0].y.z);
57414                * // => 0
57415                */
57416
57417
57418               function update(object, path, updater) {
57419                 return object == null ? object : baseUpdate(object, path, castFunction(updater));
57420               }
57421               /**
57422                * This method is like `_.update` except that it accepts `customizer` which is
57423                * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
57424                * path creation is handled by the method instead. The `customizer` is invoked
57425                * with three arguments: (nsValue, key, nsObject).
57426                *
57427                * **Note:** This method mutates `object`.
57428                *
57429                * @static
57430                * @memberOf _
57431                * @since 4.6.0
57432                * @category Object
57433                * @param {Object} object The object to modify.
57434                * @param {Array|string} path The path of the property to set.
57435                * @param {Function} updater The function to produce the updated value.
57436                * @param {Function} [customizer] The function to customize assigned values.
57437                * @returns {Object} Returns `object`.
57438                * @example
57439                *
57440                * var object = {};
57441                *
57442                * _.updateWith(object, '[0][1]', _.constant('a'), Object);
57443                * // => { '0': { '1': 'a' } }
57444                */
57445
57446
57447               function updateWith(object, path, updater, customizer) {
57448                 customizer = typeof customizer == 'function' ? customizer : undefined$1;
57449                 return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
57450               }
57451               /**
57452                * Creates an array of the own enumerable string keyed property values of `object`.
57453                *
57454                * **Note:** Non-object values are coerced to objects.
57455                *
57456                * @static
57457                * @since 0.1.0
57458                * @memberOf _
57459                * @category Object
57460                * @param {Object} object The object to query.
57461                * @returns {Array} Returns the array of property values.
57462                * @example
57463                *
57464                * function Foo() {
57465                *   this.a = 1;
57466                *   this.b = 2;
57467                * }
57468                *
57469                * Foo.prototype.c = 3;
57470                *
57471                * _.values(new Foo);
57472                * // => [1, 2] (iteration order is not guaranteed)
57473                *
57474                * _.values('hi');
57475                * // => ['h', 'i']
57476                */
57477
57478
57479               function values(object) {
57480                 return object == null ? [] : baseValues(object, keys(object));
57481               }
57482               /**
57483                * Creates an array of the own and inherited enumerable string keyed property
57484                * values of `object`.
57485                *
57486                * **Note:** Non-object values are coerced to objects.
57487                *
57488                * @static
57489                * @memberOf _
57490                * @since 3.0.0
57491                * @category Object
57492                * @param {Object} object The object to query.
57493                * @returns {Array} Returns the array of property values.
57494                * @example
57495                *
57496                * function Foo() {
57497                *   this.a = 1;
57498                *   this.b = 2;
57499                * }
57500                *
57501                * Foo.prototype.c = 3;
57502                *
57503                * _.valuesIn(new Foo);
57504                * // => [1, 2, 3] (iteration order is not guaranteed)
57505                */
57506
57507
57508               function valuesIn(object) {
57509                 return object == null ? [] : baseValues(object, keysIn(object));
57510               }
57511               /*------------------------------------------------------------------------*/
57512
57513               /**
57514                * Clamps `number` within the inclusive `lower` and `upper` bounds.
57515                *
57516                * @static
57517                * @memberOf _
57518                * @since 4.0.0
57519                * @category Number
57520                * @param {number} number The number to clamp.
57521                * @param {number} [lower] The lower bound.
57522                * @param {number} upper The upper bound.
57523                * @returns {number} Returns the clamped number.
57524                * @example
57525                *
57526                * _.clamp(-10, -5, 5);
57527                * // => -5
57528                *
57529                * _.clamp(10, -5, 5);
57530                * // => 5
57531                */
57532
57533
57534               function clamp(number, lower, upper) {
57535                 if (upper === undefined$1) {
57536                   upper = lower;
57537                   lower = undefined$1;
57538                 }
57539
57540                 if (upper !== undefined$1) {
57541                   upper = toNumber(upper);
57542                   upper = upper === upper ? upper : 0;
57543                 }
57544
57545                 if (lower !== undefined$1) {
57546                   lower = toNumber(lower);
57547                   lower = lower === lower ? lower : 0;
57548                 }
57549
57550                 return baseClamp(toNumber(number), lower, upper);
57551               }
57552               /**
57553                * Checks if `n` is between `start` and up to, but not including, `end`. If
57554                * `end` is not specified, it's set to `start` with `start` then set to `0`.
57555                * If `start` is greater than `end` the params are swapped to support
57556                * negative ranges.
57557                *
57558                * @static
57559                * @memberOf _
57560                * @since 3.3.0
57561                * @category Number
57562                * @param {number} number The number to check.
57563                * @param {number} [start=0] The start of the range.
57564                * @param {number} end The end of the range.
57565                * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
57566                * @see _.range, _.rangeRight
57567                * @example
57568                *
57569                * _.inRange(3, 2, 4);
57570                * // => true
57571                *
57572                * _.inRange(4, 8);
57573                * // => true
57574                *
57575                * _.inRange(4, 2);
57576                * // => false
57577                *
57578                * _.inRange(2, 2);
57579                * // => false
57580                *
57581                * _.inRange(1.2, 2);
57582                * // => true
57583                *
57584                * _.inRange(5.2, 4);
57585                * // => false
57586                *
57587                * _.inRange(-3, -2, -6);
57588                * // => true
57589                */
57590
57591
57592               function inRange(number, start, end) {
57593                 start = toFinite(start);
57594
57595                 if (end === undefined$1) {
57596                   end = start;
57597                   start = 0;
57598                 } else {
57599                   end = toFinite(end);
57600                 }
57601
57602                 number = toNumber(number);
57603                 return baseInRange(number, start, end);
57604               }
57605               /**
57606                * Produces a random number between the inclusive `lower` and `upper` bounds.
57607                * If only one argument is provided a number between `0` and the given number
57608                * is returned. If `floating` is `true`, or either `lower` or `upper` are
57609                * floats, a floating-point number is returned instead of an integer.
57610                *
57611                * **Note:** JavaScript follows the IEEE-754 standard for resolving
57612                * floating-point values which can produce unexpected results.
57613                *
57614                * @static
57615                * @memberOf _
57616                * @since 0.7.0
57617                * @category Number
57618                * @param {number} [lower=0] The lower bound.
57619                * @param {number} [upper=1] The upper bound.
57620                * @param {boolean} [floating] Specify returning a floating-point number.
57621                * @returns {number} Returns the random number.
57622                * @example
57623                *
57624                * _.random(0, 5);
57625                * // => an integer between 0 and 5
57626                *
57627                * _.random(5);
57628                * // => also an integer between 0 and 5
57629                *
57630                * _.random(5, true);
57631                * // => a floating-point number between 0 and 5
57632                *
57633                * _.random(1.2, 5.2);
57634                * // => a floating-point number between 1.2 and 5.2
57635                */
57636
57637
57638               function random(lower, upper, floating) {
57639                 if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
57640                   upper = floating = undefined$1;
57641                 }
57642
57643                 if (floating === undefined$1) {
57644                   if (typeof upper == 'boolean') {
57645                     floating = upper;
57646                     upper = undefined$1;
57647                   } else if (typeof lower == 'boolean') {
57648                     floating = lower;
57649                     lower = undefined$1;
57650                   }
57651                 }
57652
57653                 if (lower === undefined$1 && upper === undefined$1) {
57654                   lower = 0;
57655                   upper = 1;
57656                 } else {
57657                   lower = toFinite(lower);
57658
57659                   if (upper === undefined$1) {
57660                     upper = lower;
57661                     lower = 0;
57662                   } else {
57663                     upper = toFinite(upper);
57664                   }
57665                 }
57666
57667                 if (lower > upper) {
57668                   var temp = lower;
57669                   lower = upper;
57670                   upper = temp;
57671                 }
57672
57673                 if (floating || lower % 1 || upper % 1) {
57674                   var rand = nativeRandom();
57675                   return nativeMin(lower + rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1))), upper);
57676                 }
57677
57678                 return baseRandom(lower, upper);
57679               }
57680               /*------------------------------------------------------------------------*/
57681
57682               /**
57683                * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
57684                *
57685                * @static
57686                * @memberOf _
57687                * @since 3.0.0
57688                * @category String
57689                * @param {string} [string=''] The string to convert.
57690                * @returns {string} Returns the camel cased string.
57691                * @example
57692                *
57693                * _.camelCase('Foo Bar');
57694                * // => 'fooBar'
57695                *
57696                * _.camelCase('--foo-bar--');
57697                * // => 'fooBar'
57698                *
57699                * _.camelCase('__FOO_BAR__');
57700                * // => 'fooBar'
57701                */
57702
57703
57704               var camelCase = createCompounder(function (result, word, index) {
57705                 word = word.toLowerCase();
57706                 return result + (index ? capitalize(word) : word);
57707               });
57708               /**
57709                * Converts the first character of `string` to upper case and the remaining
57710                * to lower case.
57711                *
57712                * @static
57713                * @memberOf _
57714                * @since 3.0.0
57715                * @category String
57716                * @param {string} [string=''] The string to capitalize.
57717                * @returns {string} Returns the capitalized string.
57718                * @example
57719                *
57720                * _.capitalize('FRED');
57721                * // => 'Fred'
57722                */
57723
57724               function capitalize(string) {
57725                 return upperFirst(toString(string).toLowerCase());
57726               }
57727               /**
57728                * Deburrs `string` by converting
57729                * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
57730                * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
57731                * letters to basic Latin letters and removing
57732                * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
57733                *
57734                * @static
57735                * @memberOf _
57736                * @since 3.0.0
57737                * @category String
57738                * @param {string} [string=''] The string to deburr.
57739                * @returns {string} Returns the deburred string.
57740                * @example
57741                *
57742                * _.deburr('déjà vu');
57743                * // => 'deja vu'
57744                */
57745
57746
57747               function deburr(string) {
57748                 string = toString(string);
57749                 return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
57750               }
57751               /**
57752                * Checks if `string` ends with the given target string.
57753                *
57754                * @static
57755                * @memberOf _
57756                * @since 3.0.0
57757                * @category String
57758                * @param {string} [string=''] The string to inspect.
57759                * @param {string} [target] The string to search for.
57760                * @param {number} [position=string.length] The position to search up to.
57761                * @returns {boolean} Returns `true` if `string` ends with `target`,
57762                *  else `false`.
57763                * @example
57764                *
57765                * _.endsWith('abc', 'c');
57766                * // => true
57767                *
57768                * _.endsWith('abc', 'b');
57769                * // => false
57770                *
57771                * _.endsWith('abc', 'b', 2);
57772                * // => true
57773                */
57774
57775
57776               function endsWith(string, target, position) {
57777                 string = toString(string);
57778                 target = baseToString(target);
57779                 var length = string.length;
57780                 position = position === undefined$1 ? length : baseClamp(toInteger(position), 0, length);
57781                 var end = position;
57782                 position -= target.length;
57783                 return position >= 0 && string.slice(position, end) == target;
57784               }
57785               /**
57786                * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
57787                * corresponding HTML entities.
57788                *
57789                * **Note:** No other characters are escaped. To escape additional
57790                * characters use a third-party library like [_he_](https://mths.be/he).
57791                *
57792                * Though the ">" character is escaped for symmetry, characters like
57793                * ">" and "/" don't need escaping in HTML and have no special meaning
57794                * unless they're part of a tag or unquoted attribute value. See
57795                * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
57796                * (under "semi-related fun fact") for more details.
57797                *
57798                * When working with HTML you should always
57799                * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
57800                * XSS vectors.
57801                *
57802                * @static
57803                * @since 0.1.0
57804                * @memberOf _
57805                * @category String
57806                * @param {string} [string=''] The string to escape.
57807                * @returns {string} Returns the escaped string.
57808                * @example
57809                *
57810                * _.escape('fred, barney, & pebbles');
57811                * // => 'fred, barney, &amp; pebbles'
57812                */
57813
57814
57815               function escape(string) {
57816                 string = toString(string);
57817                 return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string;
57818               }
57819               /**
57820                * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
57821                * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
57822                *
57823                * @static
57824                * @memberOf _
57825                * @since 3.0.0
57826                * @category String
57827                * @param {string} [string=''] The string to escape.
57828                * @returns {string} Returns the escaped string.
57829                * @example
57830                *
57831                * _.escapeRegExp('[lodash](https://lodash.com/)');
57832                * // => '\[lodash\]\(https://lodash\.com/\)'
57833                */
57834
57835
57836               function escapeRegExp(string) {
57837                 string = toString(string);
57838                 return string && reHasRegExpChar.test(string) ? string.replace(reRegExpChar, '\\$&') : string;
57839               }
57840               /**
57841                * Converts `string` to
57842                * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
57843                *
57844                * @static
57845                * @memberOf _
57846                * @since 3.0.0
57847                * @category String
57848                * @param {string} [string=''] The string to convert.
57849                * @returns {string} Returns the kebab cased string.
57850                * @example
57851                *
57852                * _.kebabCase('Foo Bar');
57853                * // => 'foo-bar'
57854                *
57855                * _.kebabCase('fooBar');
57856                * // => 'foo-bar'
57857                *
57858                * _.kebabCase('__FOO_BAR__');
57859                * // => 'foo-bar'
57860                */
57861
57862
57863               var kebabCase = createCompounder(function (result, word, index) {
57864                 return result + (index ? '-' : '') + word.toLowerCase();
57865               });
57866               /**
57867                * Converts `string`, as space separated words, to lower case.
57868                *
57869                * @static
57870                * @memberOf _
57871                * @since 4.0.0
57872                * @category String
57873                * @param {string} [string=''] The string to convert.
57874                * @returns {string} Returns the lower cased string.
57875                * @example
57876                *
57877                * _.lowerCase('--Foo-Bar--');
57878                * // => 'foo bar'
57879                *
57880                * _.lowerCase('fooBar');
57881                * // => 'foo bar'
57882                *
57883                * _.lowerCase('__FOO_BAR__');
57884                * // => 'foo bar'
57885                */
57886
57887               var lowerCase = createCompounder(function (result, word, index) {
57888                 return result + (index ? ' ' : '') + word.toLowerCase();
57889               });
57890               /**
57891                * Converts the first character of `string` to lower case.
57892                *
57893                * @static
57894                * @memberOf _
57895                * @since 4.0.0
57896                * @category String
57897                * @param {string} [string=''] The string to convert.
57898                * @returns {string} Returns the converted string.
57899                * @example
57900                *
57901                * _.lowerFirst('Fred');
57902                * // => 'fred'
57903                *
57904                * _.lowerFirst('FRED');
57905                * // => 'fRED'
57906                */
57907
57908               var lowerFirst = createCaseFirst('toLowerCase');
57909               /**
57910                * Pads `string` on the left and right sides if it's shorter than `length`.
57911                * Padding characters are truncated if they can't be evenly divided by `length`.
57912                *
57913                * @static
57914                * @memberOf _
57915                * @since 3.0.0
57916                * @category String
57917                * @param {string} [string=''] The string to pad.
57918                * @param {number} [length=0] The padding length.
57919                * @param {string} [chars=' '] The string used as padding.
57920                * @returns {string} Returns the padded string.
57921                * @example
57922                *
57923                * _.pad('abc', 8);
57924                * // => '  abc   '
57925                *
57926                * _.pad('abc', 8, '_-');
57927                * // => '_-abc_-_'
57928                *
57929                * _.pad('abc', 3);
57930                * // => 'abc'
57931                */
57932
57933               function pad(string, length, chars) {
57934                 string = toString(string);
57935                 length = toInteger(length);
57936                 var strLength = length ? stringSize(string) : 0;
57937
57938                 if (!length || strLength >= length) {
57939                   return string;
57940                 }
57941
57942                 var mid = (length - strLength) / 2;
57943                 return createPadding(nativeFloor(mid), chars) + string + createPadding(nativeCeil(mid), chars);
57944               }
57945               /**
57946                * Pads `string` on the right side if it's shorter than `length`. Padding
57947                * characters are truncated if they exceed `length`.
57948                *
57949                * @static
57950                * @memberOf _
57951                * @since 4.0.0
57952                * @category String
57953                * @param {string} [string=''] The string to pad.
57954                * @param {number} [length=0] The padding length.
57955                * @param {string} [chars=' '] The string used as padding.
57956                * @returns {string} Returns the padded string.
57957                * @example
57958                *
57959                * _.padEnd('abc', 6);
57960                * // => 'abc   '
57961                *
57962                * _.padEnd('abc', 6, '_-');
57963                * // => 'abc_-_'
57964                *
57965                * _.padEnd('abc', 3);
57966                * // => 'abc'
57967                */
57968
57969
57970               function padEnd(string, length, chars) {
57971                 string = toString(string);
57972                 length = toInteger(length);
57973                 var strLength = length ? stringSize(string) : 0;
57974                 return length && strLength < length ? string + createPadding(length - strLength, chars) : string;
57975               }
57976               /**
57977                * Pads `string` on the left side if it's shorter than `length`. Padding
57978                * characters are truncated if they exceed `length`.
57979                *
57980                * @static
57981                * @memberOf _
57982                * @since 4.0.0
57983                * @category String
57984                * @param {string} [string=''] The string to pad.
57985                * @param {number} [length=0] The padding length.
57986                * @param {string} [chars=' '] The string used as padding.
57987                * @returns {string} Returns the padded string.
57988                * @example
57989                *
57990                * _.padStart('abc', 6);
57991                * // => '   abc'
57992                *
57993                * _.padStart('abc', 6, '_-');
57994                * // => '_-_abc'
57995                *
57996                * _.padStart('abc', 3);
57997                * // => 'abc'
57998                */
57999
58000
58001               function padStart(string, length, chars) {
58002                 string = toString(string);
58003                 length = toInteger(length);
58004                 var strLength = length ? stringSize(string) : 0;
58005                 return length && strLength < length ? createPadding(length - strLength, chars) + string : string;
58006               }
58007               /**
58008                * Converts `string` to an integer of the specified radix. If `radix` is
58009                * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
58010                * hexadecimal, in which case a `radix` of `16` is used.
58011                *
58012                * **Note:** This method aligns with the
58013                * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
58014                *
58015                * @static
58016                * @memberOf _
58017                * @since 1.1.0
58018                * @category String
58019                * @param {string} string The string to convert.
58020                * @param {number} [radix=10] The radix to interpret `value` by.
58021                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58022                * @returns {number} Returns the converted integer.
58023                * @example
58024                *
58025                * _.parseInt('08');
58026                * // => 8
58027                *
58028                * _.map(['6', '08', '10'], _.parseInt);
58029                * // => [6, 8, 10]
58030                */
58031
58032
58033               function parseInt(string, radix, guard) {
58034                 if (guard || radix == null) {
58035                   radix = 0;
58036                 } else if (radix) {
58037                   radix = +radix;
58038                 }
58039
58040                 return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
58041               }
58042               /**
58043                * Repeats the given string `n` times.
58044                *
58045                * @static
58046                * @memberOf _
58047                * @since 3.0.0
58048                * @category String
58049                * @param {string} [string=''] The string to repeat.
58050                * @param {number} [n=1] The number of times to repeat the string.
58051                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58052                * @returns {string} Returns the repeated string.
58053                * @example
58054                *
58055                * _.repeat('*', 3);
58056                * // => '***'
58057                *
58058                * _.repeat('abc', 2);
58059                * // => 'abcabc'
58060                *
58061                * _.repeat('abc', 0);
58062                * // => ''
58063                */
58064
58065
58066               function repeat(string, n, guard) {
58067                 if (guard ? isIterateeCall(string, n, guard) : n === undefined$1) {
58068                   n = 1;
58069                 } else {
58070                   n = toInteger(n);
58071                 }
58072
58073                 return baseRepeat(toString(string), n);
58074               }
58075               /**
58076                * Replaces matches for `pattern` in `string` with `replacement`.
58077                *
58078                * **Note:** This method is based on
58079                * [`String#replace`](https://mdn.io/String/replace).
58080                *
58081                * @static
58082                * @memberOf _
58083                * @since 4.0.0
58084                * @category String
58085                * @param {string} [string=''] The string to modify.
58086                * @param {RegExp|string} pattern The pattern to replace.
58087                * @param {Function|string} replacement The match replacement.
58088                * @returns {string} Returns the modified string.
58089                * @example
58090                *
58091                * _.replace('Hi Fred', 'Fred', 'Barney');
58092                * // => 'Hi Barney'
58093                */
58094
58095
58096               function replace() {
58097                 var args = arguments,
58098                     string = toString(args[0]);
58099                 return args.length < 3 ? string : string.replace(args[1], args[2]);
58100               }
58101               /**
58102                * Converts `string` to
58103                * [snake case](https://en.wikipedia.org/wiki/Snake_case).
58104                *
58105                * @static
58106                * @memberOf _
58107                * @since 3.0.0
58108                * @category String
58109                * @param {string} [string=''] The string to convert.
58110                * @returns {string} Returns the snake cased string.
58111                * @example
58112                *
58113                * _.snakeCase('Foo Bar');
58114                * // => 'foo_bar'
58115                *
58116                * _.snakeCase('fooBar');
58117                * // => 'foo_bar'
58118                *
58119                * _.snakeCase('--FOO-BAR--');
58120                * // => 'foo_bar'
58121                */
58122
58123
58124               var snakeCase = createCompounder(function (result, word, index) {
58125                 return result + (index ? '_' : '') + word.toLowerCase();
58126               });
58127               /**
58128                * Splits `string` by `separator`.
58129                *
58130                * **Note:** This method is based on
58131                * [`String#split`](https://mdn.io/String/split).
58132                *
58133                * @static
58134                * @memberOf _
58135                * @since 4.0.0
58136                * @category String
58137                * @param {string} [string=''] The string to split.
58138                * @param {RegExp|string} separator The separator pattern to split by.
58139                * @param {number} [limit] The length to truncate results to.
58140                * @returns {Array} Returns the string segments.
58141                * @example
58142                *
58143                * _.split('a-b-c', '-', 2);
58144                * // => ['a', 'b']
58145                */
58146
58147               function split(string, separator, limit) {
58148                 if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
58149                   separator = limit = undefined$1;
58150                 }
58151
58152                 limit = limit === undefined$1 ? MAX_ARRAY_LENGTH : limit >>> 0;
58153
58154                 if (!limit) {
58155                   return [];
58156                 }
58157
58158                 string = toString(string);
58159
58160                 if (string && (typeof separator == 'string' || separator != null && !isRegExp(separator))) {
58161                   separator = baseToString(separator);
58162
58163                   if (!separator && hasUnicode(string)) {
58164                     return castSlice(stringToArray(string), 0, limit);
58165                   }
58166                 }
58167
58168                 return string.split(separator, limit);
58169               }
58170               /**
58171                * Converts `string` to
58172                * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
58173                *
58174                * @static
58175                * @memberOf _
58176                * @since 3.1.0
58177                * @category String
58178                * @param {string} [string=''] The string to convert.
58179                * @returns {string} Returns the start cased string.
58180                * @example
58181                *
58182                * _.startCase('--foo-bar--');
58183                * // => 'Foo Bar'
58184                *
58185                * _.startCase('fooBar');
58186                * // => 'Foo Bar'
58187                *
58188                * _.startCase('__FOO_BAR__');
58189                * // => 'FOO BAR'
58190                */
58191
58192
58193               var startCase = createCompounder(function (result, word, index) {
58194                 return result + (index ? ' ' : '') + upperFirst(word);
58195               });
58196               /**
58197                * Checks if `string` starts with the given target string.
58198                *
58199                * @static
58200                * @memberOf _
58201                * @since 3.0.0
58202                * @category String
58203                * @param {string} [string=''] The string to inspect.
58204                * @param {string} [target] The string to search for.
58205                * @param {number} [position=0] The position to search from.
58206                * @returns {boolean} Returns `true` if `string` starts with `target`,
58207                *  else `false`.
58208                * @example
58209                *
58210                * _.startsWith('abc', 'a');
58211                * // => true
58212                *
58213                * _.startsWith('abc', 'b');
58214                * // => false
58215                *
58216                * _.startsWith('abc', 'b', 1);
58217                * // => true
58218                */
58219
58220               function startsWith(string, target, position) {
58221                 string = toString(string);
58222                 position = position == null ? 0 : baseClamp(toInteger(position), 0, string.length);
58223                 target = baseToString(target);
58224                 return string.slice(position, position + target.length) == target;
58225               }
58226               /**
58227                * Creates a compiled template function that can interpolate data properties
58228                * in "interpolate" delimiters, HTML-escape interpolated data properties in
58229                * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
58230                * properties may be accessed as free variables in the template. If a setting
58231                * object is given, it takes precedence over `_.templateSettings` values.
58232                *
58233                * **Note:** In the development build `_.template` utilizes
58234                * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
58235                * for easier debugging.
58236                *
58237                * For more information on precompiling templates see
58238                * [lodash's custom builds documentation](https://lodash.com/custom-builds).
58239                *
58240                * For more information on Chrome extension sandboxes see
58241                * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
58242                *
58243                * @static
58244                * @since 0.1.0
58245                * @memberOf _
58246                * @category String
58247                * @param {string} [string=''] The template string.
58248                * @param {Object} [options={}] The options object.
58249                * @param {RegExp} [options.escape=_.templateSettings.escape]
58250                *  The HTML "escape" delimiter.
58251                * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
58252                *  The "evaluate" delimiter.
58253                * @param {Object} [options.imports=_.templateSettings.imports]
58254                *  An object to import into the template as free variables.
58255                * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
58256                *  The "interpolate" delimiter.
58257                * @param {string} [options.sourceURL='lodash.templateSources[n]']
58258                *  The sourceURL of the compiled template.
58259                * @param {string} [options.variable='obj']
58260                *  The data object variable name.
58261                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58262                * @returns {Function} Returns the compiled template function.
58263                * @example
58264                *
58265                * // Use the "interpolate" delimiter to create a compiled template.
58266                * var compiled = _.template('hello <%= user %>!');
58267                * compiled({ 'user': 'fred' });
58268                * // => 'hello fred!'
58269                *
58270                * // Use the HTML "escape" delimiter to escape data property values.
58271                * var compiled = _.template('<b><%- value %></b>');
58272                * compiled({ 'value': '<script>' });
58273                * // => '<b>&lt;script&gt;</b>'
58274                *
58275                * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
58276                * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
58277                * compiled({ 'users': ['fred', 'barney'] });
58278                * // => '<li>fred</li><li>barney</li>'
58279                *
58280                * // Use the internal `print` function in "evaluate" delimiters.
58281                * var compiled = _.template('<% print("hello " + user); %>!');
58282                * compiled({ 'user': 'barney' });
58283                * // => 'hello barney!'
58284                *
58285                * // Use the ES template literal delimiter as an "interpolate" delimiter.
58286                * // Disable support by replacing the "interpolate" delimiter.
58287                * var compiled = _.template('hello ${ user }!');
58288                * compiled({ 'user': 'pebbles' });
58289                * // => 'hello pebbles!'
58290                *
58291                * // Use backslashes to treat delimiters as plain text.
58292                * var compiled = _.template('<%= "\\<%- value %\\>" %>');
58293                * compiled({ 'value': 'ignored' });
58294                * // => '<%- value %>'
58295                *
58296                * // Use the `imports` option to import `jQuery` as `jq`.
58297                * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
58298                * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
58299                * compiled({ 'users': ['fred', 'barney'] });
58300                * // => '<li>fred</li><li>barney</li>'
58301                *
58302                * // Use the `sourceURL` option to specify a custom sourceURL for the template.
58303                * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
58304                * compiled(data);
58305                * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
58306                *
58307                * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
58308                * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
58309                * compiled.source;
58310                * // => function(data) {
58311                * //   var __t, __p = '';
58312                * //   __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
58313                * //   return __p;
58314                * // }
58315                *
58316                * // Use custom template delimiters.
58317                * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
58318                * var compiled = _.template('hello {{ user }}!');
58319                * compiled({ 'user': 'mustache' });
58320                * // => 'hello mustache!'
58321                *
58322                * // Use the `source` property to inline compiled templates for meaningful
58323                * // line numbers in error messages and stack traces.
58324                * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
58325                *   var JST = {\
58326                *     "main": ' + _.template(mainText).source + '\
58327                *   };\
58328                * ');
58329                */
58330
58331
58332               function template(string, options, guard) {
58333                 // Based on John Resig's `tmpl` implementation
58334                 // (http://ejohn.org/blog/javascript-micro-templating/)
58335                 // and Laura Doktorova's doT.js (https://github.com/olado/doT).
58336                 var settings = lodash.templateSettings;
58337
58338                 if (guard && isIterateeCall(string, options, guard)) {
58339                   options = undefined$1;
58340                 }
58341
58342                 string = toString(string);
58343                 options = assignInWith({}, options, settings, customDefaultsAssignIn);
58344                 var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn),
58345                     importsKeys = keys(imports),
58346                     importsValues = baseValues(imports, importsKeys);
58347                 var isEscaping,
58348                     isEvaluating,
58349                     index = 0,
58350                     interpolate = options.interpolate || reNoMatch,
58351                     source = "__p += '"; // Compile the regexp to match each delimiter.
58352
58353                 var reDelimiters = RegExp((options.escape || reNoMatch).source + '|' + interpolate.source + '|' + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' + (options.evaluate || reNoMatch).source + '|$', 'g'); // Use a sourceURL for easier debugging.
58354                 // The sourceURL gets injected into the source that's eval-ed, so be careful
58355                 // to normalize all kinds of whitespace, so e.g. newlines (and unicode versions of it) can't sneak in
58356                 // and escape the comment, thus injecting code that gets evaled.
58357
58358                 var sourceURL = '//# sourceURL=' + (hasOwnProperty.call(options, 'sourceURL') ? (options.sourceURL + '').replace(/\s/g, ' ') : 'lodash.templateSources[' + ++templateCounter + ']') + '\n';
58359                 string.replace(reDelimiters, function (match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
58360                   interpolateValue || (interpolateValue = esTemplateValue); // Escape characters that can't be included in string literals.
58361
58362                   source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar); // Replace delimiters with snippets.
58363
58364                   if (escapeValue) {
58365                     isEscaping = true;
58366                     source += "' +\n__e(" + escapeValue + ") +\n'";
58367                   }
58368
58369                   if (evaluateValue) {
58370                     isEvaluating = true;
58371                     source += "';\n" + evaluateValue + ";\n__p += '";
58372                   }
58373
58374                   if (interpolateValue) {
58375                     source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
58376                   }
58377
58378                   index = offset + match.length; // The JS engine embedded in Adobe products needs `match` returned in
58379                   // order to produce the correct `offset` value.
58380
58381                   return match;
58382                 });
58383                 source += "';\n"; // If `variable` is not specified wrap a with-statement around the generated
58384                 // code to add the data object to the top of the scope chain.
58385
58386                 var variable = hasOwnProperty.call(options, 'variable') && options.variable;
58387
58388                 if (!variable) {
58389                   source = 'with (obj) {\n' + source + '\n}\n';
58390                 } // Throw an error if a forbidden character was found in `variable`, to prevent
58391                 // potential command injection attacks.
58392                 else if (reForbiddenIdentifierChars.test(variable)) {
58393                   throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
58394                 } // Cleanup code by stripping empty strings.
58395
58396
58397                 source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source).replace(reEmptyStringMiddle, '$1').replace(reEmptyStringTrailing, '$1;'); // Frame code as the function body.
58398
58399                 source = 'function(' + (variable || 'obj') + ') {\n' + (variable ? '' : 'obj || (obj = {});\n') + "var __t, __p = ''" + (isEscaping ? ', __e = _.escape' : '') + (isEvaluating ? ', __j = Array.prototype.join;\n' + "function print() { __p += __j.call(arguments, '') }\n" : ';\n') + source + 'return __p\n}';
58400                 var result = attempt(function () {
58401                   return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined$1, importsValues);
58402                 }); // Provide the compiled function's source by its `toString` method or
58403                 // the `source` property as a convenience for inlining compiled templates.
58404
58405                 result.source = source;
58406
58407                 if (isError(result)) {
58408                   throw result;
58409                 }
58410
58411                 return result;
58412               }
58413               /**
58414                * Converts `string`, as a whole, to lower case just like
58415                * [String#toLowerCase](https://mdn.io/toLowerCase).
58416                *
58417                * @static
58418                * @memberOf _
58419                * @since 4.0.0
58420                * @category String
58421                * @param {string} [string=''] The string to convert.
58422                * @returns {string} Returns the lower cased string.
58423                * @example
58424                *
58425                * _.toLower('--Foo-Bar--');
58426                * // => '--foo-bar--'
58427                *
58428                * _.toLower('fooBar');
58429                * // => 'foobar'
58430                *
58431                * _.toLower('__FOO_BAR__');
58432                * // => '__foo_bar__'
58433                */
58434
58435
58436               function toLower(value) {
58437                 return toString(value).toLowerCase();
58438               }
58439               /**
58440                * Converts `string`, as a whole, to upper case just like
58441                * [String#toUpperCase](https://mdn.io/toUpperCase).
58442                *
58443                * @static
58444                * @memberOf _
58445                * @since 4.0.0
58446                * @category String
58447                * @param {string} [string=''] The string to convert.
58448                * @returns {string} Returns the upper cased string.
58449                * @example
58450                *
58451                * _.toUpper('--foo-bar--');
58452                * // => '--FOO-BAR--'
58453                *
58454                * _.toUpper('fooBar');
58455                * // => 'FOOBAR'
58456                *
58457                * _.toUpper('__foo_bar__');
58458                * // => '__FOO_BAR__'
58459                */
58460
58461
58462               function toUpper(value) {
58463                 return toString(value).toUpperCase();
58464               }
58465               /**
58466                * Removes leading and trailing whitespace or specified characters from `string`.
58467                *
58468                * @static
58469                * @memberOf _
58470                * @since 3.0.0
58471                * @category String
58472                * @param {string} [string=''] The string to trim.
58473                * @param {string} [chars=whitespace] The characters to trim.
58474                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58475                * @returns {string} Returns the trimmed string.
58476                * @example
58477                *
58478                * _.trim('  abc  ');
58479                * // => 'abc'
58480                *
58481                * _.trim('-_-abc-_-', '_-');
58482                * // => 'abc'
58483                *
58484                * _.map(['  foo  ', '  bar  '], _.trim);
58485                * // => ['foo', 'bar']
58486                */
58487
58488
58489               function trim(string, chars, guard) {
58490                 string = toString(string);
58491
58492                 if (string && (guard || chars === undefined$1)) {
58493                   return baseTrim(string);
58494                 }
58495
58496                 if (!string || !(chars = baseToString(chars))) {
58497                   return string;
58498                 }
58499
58500                 var strSymbols = stringToArray(string),
58501                     chrSymbols = stringToArray(chars),
58502                     start = charsStartIndex(strSymbols, chrSymbols),
58503                     end = charsEndIndex(strSymbols, chrSymbols) + 1;
58504                 return castSlice(strSymbols, start, end).join('');
58505               }
58506               /**
58507                * Removes trailing whitespace or specified characters from `string`.
58508                *
58509                * @static
58510                * @memberOf _
58511                * @since 4.0.0
58512                * @category String
58513                * @param {string} [string=''] The string to trim.
58514                * @param {string} [chars=whitespace] The characters to trim.
58515                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58516                * @returns {string} Returns the trimmed string.
58517                * @example
58518                *
58519                * _.trimEnd('  abc  ');
58520                * // => '  abc'
58521                *
58522                * _.trimEnd('-_-abc-_-', '_-');
58523                * // => '-_-abc'
58524                */
58525
58526
58527               function trimEnd(string, chars, guard) {
58528                 string = toString(string);
58529
58530                 if (string && (guard || chars === undefined$1)) {
58531                   return string.slice(0, trimmedEndIndex(string) + 1);
58532                 }
58533
58534                 if (!string || !(chars = baseToString(chars))) {
58535                   return string;
58536                 }
58537
58538                 var strSymbols = stringToArray(string),
58539                     end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
58540                 return castSlice(strSymbols, 0, end).join('');
58541               }
58542               /**
58543                * Removes leading whitespace or specified characters from `string`.
58544                *
58545                * @static
58546                * @memberOf _
58547                * @since 4.0.0
58548                * @category String
58549                * @param {string} [string=''] The string to trim.
58550                * @param {string} [chars=whitespace] The characters to trim.
58551                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58552                * @returns {string} Returns the trimmed string.
58553                * @example
58554                *
58555                * _.trimStart('  abc  ');
58556                * // => 'abc  '
58557                *
58558                * _.trimStart('-_-abc-_-', '_-');
58559                * // => 'abc-_-'
58560                */
58561
58562
58563               function trimStart(string, chars, guard) {
58564                 string = toString(string);
58565
58566                 if (string && (guard || chars === undefined$1)) {
58567                   return string.replace(reTrimStart, '');
58568                 }
58569
58570                 if (!string || !(chars = baseToString(chars))) {
58571                   return string;
58572                 }
58573
58574                 var strSymbols = stringToArray(string),
58575                     start = charsStartIndex(strSymbols, stringToArray(chars));
58576                 return castSlice(strSymbols, start).join('');
58577               }
58578               /**
58579                * Truncates `string` if it's longer than the given maximum string length.
58580                * The last characters of the truncated string are replaced with the omission
58581                * string which defaults to "...".
58582                *
58583                * @static
58584                * @memberOf _
58585                * @since 4.0.0
58586                * @category String
58587                * @param {string} [string=''] The string to truncate.
58588                * @param {Object} [options={}] The options object.
58589                * @param {number} [options.length=30] The maximum string length.
58590                * @param {string} [options.omission='...'] The string to indicate text is omitted.
58591                * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
58592                * @returns {string} Returns the truncated string.
58593                * @example
58594                *
58595                * _.truncate('hi-diddly-ho there, neighborino');
58596                * // => 'hi-diddly-ho there, neighbo...'
58597                *
58598                * _.truncate('hi-diddly-ho there, neighborino', {
58599                *   'length': 24,
58600                *   'separator': ' '
58601                * });
58602                * // => 'hi-diddly-ho there,...'
58603                *
58604                * _.truncate('hi-diddly-ho there, neighborino', {
58605                *   'length': 24,
58606                *   'separator': /,? +/
58607                * });
58608                * // => 'hi-diddly-ho there...'
58609                *
58610                * _.truncate('hi-diddly-ho there, neighborino', {
58611                *   'omission': ' [...]'
58612                * });
58613                * // => 'hi-diddly-ho there, neig [...]'
58614                */
58615
58616
58617               function truncate(string, options) {
58618                 var length = DEFAULT_TRUNC_LENGTH,
58619                     omission = DEFAULT_TRUNC_OMISSION;
58620
58621                 if (isObject(options)) {
58622                   var separator = 'separator' in options ? options.separator : separator;
58623                   length = 'length' in options ? toInteger(options.length) : length;
58624                   omission = 'omission' in options ? baseToString(options.omission) : omission;
58625                 }
58626
58627                 string = toString(string);
58628                 var strLength = string.length;
58629
58630                 if (hasUnicode(string)) {
58631                   var strSymbols = stringToArray(string);
58632                   strLength = strSymbols.length;
58633                 }
58634
58635                 if (length >= strLength) {
58636                   return string;
58637                 }
58638
58639                 var end = length - stringSize(omission);
58640
58641                 if (end < 1) {
58642                   return omission;
58643                 }
58644
58645                 var result = strSymbols ? castSlice(strSymbols, 0, end).join('') : string.slice(0, end);
58646
58647                 if (separator === undefined$1) {
58648                   return result + omission;
58649                 }
58650
58651                 if (strSymbols) {
58652                   end += result.length - end;
58653                 }
58654
58655                 if (isRegExp(separator)) {
58656                   if (string.slice(end).search(separator)) {
58657                     var match,
58658                         substring = result;
58659
58660                     if (!separator.global) {
58661                       separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
58662                     }
58663
58664                     separator.lastIndex = 0;
58665
58666                     while (match = separator.exec(substring)) {
58667                       var newEnd = match.index;
58668                     }
58669
58670                     result = result.slice(0, newEnd === undefined$1 ? end : newEnd);
58671                   }
58672                 } else if (string.indexOf(baseToString(separator), end) != end) {
58673                   var index = result.lastIndexOf(separator);
58674
58675                   if (index > -1) {
58676                     result = result.slice(0, index);
58677                   }
58678                 }
58679
58680                 return result + omission;
58681               }
58682               /**
58683                * The inverse of `_.escape`; this method converts the HTML entities
58684                * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to
58685                * their corresponding characters.
58686                *
58687                * **Note:** No other HTML entities are unescaped. To unescape additional
58688                * HTML entities use a third-party library like [_he_](https://mths.be/he).
58689                *
58690                * @static
58691                * @memberOf _
58692                * @since 0.6.0
58693                * @category String
58694                * @param {string} [string=''] The string to unescape.
58695                * @returns {string} Returns the unescaped string.
58696                * @example
58697                *
58698                * _.unescape('fred, barney, &amp; pebbles');
58699                * // => 'fred, barney, & pebbles'
58700                */
58701
58702
58703               function unescape(string) {
58704                 string = toString(string);
58705                 return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string;
58706               }
58707               /**
58708                * Converts `string`, as space separated words, to upper case.
58709                *
58710                * @static
58711                * @memberOf _
58712                * @since 4.0.0
58713                * @category String
58714                * @param {string} [string=''] The string to convert.
58715                * @returns {string} Returns the upper cased string.
58716                * @example
58717                *
58718                * _.upperCase('--foo-bar');
58719                * // => 'FOO BAR'
58720                *
58721                * _.upperCase('fooBar');
58722                * // => 'FOO BAR'
58723                *
58724                * _.upperCase('__foo_bar__');
58725                * // => 'FOO BAR'
58726                */
58727
58728
58729               var upperCase = createCompounder(function (result, word, index) {
58730                 return result + (index ? ' ' : '') + word.toUpperCase();
58731               });
58732               /**
58733                * Converts the first character of `string` to upper case.
58734                *
58735                * @static
58736                * @memberOf _
58737                * @since 4.0.0
58738                * @category String
58739                * @param {string} [string=''] The string to convert.
58740                * @returns {string} Returns the converted string.
58741                * @example
58742                *
58743                * _.upperFirst('fred');
58744                * // => 'Fred'
58745                *
58746                * _.upperFirst('FRED');
58747                * // => 'FRED'
58748                */
58749
58750               var upperFirst = createCaseFirst('toUpperCase');
58751               /**
58752                * Splits `string` into an array of its words.
58753                *
58754                * @static
58755                * @memberOf _
58756                * @since 3.0.0
58757                * @category String
58758                * @param {string} [string=''] The string to inspect.
58759                * @param {RegExp|string} [pattern] The pattern to match words.
58760                * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
58761                * @returns {Array} Returns the words of `string`.
58762                * @example
58763                *
58764                * _.words('fred, barney, & pebbles');
58765                * // => ['fred', 'barney', 'pebbles']
58766                *
58767                * _.words('fred, barney, & pebbles', /[^, ]+/g);
58768                * // => ['fred', 'barney', '&', 'pebbles']
58769                */
58770
58771               function words(string, pattern, guard) {
58772                 string = toString(string);
58773                 pattern = guard ? undefined$1 : pattern;
58774
58775                 if (pattern === undefined$1) {
58776                   return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
58777                 }
58778
58779                 return string.match(pattern) || [];
58780               }
58781               /*------------------------------------------------------------------------*/
58782
58783               /**
58784                * Attempts to invoke `func`, returning either the result or the caught error
58785                * object. Any additional arguments are provided to `func` when it's invoked.
58786                *
58787                * @static
58788                * @memberOf _
58789                * @since 3.0.0
58790                * @category Util
58791                * @param {Function} func The function to attempt.
58792                * @param {...*} [args] The arguments to invoke `func` with.
58793                * @returns {*} Returns the `func` result or error object.
58794                * @example
58795                *
58796                * // Avoid throwing errors for invalid selectors.
58797                * var elements = _.attempt(function(selector) {
58798                *   return document.querySelectorAll(selector);
58799                * }, '>_>');
58800                *
58801                * if (_.isError(elements)) {
58802                *   elements = [];
58803                * }
58804                */
58805
58806
58807               var attempt = baseRest(function (func, args) {
58808                 try {
58809                   return apply(func, undefined$1, args);
58810                 } catch (e) {
58811                   return isError(e) ? e : new Error(e);
58812                 }
58813               });
58814               /**
58815                * Binds methods of an object to the object itself, overwriting the existing
58816                * method.
58817                *
58818                * **Note:** This method doesn't set the "length" property of bound functions.
58819                *
58820                * @static
58821                * @since 0.1.0
58822                * @memberOf _
58823                * @category Util
58824                * @param {Object} object The object to bind and assign the bound methods to.
58825                * @param {...(string|string[])} methodNames The object method names to bind.
58826                * @returns {Object} Returns `object`.
58827                * @example
58828                *
58829                * var view = {
58830                *   'label': 'docs',
58831                *   'click': function() {
58832                *     console.log('clicked ' + this.label);
58833                *   }
58834                * };
58835                *
58836                * _.bindAll(view, ['click']);
58837                * jQuery(element).on('click', view.click);
58838                * // => Logs 'clicked docs' when clicked.
58839                */
58840
58841               var bindAll = flatRest(function (object, methodNames) {
58842                 arrayEach(methodNames, function (key) {
58843                   key = toKey(key);
58844                   baseAssignValue(object, key, bind(object[key], object));
58845                 });
58846                 return object;
58847               });
58848               /**
58849                * Creates a function that iterates over `pairs` and invokes the corresponding
58850                * function of the first predicate to return truthy. The predicate-function
58851                * pairs are invoked with the `this` binding and arguments of the created
58852                * function.
58853                *
58854                * @static
58855                * @memberOf _
58856                * @since 4.0.0
58857                * @category Util
58858                * @param {Array} pairs The predicate-function pairs.
58859                * @returns {Function} Returns the new composite function.
58860                * @example
58861                *
58862                * var func = _.cond([
58863                *   [_.matches({ 'a': 1 }),           _.constant('matches A')],
58864                *   [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
58865                *   [_.stubTrue,                      _.constant('no match')]
58866                * ]);
58867                *
58868                * func({ 'a': 1, 'b': 2 });
58869                * // => 'matches A'
58870                *
58871                * func({ 'a': 0, 'b': 1 });
58872                * // => 'matches B'
58873                *
58874                * func({ 'a': '1', 'b': '2' });
58875                * // => 'no match'
58876                */
58877
58878               function cond(pairs) {
58879                 var length = pairs == null ? 0 : pairs.length,
58880                     toIteratee = getIteratee();
58881                 pairs = !length ? [] : arrayMap(pairs, function (pair) {
58882                   if (typeof pair[1] != 'function') {
58883                     throw new TypeError(FUNC_ERROR_TEXT);
58884                   }
58885
58886                   return [toIteratee(pair[0]), pair[1]];
58887                 });
58888                 return baseRest(function (args) {
58889                   var index = -1;
58890
58891                   while (++index < length) {
58892                     var pair = pairs[index];
58893
58894                     if (apply(pair[0], this, args)) {
58895                       return apply(pair[1], this, args);
58896                     }
58897                   }
58898                 });
58899               }
58900               /**
58901                * Creates a function that invokes the predicate properties of `source` with
58902                * the corresponding property values of a given object, returning `true` if
58903                * all predicates return truthy, else `false`.
58904                *
58905                * **Note:** The created function is equivalent to `_.conformsTo` with
58906                * `source` partially applied.
58907                *
58908                * @static
58909                * @memberOf _
58910                * @since 4.0.0
58911                * @category Util
58912                * @param {Object} source The object of property predicates to conform to.
58913                * @returns {Function} Returns the new spec function.
58914                * @example
58915                *
58916                * var objects = [
58917                *   { 'a': 2, 'b': 1 },
58918                *   { 'a': 1, 'b': 2 }
58919                * ];
58920                *
58921                * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
58922                * // => [{ 'a': 1, 'b': 2 }]
58923                */
58924
58925
58926               function conforms(source) {
58927                 return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
58928               }
58929               /**
58930                * Creates a function that returns `value`.
58931                *
58932                * @static
58933                * @memberOf _
58934                * @since 2.4.0
58935                * @category Util
58936                * @param {*} value The value to return from the new function.
58937                * @returns {Function} Returns the new constant function.
58938                * @example
58939                *
58940                * var objects = _.times(2, _.constant({ 'a': 1 }));
58941                *
58942                * console.log(objects);
58943                * // => [{ 'a': 1 }, { 'a': 1 }]
58944                *
58945                * console.log(objects[0] === objects[1]);
58946                * // => true
58947                */
58948
58949
58950               function constant(value) {
58951                 return function () {
58952                   return value;
58953                 };
58954               }
58955               /**
58956                * Checks `value` to determine whether a default value should be returned in
58957                * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
58958                * or `undefined`.
58959                *
58960                * @static
58961                * @memberOf _
58962                * @since 4.14.0
58963                * @category Util
58964                * @param {*} value The value to check.
58965                * @param {*} defaultValue The default value.
58966                * @returns {*} Returns the resolved value.
58967                * @example
58968                *
58969                * _.defaultTo(1, 10);
58970                * // => 1
58971                *
58972                * _.defaultTo(undefined, 10);
58973                * // => 10
58974                */
58975
58976
58977               function defaultTo(value, defaultValue) {
58978                 return value == null || value !== value ? defaultValue : value;
58979               }
58980               /**
58981                * Creates a function that returns the result of invoking the given functions
58982                * with the `this` binding of the created function, where each successive
58983                * invocation is supplied the return value of the previous.
58984                *
58985                * @static
58986                * @memberOf _
58987                * @since 3.0.0
58988                * @category Util
58989                * @param {...(Function|Function[])} [funcs] The functions to invoke.
58990                * @returns {Function} Returns the new composite function.
58991                * @see _.flowRight
58992                * @example
58993                *
58994                * function square(n) {
58995                *   return n * n;
58996                * }
58997                *
58998                * var addSquare = _.flow([_.add, square]);
58999                * addSquare(1, 2);
59000                * // => 9
59001                */
59002
59003
59004               var flow = createFlow();
59005               /**
59006                * This method is like `_.flow` except that it creates a function that
59007                * invokes the given functions from right to left.
59008                *
59009                * @static
59010                * @since 3.0.0
59011                * @memberOf _
59012                * @category Util
59013                * @param {...(Function|Function[])} [funcs] The functions to invoke.
59014                * @returns {Function} Returns the new composite function.
59015                * @see _.flow
59016                * @example
59017                *
59018                * function square(n) {
59019                *   return n * n;
59020                * }
59021                *
59022                * var addSquare = _.flowRight([square, _.add]);
59023                * addSquare(1, 2);
59024                * // => 9
59025                */
59026
59027               var flowRight = createFlow(true);
59028               /**
59029                * This method returns the first argument it receives.
59030                *
59031                * @static
59032                * @since 0.1.0
59033                * @memberOf _
59034                * @category Util
59035                * @param {*} value Any value.
59036                * @returns {*} Returns `value`.
59037                * @example
59038                *
59039                * var object = { 'a': 1 };
59040                *
59041                * console.log(_.identity(object) === object);
59042                * // => true
59043                */
59044
59045               function identity(value) {
59046                 return value;
59047               }
59048               /**
59049                * Creates a function that invokes `func` with the arguments of the created
59050                * function. If `func` is a property name, the created function returns the
59051                * property value for a given element. If `func` is an array or object, the
59052                * created function returns `true` for elements that contain the equivalent
59053                * source properties, otherwise it returns `false`.
59054                *
59055                * @static
59056                * @since 4.0.0
59057                * @memberOf _
59058                * @category Util
59059                * @param {*} [func=_.identity] The value to convert to a callback.
59060                * @returns {Function} Returns the callback.
59061                * @example
59062                *
59063                * var users = [
59064                *   { 'user': 'barney', 'age': 36, 'active': true },
59065                *   { 'user': 'fred',   'age': 40, 'active': false }
59066                * ];
59067                *
59068                * // The `_.matches` iteratee shorthand.
59069                * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
59070                * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
59071                *
59072                * // The `_.matchesProperty` iteratee shorthand.
59073                * _.filter(users, _.iteratee(['user', 'fred']));
59074                * // => [{ 'user': 'fred', 'age': 40 }]
59075                *
59076                * // The `_.property` iteratee shorthand.
59077                * _.map(users, _.iteratee('user'));
59078                * // => ['barney', 'fred']
59079                *
59080                * // Create custom iteratee shorthands.
59081                * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
59082                *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
59083                *     return func.test(string);
59084                *   };
59085                * });
59086                *
59087                * _.filter(['abc', 'def'], /ef/);
59088                * // => ['def']
59089                */
59090
59091
59092               function iteratee(func) {
59093                 return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
59094               }
59095               /**
59096                * Creates a function that performs a partial deep comparison between a given
59097                * object and `source`, returning `true` if the given object has equivalent
59098                * property values, else `false`.
59099                *
59100                * **Note:** The created function is equivalent to `_.isMatch` with `source`
59101                * partially applied.
59102                *
59103                * Partial comparisons will match empty array and empty object `source`
59104                * values against any array or object value, respectively. See `_.isEqual`
59105                * for a list of supported value comparisons.
59106                *
59107                * **Note:** Multiple values can be checked by combining several matchers
59108                * using `_.overSome`
59109                *
59110                * @static
59111                * @memberOf _
59112                * @since 3.0.0
59113                * @category Util
59114                * @param {Object} source The object of property values to match.
59115                * @returns {Function} Returns the new spec function.
59116                * @example
59117                *
59118                * var objects = [
59119                *   { 'a': 1, 'b': 2, 'c': 3 },
59120                *   { 'a': 4, 'b': 5, 'c': 6 }
59121                * ];
59122                *
59123                * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
59124                * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
59125                *
59126                * // Checking for several possible values
59127                * _.filter(objects, _.overSome([_.matches({ 'a': 1 }), _.matches({ 'a': 4 })]));
59128                * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
59129                */
59130
59131
59132               function matches(source) {
59133                 return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
59134               }
59135               /**
59136                * Creates a function that performs a partial deep comparison between the
59137                * value at `path` of a given object to `srcValue`, returning `true` if the
59138                * object value is equivalent, else `false`.
59139                *
59140                * **Note:** Partial comparisons will match empty array and empty object
59141                * `srcValue` values against any array or object value, respectively. See
59142                * `_.isEqual` for a list of supported value comparisons.
59143                *
59144                * **Note:** Multiple values can be checked by combining several matchers
59145                * using `_.overSome`
59146                *
59147                * @static
59148                * @memberOf _
59149                * @since 3.2.0
59150                * @category Util
59151                * @param {Array|string} path The path of the property to get.
59152                * @param {*} srcValue The value to match.
59153                * @returns {Function} Returns the new spec function.
59154                * @example
59155                *
59156                * var objects = [
59157                *   { 'a': 1, 'b': 2, 'c': 3 },
59158                *   { 'a': 4, 'b': 5, 'c': 6 }
59159                * ];
59160                *
59161                * _.find(objects, _.matchesProperty('a', 4));
59162                * // => { 'a': 4, 'b': 5, 'c': 6 }
59163                *
59164                * // Checking for several possible values
59165                * _.filter(objects, _.overSome([_.matchesProperty('a', 1), _.matchesProperty('a', 4)]));
59166                * // => [{ 'a': 1, 'b': 2, 'c': 3 }, { 'a': 4, 'b': 5, 'c': 6 }]
59167                */
59168
59169
59170               function matchesProperty(path, srcValue) {
59171                 return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
59172               }
59173               /**
59174                * Creates a function that invokes the method at `path` of a given object.
59175                * Any additional arguments are provided to the invoked method.
59176                *
59177                * @static
59178                * @memberOf _
59179                * @since 3.7.0
59180                * @category Util
59181                * @param {Array|string} path The path of the method to invoke.
59182                * @param {...*} [args] The arguments to invoke the method with.
59183                * @returns {Function} Returns the new invoker function.
59184                * @example
59185                *
59186                * var objects = [
59187                *   { 'a': { 'b': _.constant(2) } },
59188                *   { 'a': { 'b': _.constant(1) } }
59189                * ];
59190                *
59191                * _.map(objects, _.method('a.b'));
59192                * // => [2, 1]
59193                *
59194                * _.map(objects, _.method(['a', 'b']));
59195                * // => [2, 1]
59196                */
59197
59198
59199               var method = baseRest(function (path, args) {
59200                 return function (object) {
59201                   return baseInvoke(object, path, args);
59202                 };
59203               });
59204               /**
59205                * The opposite of `_.method`; this method creates a function that invokes
59206                * the method at a given path of `object`. Any additional arguments are
59207                * provided to the invoked method.
59208                *
59209                * @static
59210                * @memberOf _
59211                * @since 3.7.0
59212                * @category Util
59213                * @param {Object} object The object to query.
59214                * @param {...*} [args] The arguments to invoke the method with.
59215                * @returns {Function} Returns the new invoker function.
59216                * @example
59217                *
59218                * var array = _.times(3, _.constant),
59219                *     object = { 'a': array, 'b': array, 'c': array };
59220                *
59221                * _.map(['a[2]', 'c[0]'], _.methodOf(object));
59222                * // => [2, 0]
59223                *
59224                * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
59225                * // => [2, 0]
59226                */
59227
59228               var methodOf = baseRest(function (object, args) {
59229                 return function (path) {
59230                   return baseInvoke(object, path, args);
59231                 };
59232               });
59233               /**
59234                * Adds all own enumerable string keyed function properties of a source
59235                * object to the destination object. If `object` is a function, then methods
59236                * are added to its prototype as well.
59237                *
59238                * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
59239                * avoid conflicts caused by modifying the original.
59240                *
59241                * @static
59242                * @since 0.1.0
59243                * @memberOf _
59244                * @category Util
59245                * @param {Function|Object} [object=lodash] The destination object.
59246                * @param {Object} source The object of functions to add.
59247                * @param {Object} [options={}] The options object.
59248                * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
59249                * @returns {Function|Object} Returns `object`.
59250                * @example
59251                *
59252                * function vowels(string) {
59253                *   return _.filter(string, function(v) {
59254                *     return /[aeiou]/i.test(v);
59255                *   });
59256                * }
59257                *
59258                * _.mixin({ 'vowels': vowels });
59259                * _.vowels('fred');
59260                * // => ['e']
59261                *
59262                * _('fred').vowels().value();
59263                * // => ['e']
59264                *
59265                * _.mixin({ 'vowels': vowels }, { 'chain': false });
59266                * _('fred').vowels();
59267                * // => ['e']
59268                */
59269
59270               function mixin(object, source, options) {
59271                 var props = keys(source),
59272                     methodNames = baseFunctions(source, props);
59273
59274                 if (options == null && !(isObject(source) && (methodNames.length || !props.length))) {
59275                   options = source;
59276                   source = object;
59277                   object = this;
59278                   methodNames = baseFunctions(source, keys(source));
59279                 }
59280
59281                 var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
59282                     isFunc = isFunction(object);
59283                 arrayEach(methodNames, function (methodName) {
59284                   var func = source[methodName];
59285                   object[methodName] = func;
59286
59287                   if (isFunc) {
59288                     object.prototype[methodName] = function () {
59289                       var chainAll = this.__chain__;
59290
59291                       if (chain || chainAll) {
59292                         var result = object(this.__wrapped__),
59293                             actions = result.__actions__ = copyArray(this.__actions__);
59294                         actions.push({
59295                           'func': func,
59296                           'args': arguments,
59297                           'thisArg': object
59298                         });
59299                         result.__chain__ = chainAll;
59300                         return result;
59301                       }
59302
59303                       return func.apply(object, arrayPush([this.value()], arguments));
59304                     };
59305                   }
59306                 });
59307                 return object;
59308               }
59309               /**
59310                * Reverts the `_` variable to its previous value and returns a reference to
59311                * the `lodash` function.
59312                *
59313                * @static
59314                * @since 0.1.0
59315                * @memberOf _
59316                * @category Util
59317                * @returns {Function} Returns the `lodash` function.
59318                * @example
59319                *
59320                * var lodash = _.noConflict();
59321                */
59322
59323
59324               function noConflict() {
59325                 if (root._ === this) {
59326                   root._ = oldDash;
59327                 }
59328
59329                 return this;
59330               }
59331               /**
59332                * This method returns `undefined`.
59333                *
59334                * @static
59335                * @memberOf _
59336                * @since 2.3.0
59337                * @category Util
59338                * @example
59339                *
59340                * _.times(2, _.noop);
59341                * // => [undefined, undefined]
59342                */
59343
59344
59345               function noop() {// No operation performed.
59346               }
59347               /**
59348                * Creates a function that gets the argument at index `n`. If `n` is negative,
59349                * the nth argument from the end is returned.
59350                *
59351                * @static
59352                * @memberOf _
59353                * @since 4.0.0
59354                * @category Util
59355                * @param {number} [n=0] The index of the argument to return.
59356                * @returns {Function} Returns the new pass-thru function.
59357                * @example
59358                *
59359                * var func = _.nthArg(1);
59360                * func('a', 'b', 'c', 'd');
59361                * // => 'b'
59362                *
59363                * var func = _.nthArg(-2);
59364                * func('a', 'b', 'c', 'd');
59365                * // => 'c'
59366                */
59367
59368
59369               function nthArg(n) {
59370                 n = toInteger(n);
59371                 return baseRest(function (args) {
59372                   return baseNth(args, n);
59373                 });
59374               }
59375               /**
59376                * Creates a function that invokes `iteratees` with the arguments it receives
59377                * and returns their results.
59378                *
59379                * @static
59380                * @memberOf _
59381                * @since 4.0.0
59382                * @category Util
59383                * @param {...(Function|Function[])} [iteratees=[_.identity]]
59384                *  The iteratees to invoke.
59385                * @returns {Function} Returns the new function.
59386                * @example
59387                *
59388                * var func = _.over([Math.max, Math.min]);
59389                *
59390                * func(1, 2, 3, 4);
59391                * // => [4, 1]
59392                */
59393
59394
59395               var over = createOver(arrayMap);
59396               /**
59397                * Creates a function that checks if **all** of the `predicates` return
59398                * truthy when invoked with the arguments it receives.
59399                *
59400                * Following shorthands are possible for providing predicates.
59401                * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
59402                * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
59403                *
59404                * @static
59405                * @memberOf _
59406                * @since 4.0.0
59407                * @category Util
59408                * @param {...(Function|Function[])} [predicates=[_.identity]]
59409                *  The predicates to check.
59410                * @returns {Function} Returns the new function.
59411                * @example
59412                *
59413                * var func = _.overEvery([Boolean, isFinite]);
59414                *
59415                * func('1');
59416                * // => true
59417                *
59418                * func(null);
59419                * // => false
59420                *
59421                * func(NaN);
59422                * // => false
59423                */
59424
59425               var overEvery = createOver(arrayEvery);
59426               /**
59427                * Creates a function that checks if **any** of the `predicates` return
59428                * truthy when invoked with the arguments it receives.
59429                *
59430                * Following shorthands are possible for providing predicates.
59431                * Pass an `Object` and it will be used as an parameter for `_.matches` to create the predicate.
59432                * Pass an `Array` of parameters for `_.matchesProperty` and the predicate will be created using them.
59433                *
59434                * @static
59435                * @memberOf _
59436                * @since 4.0.0
59437                * @category Util
59438                * @param {...(Function|Function[])} [predicates=[_.identity]]
59439                *  The predicates to check.
59440                * @returns {Function} Returns the new function.
59441                * @example
59442                *
59443                * var func = _.overSome([Boolean, isFinite]);
59444                *
59445                * func('1');
59446                * // => true
59447                *
59448                * func(null);
59449                * // => true
59450                *
59451                * func(NaN);
59452                * // => false
59453                *
59454                * var matchesFunc = _.overSome([{ 'a': 1 }, { 'a': 2 }])
59455                * var matchesPropertyFunc = _.overSome([['a', 1], ['a', 2]])
59456                */
59457
59458               var overSome = createOver(arraySome);
59459               /**
59460                * Creates a function that returns the value at `path` of a given object.
59461                *
59462                * @static
59463                * @memberOf _
59464                * @since 2.4.0
59465                * @category Util
59466                * @param {Array|string} path The path of the property to get.
59467                * @returns {Function} Returns the new accessor function.
59468                * @example
59469                *
59470                * var objects = [
59471                *   { 'a': { 'b': 2 } },
59472                *   { 'a': { 'b': 1 } }
59473                * ];
59474                *
59475                * _.map(objects, _.property('a.b'));
59476                * // => [2, 1]
59477                *
59478                * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
59479                * // => [1, 2]
59480                */
59481
59482               function property(path) {
59483                 return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
59484               }
59485               /**
59486                * The opposite of `_.property`; this method creates a function that returns
59487                * the value at a given path of `object`.
59488                *
59489                * @static
59490                * @memberOf _
59491                * @since 3.0.0
59492                * @category Util
59493                * @param {Object} object The object to query.
59494                * @returns {Function} Returns the new accessor function.
59495                * @example
59496                *
59497                * var array = [0, 1, 2],
59498                *     object = { 'a': array, 'b': array, 'c': array };
59499                *
59500                * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
59501                * // => [2, 0]
59502                *
59503                * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
59504                * // => [2, 0]
59505                */
59506
59507
59508               function propertyOf(object) {
59509                 return function (path) {
59510                   return object == null ? undefined$1 : baseGet(object, path);
59511                 };
59512               }
59513               /**
59514                * Creates an array of numbers (positive and/or negative) progressing from
59515                * `start` up to, but not including, `end`. A step of `-1` is used if a negative
59516                * `start` is specified without an `end` or `step`. If `end` is not specified,
59517                * it's set to `start` with `start` then set to `0`.
59518                *
59519                * **Note:** JavaScript follows the IEEE-754 standard for resolving
59520                * floating-point values which can produce unexpected results.
59521                *
59522                * @static
59523                * @since 0.1.0
59524                * @memberOf _
59525                * @category Util
59526                * @param {number} [start=0] The start of the range.
59527                * @param {number} end The end of the range.
59528                * @param {number} [step=1] The value to increment or decrement by.
59529                * @returns {Array} Returns the range of numbers.
59530                * @see _.inRange, _.rangeRight
59531                * @example
59532                *
59533                * _.range(4);
59534                * // => [0, 1, 2, 3]
59535                *
59536                * _.range(-4);
59537                * // => [0, -1, -2, -3]
59538                *
59539                * _.range(1, 5);
59540                * // => [1, 2, 3, 4]
59541                *
59542                * _.range(0, 20, 5);
59543                * // => [0, 5, 10, 15]
59544                *
59545                * _.range(0, -4, -1);
59546                * // => [0, -1, -2, -3]
59547                *
59548                * _.range(1, 4, 0);
59549                * // => [1, 1, 1]
59550                *
59551                * _.range(0);
59552                * // => []
59553                */
59554
59555
59556               var range = createRange();
59557               /**
59558                * This method is like `_.range` except that it populates values in
59559                * descending order.
59560                *
59561                * @static
59562                * @memberOf _
59563                * @since 4.0.0
59564                * @category Util
59565                * @param {number} [start=0] The start of the range.
59566                * @param {number} end The end of the range.
59567                * @param {number} [step=1] The value to increment or decrement by.
59568                * @returns {Array} Returns the range of numbers.
59569                * @see _.inRange, _.range
59570                * @example
59571                *
59572                * _.rangeRight(4);
59573                * // => [3, 2, 1, 0]
59574                *
59575                * _.rangeRight(-4);
59576                * // => [-3, -2, -1, 0]
59577                *
59578                * _.rangeRight(1, 5);
59579                * // => [4, 3, 2, 1]
59580                *
59581                * _.rangeRight(0, 20, 5);
59582                * // => [15, 10, 5, 0]
59583                *
59584                * _.rangeRight(0, -4, -1);
59585                * // => [-3, -2, -1, 0]
59586                *
59587                * _.rangeRight(1, 4, 0);
59588                * // => [1, 1, 1]
59589                *
59590                * _.rangeRight(0);
59591                * // => []
59592                */
59593
59594               var rangeRight = createRange(true);
59595               /**
59596                * This method returns a new empty array.
59597                *
59598                * @static
59599                * @memberOf _
59600                * @since 4.13.0
59601                * @category Util
59602                * @returns {Array} Returns the new empty array.
59603                * @example
59604                *
59605                * var arrays = _.times(2, _.stubArray);
59606                *
59607                * console.log(arrays);
59608                * // => [[], []]
59609                *
59610                * console.log(arrays[0] === arrays[1]);
59611                * // => false
59612                */
59613
59614               function stubArray() {
59615                 return [];
59616               }
59617               /**
59618                * This method returns `false`.
59619                *
59620                * @static
59621                * @memberOf _
59622                * @since 4.13.0
59623                * @category Util
59624                * @returns {boolean} Returns `false`.
59625                * @example
59626                *
59627                * _.times(2, _.stubFalse);
59628                * // => [false, false]
59629                */
59630
59631
59632               function stubFalse() {
59633                 return false;
59634               }
59635               /**
59636                * This method returns a new empty object.
59637                *
59638                * @static
59639                * @memberOf _
59640                * @since 4.13.0
59641                * @category Util
59642                * @returns {Object} Returns the new empty object.
59643                * @example
59644                *
59645                * var objects = _.times(2, _.stubObject);
59646                *
59647                * console.log(objects);
59648                * // => [{}, {}]
59649                *
59650                * console.log(objects[0] === objects[1]);
59651                * // => false
59652                */
59653
59654
59655               function stubObject() {
59656                 return {};
59657               }
59658               /**
59659                * This method returns an empty string.
59660                *
59661                * @static
59662                * @memberOf _
59663                * @since 4.13.0
59664                * @category Util
59665                * @returns {string} Returns the empty string.
59666                * @example
59667                *
59668                * _.times(2, _.stubString);
59669                * // => ['', '']
59670                */
59671
59672
59673               function stubString() {
59674                 return '';
59675               }
59676               /**
59677                * This method returns `true`.
59678                *
59679                * @static
59680                * @memberOf _
59681                * @since 4.13.0
59682                * @category Util
59683                * @returns {boolean} Returns `true`.
59684                * @example
59685                *
59686                * _.times(2, _.stubTrue);
59687                * // => [true, true]
59688                */
59689
59690
59691               function stubTrue() {
59692                 return true;
59693               }
59694               /**
59695                * Invokes the iteratee `n` times, returning an array of the results of
59696                * each invocation. The iteratee is invoked with one argument; (index).
59697                *
59698                * @static
59699                * @since 0.1.0
59700                * @memberOf _
59701                * @category Util
59702                * @param {number} n The number of times to invoke `iteratee`.
59703                * @param {Function} [iteratee=_.identity] The function invoked per iteration.
59704                * @returns {Array} Returns the array of results.
59705                * @example
59706                *
59707                * _.times(3, String);
59708                * // => ['0', '1', '2']
59709                *
59710                *  _.times(4, _.constant(0));
59711                * // => [0, 0, 0, 0]
59712                */
59713
59714
59715               function times(n, iteratee) {
59716                 n = toInteger(n);
59717
59718                 if (n < 1 || n > MAX_SAFE_INTEGER) {
59719                   return [];
59720                 }
59721
59722                 var index = MAX_ARRAY_LENGTH,
59723                     length = nativeMin(n, MAX_ARRAY_LENGTH);
59724                 iteratee = getIteratee(iteratee);
59725                 n -= MAX_ARRAY_LENGTH;
59726                 var result = baseTimes(length, iteratee);
59727
59728                 while (++index < n) {
59729                   iteratee(index);
59730                 }
59731
59732                 return result;
59733               }
59734               /**
59735                * Converts `value` to a property path array.
59736                *
59737                * @static
59738                * @memberOf _
59739                * @since 4.0.0
59740                * @category Util
59741                * @param {*} value The value to convert.
59742                * @returns {Array} Returns the new property path array.
59743                * @example
59744                *
59745                * _.toPath('a.b.c');
59746                * // => ['a', 'b', 'c']
59747                *
59748                * _.toPath('a[0].b.c');
59749                * // => ['a', '0', 'b', 'c']
59750                */
59751
59752
59753               function toPath(value) {
59754                 if (isArray(value)) {
59755                   return arrayMap(value, toKey);
59756                 }
59757
59758                 return isSymbol(value) ? [value] : copyArray(stringToPath(toString(value)));
59759               }
59760               /**
59761                * Generates a unique ID. If `prefix` is given, the ID is appended to it.
59762                *
59763                * @static
59764                * @since 0.1.0
59765                * @memberOf _
59766                * @category Util
59767                * @param {string} [prefix=''] The value to prefix the ID with.
59768                * @returns {string} Returns the unique ID.
59769                * @example
59770                *
59771                * _.uniqueId('contact_');
59772                * // => 'contact_104'
59773                *
59774                * _.uniqueId();
59775                * // => '105'
59776                */
59777
59778
59779               function uniqueId(prefix) {
59780                 var id = ++idCounter;
59781                 return toString(prefix) + id;
59782               }
59783               /*------------------------------------------------------------------------*/
59784
59785               /**
59786                * Adds two numbers.
59787                *
59788                * @static
59789                * @memberOf _
59790                * @since 3.4.0
59791                * @category Math
59792                * @param {number} augend The first number in an addition.
59793                * @param {number} addend The second number in an addition.
59794                * @returns {number} Returns the total.
59795                * @example
59796                *
59797                * _.add(6, 4);
59798                * // => 10
59799                */
59800
59801
59802               var add = createMathOperation(function (augend, addend) {
59803                 return augend + addend;
59804               }, 0);
59805               /**
59806                * Computes `number` rounded up to `precision`.
59807                *
59808                * @static
59809                * @memberOf _
59810                * @since 3.10.0
59811                * @category Math
59812                * @param {number} number The number to round up.
59813                * @param {number} [precision=0] The precision to round up to.
59814                * @returns {number} Returns the rounded up number.
59815                * @example
59816                *
59817                * _.ceil(4.006);
59818                * // => 5
59819                *
59820                * _.ceil(6.004, 2);
59821                * // => 6.01
59822                *
59823                * _.ceil(6040, -2);
59824                * // => 6100
59825                */
59826
59827               var ceil = createRound('ceil');
59828               /**
59829                * Divide two numbers.
59830                *
59831                * @static
59832                * @memberOf _
59833                * @since 4.7.0
59834                * @category Math
59835                * @param {number} dividend The first number in a division.
59836                * @param {number} divisor The second number in a division.
59837                * @returns {number} Returns the quotient.
59838                * @example
59839                *
59840                * _.divide(6, 4);
59841                * // => 1.5
59842                */
59843
59844               var divide = createMathOperation(function (dividend, divisor) {
59845                 return dividend / divisor;
59846               }, 1);
59847               /**
59848                * Computes `number` rounded down to `precision`.
59849                *
59850                * @static
59851                * @memberOf _
59852                * @since 3.10.0
59853                * @category Math
59854                * @param {number} number The number to round down.
59855                * @param {number} [precision=0] The precision to round down to.
59856                * @returns {number} Returns the rounded down number.
59857                * @example
59858                *
59859                * _.floor(4.006);
59860                * // => 4
59861                *
59862                * _.floor(0.046, 2);
59863                * // => 0.04
59864                *
59865                * _.floor(4060, -2);
59866                * // => 4000
59867                */
59868
59869               var floor = createRound('floor');
59870               /**
59871                * Computes the maximum value of `array`. If `array` is empty or falsey,
59872                * `undefined` is returned.
59873                *
59874                * @static
59875                * @since 0.1.0
59876                * @memberOf _
59877                * @category Math
59878                * @param {Array} array The array to iterate over.
59879                * @returns {*} Returns the maximum value.
59880                * @example
59881                *
59882                * _.max([4, 2, 8, 6]);
59883                * // => 8
59884                *
59885                * _.max([]);
59886                * // => undefined
59887                */
59888
59889               function max(array) {
59890                 return array && array.length ? baseExtremum(array, identity, baseGt) : undefined$1;
59891               }
59892               /**
59893                * This method is like `_.max` except that it accepts `iteratee` which is
59894                * invoked for each element in `array` to generate the criterion by which
59895                * the value is ranked. The iteratee is invoked with one argument: (value).
59896                *
59897                * @static
59898                * @memberOf _
59899                * @since 4.0.0
59900                * @category Math
59901                * @param {Array} array The array to iterate over.
59902                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
59903                * @returns {*} Returns the maximum value.
59904                * @example
59905                *
59906                * var objects = [{ 'n': 1 }, { 'n': 2 }];
59907                *
59908                * _.maxBy(objects, function(o) { return o.n; });
59909                * // => { 'n': 2 }
59910                *
59911                * // The `_.property` iteratee shorthand.
59912                * _.maxBy(objects, 'n');
59913                * // => { 'n': 2 }
59914                */
59915
59916
59917               function maxBy(array, iteratee) {
59918                 return array && array.length ? baseExtremum(array, getIteratee(iteratee, 2), baseGt) : undefined$1;
59919               }
59920               /**
59921                * Computes the mean of the values in `array`.
59922                *
59923                * @static
59924                * @memberOf _
59925                * @since 4.0.0
59926                * @category Math
59927                * @param {Array} array The array to iterate over.
59928                * @returns {number} Returns the mean.
59929                * @example
59930                *
59931                * _.mean([4, 2, 8, 6]);
59932                * // => 5
59933                */
59934
59935
59936               function mean(array) {
59937                 return baseMean(array, identity);
59938               }
59939               /**
59940                * This method is like `_.mean` except that it accepts `iteratee` which is
59941                * invoked for each element in `array` to generate the value to be averaged.
59942                * The iteratee is invoked with one argument: (value).
59943                *
59944                * @static
59945                * @memberOf _
59946                * @since 4.7.0
59947                * @category Math
59948                * @param {Array} array The array to iterate over.
59949                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
59950                * @returns {number} Returns the mean.
59951                * @example
59952                *
59953                * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
59954                *
59955                * _.meanBy(objects, function(o) { return o.n; });
59956                * // => 5
59957                *
59958                * // The `_.property` iteratee shorthand.
59959                * _.meanBy(objects, 'n');
59960                * // => 5
59961                */
59962
59963
59964               function meanBy(array, iteratee) {
59965                 return baseMean(array, getIteratee(iteratee, 2));
59966               }
59967               /**
59968                * Computes the minimum value of `array`. If `array` is empty or falsey,
59969                * `undefined` is returned.
59970                *
59971                * @static
59972                * @since 0.1.0
59973                * @memberOf _
59974                * @category Math
59975                * @param {Array} array The array to iterate over.
59976                * @returns {*} Returns the minimum value.
59977                * @example
59978                *
59979                * _.min([4, 2, 8, 6]);
59980                * // => 2
59981                *
59982                * _.min([]);
59983                * // => undefined
59984                */
59985
59986
59987               function min(array) {
59988                 return array && array.length ? baseExtremum(array, identity, baseLt) : undefined$1;
59989               }
59990               /**
59991                * This method is like `_.min` except that it accepts `iteratee` which is
59992                * invoked for each element in `array` to generate the criterion by which
59993                * the value is ranked. The iteratee is invoked with one argument: (value).
59994                *
59995                * @static
59996                * @memberOf _
59997                * @since 4.0.0
59998                * @category Math
59999                * @param {Array} array The array to iterate over.
60000                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
60001                * @returns {*} Returns the minimum value.
60002                * @example
60003                *
60004                * var objects = [{ 'n': 1 }, { 'n': 2 }];
60005                *
60006                * _.minBy(objects, function(o) { return o.n; });
60007                * // => { 'n': 1 }
60008                *
60009                * // The `_.property` iteratee shorthand.
60010                * _.minBy(objects, 'n');
60011                * // => { 'n': 1 }
60012                */
60013
60014
60015               function minBy(array, iteratee) {
60016                 return array && array.length ? baseExtremum(array, getIteratee(iteratee, 2), baseLt) : undefined$1;
60017               }
60018               /**
60019                * Multiply two numbers.
60020                *
60021                * @static
60022                * @memberOf _
60023                * @since 4.7.0
60024                * @category Math
60025                * @param {number} multiplier The first number in a multiplication.
60026                * @param {number} multiplicand The second number in a multiplication.
60027                * @returns {number} Returns the product.
60028                * @example
60029                *
60030                * _.multiply(6, 4);
60031                * // => 24
60032                */
60033
60034
60035               var multiply = createMathOperation(function (multiplier, multiplicand) {
60036                 return multiplier * multiplicand;
60037               }, 1);
60038               /**
60039                * Computes `number` rounded to `precision`.
60040                *
60041                * @static
60042                * @memberOf _
60043                * @since 3.10.0
60044                * @category Math
60045                * @param {number} number The number to round.
60046                * @param {number} [precision=0] The precision to round to.
60047                * @returns {number} Returns the rounded number.
60048                * @example
60049                *
60050                * _.round(4.006);
60051                * // => 4
60052                *
60053                * _.round(4.006, 2);
60054                * // => 4.01
60055                *
60056                * _.round(4060, -2);
60057                * // => 4100
60058                */
60059
60060               var round = createRound('round');
60061               /**
60062                * Subtract two numbers.
60063                *
60064                * @static
60065                * @memberOf _
60066                * @since 4.0.0
60067                * @category Math
60068                * @param {number} minuend The first number in a subtraction.
60069                * @param {number} subtrahend The second number in a subtraction.
60070                * @returns {number} Returns the difference.
60071                * @example
60072                *
60073                * _.subtract(6, 4);
60074                * // => 2
60075                */
60076
60077               var subtract = createMathOperation(function (minuend, subtrahend) {
60078                 return minuend - subtrahend;
60079               }, 0);
60080               /**
60081                * Computes the sum of the values in `array`.
60082                *
60083                * @static
60084                * @memberOf _
60085                * @since 3.4.0
60086                * @category Math
60087                * @param {Array} array The array to iterate over.
60088                * @returns {number} Returns the sum.
60089                * @example
60090                *
60091                * _.sum([4, 2, 8, 6]);
60092                * // => 20
60093                */
60094
60095               function sum(array) {
60096                 return array && array.length ? baseSum(array, identity) : 0;
60097               }
60098               /**
60099                * This method is like `_.sum` except that it accepts `iteratee` which is
60100                * invoked for each element in `array` to generate the value to be summed.
60101                * The iteratee is invoked with one argument: (value).
60102                *
60103                * @static
60104                * @memberOf _
60105                * @since 4.0.0
60106                * @category Math
60107                * @param {Array} array The array to iterate over.
60108                * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
60109                * @returns {number} Returns the sum.
60110                * @example
60111                *
60112                * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
60113                *
60114                * _.sumBy(objects, function(o) { return o.n; });
60115                * // => 20
60116                *
60117                * // The `_.property` iteratee shorthand.
60118                * _.sumBy(objects, 'n');
60119                * // => 20
60120                */
60121
60122
60123               function sumBy(array, iteratee) {
60124                 return array && array.length ? baseSum(array, getIteratee(iteratee, 2)) : 0;
60125               }
60126               /*------------------------------------------------------------------------*/
60127               // Add methods that return wrapped values in chain sequences.
60128
60129
60130               lodash.after = after;
60131               lodash.ary = ary;
60132               lodash.assign = assign;
60133               lodash.assignIn = assignIn;
60134               lodash.assignInWith = assignInWith;
60135               lodash.assignWith = assignWith;
60136               lodash.at = at;
60137               lodash.before = before;
60138               lodash.bind = bind;
60139               lodash.bindAll = bindAll;
60140               lodash.bindKey = bindKey;
60141               lodash.castArray = castArray;
60142               lodash.chain = chain;
60143               lodash.chunk = chunk;
60144               lodash.compact = compact;
60145               lodash.concat = concat;
60146               lodash.cond = cond;
60147               lodash.conforms = conforms;
60148               lodash.constant = constant;
60149               lodash.countBy = countBy;
60150               lodash.create = create;
60151               lodash.curry = curry;
60152               lodash.curryRight = curryRight;
60153               lodash.debounce = debounce;
60154               lodash.defaults = defaults;
60155               lodash.defaultsDeep = defaultsDeep;
60156               lodash.defer = defer;
60157               lodash.delay = delay;
60158               lodash.difference = difference;
60159               lodash.differenceBy = differenceBy;
60160               lodash.differenceWith = differenceWith;
60161               lodash.drop = drop;
60162               lodash.dropRight = dropRight;
60163               lodash.dropRightWhile = dropRightWhile;
60164               lodash.dropWhile = dropWhile;
60165               lodash.fill = fill;
60166               lodash.filter = filter;
60167               lodash.flatMap = flatMap;
60168               lodash.flatMapDeep = flatMapDeep;
60169               lodash.flatMapDepth = flatMapDepth;
60170               lodash.flatten = flatten;
60171               lodash.flattenDeep = flattenDeep;
60172               lodash.flattenDepth = flattenDepth;
60173               lodash.flip = flip;
60174               lodash.flow = flow;
60175               lodash.flowRight = flowRight;
60176               lodash.fromPairs = fromPairs;
60177               lodash.functions = functions;
60178               lodash.functionsIn = functionsIn;
60179               lodash.groupBy = groupBy;
60180               lodash.initial = initial;
60181               lodash.intersection = intersection;
60182               lodash.intersectionBy = intersectionBy;
60183               lodash.intersectionWith = intersectionWith;
60184               lodash.invert = invert;
60185               lodash.invertBy = invertBy;
60186               lodash.invokeMap = invokeMap;
60187               lodash.iteratee = iteratee;
60188               lodash.keyBy = keyBy;
60189               lodash.keys = keys;
60190               lodash.keysIn = keysIn;
60191               lodash.map = map;
60192               lodash.mapKeys = mapKeys;
60193               lodash.mapValues = mapValues;
60194               lodash.matches = matches;
60195               lodash.matchesProperty = matchesProperty;
60196               lodash.memoize = memoize;
60197               lodash.merge = merge;
60198               lodash.mergeWith = mergeWith;
60199               lodash.method = method;
60200               lodash.methodOf = methodOf;
60201               lodash.mixin = mixin;
60202               lodash.negate = negate;
60203               lodash.nthArg = nthArg;
60204               lodash.omit = omit;
60205               lodash.omitBy = omitBy;
60206               lodash.once = once;
60207               lodash.orderBy = orderBy;
60208               lodash.over = over;
60209               lodash.overArgs = overArgs;
60210               lodash.overEvery = overEvery;
60211               lodash.overSome = overSome;
60212               lodash.partial = partial;
60213               lodash.partialRight = partialRight;
60214               lodash.partition = partition;
60215               lodash.pick = pick;
60216               lodash.pickBy = pickBy;
60217               lodash.property = property;
60218               lodash.propertyOf = propertyOf;
60219               lodash.pull = pull;
60220               lodash.pullAll = pullAll;
60221               lodash.pullAllBy = pullAllBy;
60222               lodash.pullAllWith = pullAllWith;
60223               lodash.pullAt = pullAt;
60224               lodash.range = range;
60225               lodash.rangeRight = rangeRight;
60226               lodash.rearg = rearg;
60227               lodash.reject = reject;
60228               lodash.remove = remove;
60229               lodash.rest = rest;
60230               lodash.reverse = reverse;
60231               lodash.sampleSize = sampleSize;
60232               lodash.set = set;
60233               lodash.setWith = setWith;
60234               lodash.shuffle = shuffle;
60235               lodash.slice = slice;
60236               lodash.sortBy = sortBy;
60237               lodash.sortedUniq = sortedUniq;
60238               lodash.sortedUniqBy = sortedUniqBy;
60239               lodash.split = split;
60240               lodash.spread = spread;
60241               lodash.tail = tail;
60242               lodash.take = take;
60243               lodash.takeRight = takeRight;
60244               lodash.takeRightWhile = takeRightWhile;
60245               lodash.takeWhile = takeWhile;
60246               lodash.tap = tap;
60247               lodash.throttle = throttle;
60248               lodash.thru = thru;
60249               lodash.toArray = toArray;
60250               lodash.toPairs = toPairs;
60251               lodash.toPairsIn = toPairsIn;
60252               lodash.toPath = toPath;
60253               lodash.toPlainObject = toPlainObject;
60254               lodash.transform = transform;
60255               lodash.unary = unary;
60256               lodash.union = union;
60257               lodash.unionBy = unionBy;
60258               lodash.unionWith = unionWith;
60259               lodash.uniq = uniq;
60260               lodash.uniqBy = uniqBy;
60261               lodash.uniqWith = uniqWith;
60262               lodash.unset = unset;
60263               lodash.unzip = unzip;
60264               lodash.unzipWith = unzipWith;
60265               lodash.update = update;
60266               lodash.updateWith = updateWith;
60267               lodash.values = values;
60268               lodash.valuesIn = valuesIn;
60269               lodash.without = without;
60270               lodash.words = words;
60271               lodash.wrap = wrap;
60272               lodash.xor = xor;
60273               lodash.xorBy = xorBy;
60274               lodash.xorWith = xorWith;
60275               lodash.zip = zip;
60276               lodash.zipObject = zipObject;
60277               lodash.zipObjectDeep = zipObjectDeep;
60278               lodash.zipWith = zipWith; // Add aliases.
60279
60280               lodash.entries = toPairs;
60281               lodash.entriesIn = toPairsIn;
60282               lodash.extend = assignIn;
60283               lodash.extendWith = assignInWith; // Add methods to `lodash.prototype`.
60284
60285               mixin(lodash, lodash);
60286               /*------------------------------------------------------------------------*/
60287               // Add methods that return unwrapped values in chain sequences.
60288
60289               lodash.add = add;
60290               lodash.attempt = attempt;
60291               lodash.camelCase = camelCase;
60292               lodash.capitalize = capitalize;
60293               lodash.ceil = ceil;
60294               lodash.clamp = clamp;
60295               lodash.clone = clone;
60296               lodash.cloneDeep = cloneDeep;
60297               lodash.cloneDeepWith = cloneDeepWith;
60298               lodash.cloneWith = cloneWith;
60299               lodash.conformsTo = conformsTo;
60300               lodash.deburr = deburr;
60301               lodash.defaultTo = defaultTo;
60302               lodash.divide = divide;
60303               lodash.endsWith = endsWith;
60304               lodash.eq = eq;
60305               lodash.escape = escape;
60306               lodash.escapeRegExp = escapeRegExp;
60307               lodash.every = every;
60308               lodash.find = find;
60309               lodash.findIndex = findIndex;
60310               lodash.findKey = findKey;
60311               lodash.findLast = findLast;
60312               lodash.findLastIndex = findLastIndex;
60313               lodash.findLastKey = findLastKey;
60314               lodash.floor = floor;
60315               lodash.forEach = forEach;
60316               lodash.forEachRight = forEachRight;
60317               lodash.forIn = forIn;
60318               lodash.forInRight = forInRight;
60319               lodash.forOwn = forOwn;
60320               lodash.forOwnRight = forOwnRight;
60321               lodash.get = get;
60322               lodash.gt = gt;
60323               lodash.gte = gte;
60324               lodash.has = has;
60325               lodash.hasIn = hasIn;
60326               lodash.head = head;
60327               lodash.identity = identity;
60328               lodash.includes = includes;
60329               lodash.indexOf = indexOf;
60330               lodash.inRange = inRange;
60331               lodash.invoke = invoke;
60332               lodash.isArguments = isArguments;
60333               lodash.isArray = isArray;
60334               lodash.isArrayBuffer = isArrayBuffer;
60335               lodash.isArrayLike = isArrayLike;
60336               lodash.isArrayLikeObject = isArrayLikeObject;
60337               lodash.isBoolean = isBoolean;
60338               lodash.isBuffer = isBuffer;
60339               lodash.isDate = isDate;
60340               lodash.isElement = isElement;
60341               lodash.isEmpty = isEmpty;
60342               lodash.isEqual = isEqual;
60343               lodash.isEqualWith = isEqualWith;
60344               lodash.isError = isError;
60345               lodash.isFinite = isFinite;
60346               lodash.isFunction = isFunction;
60347               lodash.isInteger = isInteger;
60348               lodash.isLength = isLength;
60349               lodash.isMap = isMap;
60350               lodash.isMatch = isMatch;
60351               lodash.isMatchWith = isMatchWith;
60352               lodash.isNaN = isNaN;
60353               lodash.isNative = isNative;
60354               lodash.isNil = isNil;
60355               lodash.isNull = isNull;
60356               lodash.isNumber = isNumber;
60357               lodash.isObject = isObject;
60358               lodash.isObjectLike = isObjectLike;
60359               lodash.isPlainObject = isPlainObject;
60360               lodash.isRegExp = isRegExp;
60361               lodash.isSafeInteger = isSafeInteger;
60362               lodash.isSet = isSet;
60363               lodash.isString = isString;
60364               lodash.isSymbol = isSymbol;
60365               lodash.isTypedArray = isTypedArray;
60366               lodash.isUndefined = isUndefined;
60367               lodash.isWeakMap = isWeakMap;
60368               lodash.isWeakSet = isWeakSet;
60369               lodash.join = join;
60370               lodash.kebabCase = kebabCase;
60371               lodash.last = last;
60372               lodash.lastIndexOf = lastIndexOf;
60373               lodash.lowerCase = lowerCase;
60374               lodash.lowerFirst = lowerFirst;
60375               lodash.lt = lt;
60376               lodash.lte = lte;
60377               lodash.max = max;
60378               lodash.maxBy = maxBy;
60379               lodash.mean = mean;
60380               lodash.meanBy = meanBy;
60381               lodash.min = min;
60382               lodash.minBy = minBy;
60383               lodash.stubArray = stubArray;
60384               lodash.stubFalse = stubFalse;
60385               lodash.stubObject = stubObject;
60386               lodash.stubString = stubString;
60387               lodash.stubTrue = stubTrue;
60388               lodash.multiply = multiply;
60389               lodash.nth = nth;
60390               lodash.noConflict = noConflict;
60391               lodash.noop = noop;
60392               lodash.now = now;
60393               lodash.pad = pad;
60394               lodash.padEnd = padEnd;
60395               lodash.padStart = padStart;
60396               lodash.parseInt = parseInt;
60397               lodash.random = random;
60398               lodash.reduce = reduce;
60399               lodash.reduceRight = reduceRight;
60400               lodash.repeat = repeat;
60401               lodash.replace = replace;
60402               lodash.result = result;
60403               lodash.round = round;
60404               lodash.runInContext = runInContext;
60405               lodash.sample = sample;
60406               lodash.size = size;
60407               lodash.snakeCase = snakeCase;
60408               lodash.some = some;
60409               lodash.sortedIndex = sortedIndex;
60410               lodash.sortedIndexBy = sortedIndexBy;
60411               lodash.sortedIndexOf = sortedIndexOf;
60412               lodash.sortedLastIndex = sortedLastIndex;
60413               lodash.sortedLastIndexBy = sortedLastIndexBy;
60414               lodash.sortedLastIndexOf = sortedLastIndexOf;
60415               lodash.startCase = startCase;
60416               lodash.startsWith = startsWith;
60417               lodash.subtract = subtract;
60418               lodash.sum = sum;
60419               lodash.sumBy = sumBy;
60420               lodash.template = template;
60421               lodash.times = times;
60422               lodash.toFinite = toFinite;
60423               lodash.toInteger = toInteger;
60424               lodash.toLength = toLength;
60425               lodash.toLower = toLower;
60426               lodash.toNumber = toNumber;
60427               lodash.toSafeInteger = toSafeInteger;
60428               lodash.toString = toString;
60429               lodash.toUpper = toUpper;
60430               lodash.trim = trim;
60431               lodash.trimEnd = trimEnd;
60432               lodash.trimStart = trimStart;
60433               lodash.truncate = truncate;
60434               lodash.unescape = unescape;
60435               lodash.uniqueId = uniqueId;
60436               lodash.upperCase = upperCase;
60437               lodash.upperFirst = upperFirst; // Add aliases.
60438
60439               lodash.each = forEach;
60440               lodash.eachRight = forEachRight;
60441               lodash.first = head;
60442               mixin(lodash, function () {
60443                 var source = {};
60444                 baseForOwn(lodash, function (func, methodName) {
60445                   if (!hasOwnProperty.call(lodash.prototype, methodName)) {
60446                     source[methodName] = func;
60447                   }
60448                 });
60449                 return source;
60450               }(), {
60451                 'chain': false
60452               });
60453               /*------------------------------------------------------------------------*/
60454
60455               /**
60456                * The semantic version number.
60457                *
60458                * @static
60459                * @memberOf _
60460                * @type {string}
60461                */
60462
60463               lodash.VERSION = VERSION; // Assign default placeholders.
60464
60465               arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function (methodName) {
60466                 lodash[methodName].placeholder = lodash;
60467               }); // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
60468
60469               arrayEach(['drop', 'take'], function (methodName, index) {
60470                 LazyWrapper.prototype[methodName] = function (n) {
60471                   n = n === undefined$1 ? 1 : nativeMax(toInteger(n), 0);
60472                   var result = this.__filtered__ && !index ? new LazyWrapper(this) : this.clone();
60473
60474                   if (result.__filtered__) {
60475                     result.__takeCount__ = nativeMin(n, result.__takeCount__);
60476                   } else {
60477                     result.__views__.push({
60478                       'size': nativeMin(n, MAX_ARRAY_LENGTH),
60479                       'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
60480                     });
60481                   }
60482
60483                   return result;
60484                 };
60485
60486                 LazyWrapper.prototype[methodName + 'Right'] = function (n) {
60487                   return this.reverse()[methodName](n).reverse();
60488                 };
60489               }); // Add `LazyWrapper` methods that accept an `iteratee` value.
60490
60491               arrayEach(['filter', 'map', 'takeWhile'], function (methodName, index) {
60492                 var type = index + 1,
60493                     isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
60494
60495                 LazyWrapper.prototype[methodName] = function (iteratee) {
60496                   var result = this.clone();
60497
60498                   result.__iteratees__.push({
60499                     'iteratee': getIteratee(iteratee, 3),
60500                     'type': type
60501                   });
60502
60503                   result.__filtered__ = result.__filtered__ || isFilter;
60504                   return result;
60505                 };
60506               }); // Add `LazyWrapper` methods for `_.head` and `_.last`.
60507
60508               arrayEach(['head', 'last'], function (methodName, index) {
60509                 var takeName = 'take' + (index ? 'Right' : '');
60510
60511                 LazyWrapper.prototype[methodName] = function () {
60512                   return this[takeName](1).value()[0];
60513                 };
60514               }); // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
60515
60516               arrayEach(['initial', 'tail'], function (methodName, index) {
60517                 var dropName = 'drop' + (index ? '' : 'Right');
60518
60519                 LazyWrapper.prototype[methodName] = function () {
60520                   return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
60521                 };
60522               });
60523
60524               LazyWrapper.prototype.compact = function () {
60525                 return this.filter(identity);
60526               };
60527
60528               LazyWrapper.prototype.find = function (predicate) {
60529                 return this.filter(predicate).head();
60530               };
60531
60532               LazyWrapper.prototype.findLast = function (predicate) {
60533                 return this.reverse().find(predicate);
60534               };
60535
60536               LazyWrapper.prototype.invokeMap = baseRest(function (path, args) {
60537                 if (typeof path == 'function') {
60538                   return new LazyWrapper(this);
60539                 }
60540
60541                 return this.map(function (value) {
60542                   return baseInvoke(value, path, args);
60543                 });
60544               });
60545
60546               LazyWrapper.prototype.reject = function (predicate) {
60547                 return this.filter(negate(getIteratee(predicate)));
60548               };
60549
60550               LazyWrapper.prototype.slice = function (start, end) {
60551                 start = toInteger(start);
60552                 var result = this;
60553
60554                 if (result.__filtered__ && (start > 0 || end < 0)) {
60555                   return new LazyWrapper(result);
60556                 }
60557
60558                 if (start < 0) {
60559                   result = result.takeRight(-start);
60560                 } else if (start) {
60561                   result = result.drop(start);
60562                 }
60563
60564                 if (end !== undefined$1) {
60565                   end = toInteger(end);
60566                   result = end < 0 ? result.dropRight(-end) : result.take(end - start);
60567                 }
60568
60569                 return result;
60570               };
60571
60572               LazyWrapper.prototype.takeRightWhile = function (predicate) {
60573                 return this.reverse().takeWhile(predicate).reverse();
60574               };
60575
60576               LazyWrapper.prototype.toArray = function () {
60577                 return this.take(MAX_ARRAY_LENGTH);
60578               }; // Add `LazyWrapper` methods to `lodash.prototype`.
60579
60580
60581               baseForOwn(LazyWrapper.prototype, function (func, methodName) {
60582                 var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
60583                     isTaker = /^(?:head|last)$/.test(methodName),
60584                     lodashFunc = lodash[isTaker ? 'take' + (methodName == 'last' ? 'Right' : '') : methodName],
60585                     retUnwrapped = isTaker || /^find/.test(methodName);
60586
60587                 if (!lodashFunc) {
60588                   return;
60589                 }
60590
60591                 lodash.prototype[methodName] = function () {
60592                   var value = this.__wrapped__,
60593                       args = isTaker ? [1] : arguments,
60594                       isLazy = value instanceof LazyWrapper,
60595                       iteratee = args[0],
60596                       useLazy = isLazy || isArray(value);
60597
60598                   var interceptor = function interceptor(value) {
60599                     var result = lodashFunc.apply(lodash, arrayPush([value], args));
60600                     return isTaker && chainAll ? result[0] : result;
60601                   };
60602
60603                   if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
60604                     // Avoid lazy use if the iteratee has a "length" value other than `1`.
60605                     isLazy = useLazy = false;
60606                   }
60607
60608                   var chainAll = this.__chain__,
60609                       isHybrid = !!this.__actions__.length,
60610                       isUnwrapped = retUnwrapped && !chainAll,
60611                       onlyLazy = isLazy && !isHybrid;
60612
60613                   if (!retUnwrapped && useLazy) {
60614                     value = onlyLazy ? value : new LazyWrapper(this);
60615                     var result = func.apply(value, args);
60616
60617                     result.__actions__.push({
60618                       'func': thru,
60619                       'args': [interceptor],
60620                       'thisArg': undefined$1
60621                     });
60622
60623                     return new LodashWrapper(result, chainAll);
60624                   }
60625
60626                   if (isUnwrapped && onlyLazy) {
60627                     return func.apply(this, args);
60628                   }
60629
60630                   result = this.thru(interceptor);
60631                   return isUnwrapped ? isTaker ? result.value()[0] : result.value() : result;
60632                 };
60633               }); // Add `Array` methods to `lodash.prototype`.
60634
60635               arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function (methodName) {
60636                 var func = arrayProto[methodName],
60637                     chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
60638                     retUnwrapped = /^(?:pop|shift)$/.test(methodName);
60639
60640                 lodash.prototype[methodName] = function () {
60641                   var args = arguments;
60642
60643                   if (retUnwrapped && !this.__chain__) {
60644                     var value = this.value();
60645                     return func.apply(isArray(value) ? value : [], args);
60646                   }
60647
60648                   return this[chainName](function (value) {
60649                     return func.apply(isArray(value) ? value : [], args);
60650                   });
60651                 };
60652               }); // Map minified method names to their real names.
60653
60654               baseForOwn(LazyWrapper.prototype, function (func, methodName) {
60655                 var lodashFunc = lodash[methodName];
60656
60657                 if (lodashFunc) {
60658                   var key = lodashFunc.name + '';
60659
60660                   if (!hasOwnProperty.call(realNames, key)) {
60661                     realNames[key] = [];
60662                   }
60663
60664                   realNames[key].push({
60665                     'name': methodName,
60666                     'func': lodashFunc
60667                   });
60668                 }
60669               });
60670               realNames[createHybrid(undefined$1, WRAP_BIND_KEY_FLAG).name] = [{
60671                 'name': 'wrapper',
60672                 'func': undefined$1
60673               }]; // Add methods to `LazyWrapper`.
60674
60675               LazyWrapper.prototype.clone = lazyClone;
60676               LazyWrapper.prototype.reverse = lazyReverse;
60677               LazyWrapper.prototype.value = lazyValue; // Add chain sequence methods to the `lodash` wrapper.
60678
60679               lodash.prototype.at = wrapperAt;
60680               lodash.prototype.chain = wrapperChain;
60681               lodash.prototype.commit = wrapperCommit;
60682               lodash.prototype.next = wrapperNext;
60683               lodash.prototype.plant = wrapperPlant;
60684               lodash.prototype.reverse = wrapperReverse;
60685               lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue; // Add lazy aliases.
60686
60687               lodash.prototype.first = lodash.prototype.head;
60688
60689               if (symIterator) {
60690                 lodash.prototype[symIterator] = wrapperToIterator;
60691               }
60692
60693               return lodash;
60694             };
60695             /*--------------------------------------------------------------------------*/
60696             // Export lodash.
60697
60698
60699             var _ = runInContext(); // Some AMD build optimizers, like r.js, check for condition patterns like:
60700
60701
60702             if (freeModule) {
60703               // Export for Node.js.
60704               (freeModule.exports = _)._ = _; // Export for CommonJS support.
60705
60706               freeExports._ = _;
60707             } else {
60708               // Export to the global object.
60709               root._ = _;
60710             }
60711           }).call(commonjsGlobal);
60712         })(lodash, lodash.exports);
60713
60714         function actionMergeRemoteChanges(id, localGraph, remoteGraph, discardTags, formatUser) {
60715           discardTags = discardTags || {};
60716           var _option = 'safe'; // 'safe', 'force_local', 'force_remote'
60717
60718           var _conflicts = [];
60719
60720           function user(d) {
60721             return typeof formatUser === 'function' ? formatUser(d) : lodash.exports.escape(d);
60722           }
60723
60724           function mergeLocation(remote, target) {
60725             function pointEqual(a, b) {
60726               var epsilon = 1e-6;
60727               return Math.abs(a[0] - b[0]) < epsilon && Math.abs(a[1] - b[1]) < epsilon;
60728             }
60729
60730             if (_option === 'force_local' || pointEqual(target.loc, remote.loc)) {
60731               return target;
60732             }
60733
60734             if (_option === 'force_remote') {
60735               return target.update({
60736                 loc: remote.loc
60737               });
60738             }
60739
60740             _conflicts.push(_t.html('merge_remote_changes.conflict.location', {
60741               user: {
60742                 html: user(remote.user)
60743               }
60744             }));
60745
60746             return target;
60747           }
60748
60749           function mergeNodes(base, remote, target) {
60750             if (_option === 'force_local' || fastDeepEqual(target.nodes, remote.nodes)) {
60751               return target;
60752             }
60753
60754             if (_option === 'force_remote') {
60755               return target.update({
60756                 nodes: remote.nodes
60757               });
60758             }
60759
60760             var ccount = _conflicts.length;
60761             var o = base.nodes || [];
60762             var a = target.nodes || [];
60763             var b = remote.nodes || [];
60764             var nodes = [];
60765             var hunks = diff3Merge(a, o, b, {
60766               excludeFalseConflicts: true
60767             });
60768
60769             for (var i = 0; i < hunks.length; i++) {
60770               var hunk = hunks[i];
60771
60772               if (hunk.ok) {
60773                 nodes.push.apply(nodes, hunk.ok);
60774               } else {
60775                 // for all conflicts, we can assume c.a !== c.b
60776                 // because `diff3Merge` called with `true` option to exclude false conflicts..
60777                 var c = hunk.conflict;
60778
60779                 if (fastDeepEqual(c.o, c.a)) {
60780                   // only changed remotely
60781                   nodes.push.apply(nodes, c.b);
60782                 } else if (fastDeepEqual(c.o, c.b)) {
60783                   // only changed locally
60784                   nodes.push.apply(nodes, c.a);
60785                 } else {
60786                   // changed both locally and remotely
60787                   _conflicts.push(_t.html('merge_remote_changes.conflict.nodelist', {
60788                     user: {
60789                       html: user(remote.user)
60790                     }
60791                   }));
60792
60793                   break;
60794                 }
60795               }
60796             }
60797
60798             return _conflicts.length === ccount ? target.update({
60799               nodes: nodes
60800             }) : target;
60801           }
60802
60803           function mergeChildren(targetWay, children, updates, graph) {
60804             function isUsed(node, targetWay) {
60805               var hasInterestingParent = graph.parentWays(node).some(function (way) {
60806                 return way.id !== targetWay.id;
60807               });
60808               return node.hasInterestingTags() || hasInterestingParent || graph.parentRelations(node).length > 0;
60809             }
60810
60811             var ccount = _conflicts.length;
60812
60813             for (var i = 0; i < children.length; i++) {
60814               var id = children[i];
60815               var node = graph.hasEntity(id); // remove unused childNodes..
60816
60817               if (targetWay.nodes.indexOf(id) === -1) {
60818                 if (node && !isUsed(node, targetWay)) {
60819                   updates.removeIds.push(id);
60820                 }
60821
60822                 continue;
60823               } // restore used childNodes..
60824
60825
60826               var local = localGraph.hasEntity(id);
60827               var remote = remoteGraph.hasEntity(id);
60828               var target;
60829
60830               if (_option === 'force_remote' && remote && remote.visible) {
60831                 updates.replacements.push(remote);
60832               } else if (_option === 'force_local' && local) {
60833                 target = osmEntity(local);
60834
60835                 if (remote) {
60836                   target = target.update({
60837                     version: remote.version
60838                   });
60839                 }
60840
60841                 updates.replacements.push(target);
60842               } else if (_option === 'safe' && local && remote && local.version !== remote.version) {
60843                 target = osmEntity(local, {
60844                   version: remote.version
60845                 });
60846
60847                 if (remote.visible) {
60848                   target = mergeLocation(remote, target);
60849                 } else {
60850                   _conflicts.push(_t.html('merge_remote_changes.conflict.deleted', {
60851                     user: {
60852                       html: user(remote.user)
60853                     }
60854                   }));
60855                 }
60856
60857                 if (_conflicts.length !== ccount) break;
60858                 updates.replacements.push(target);
60859               }
60860             }
60861
60862             return targetWay;
60863           }
60864
60865           function updateChildren(updates, graph) {
60866             for (var i = 0; i < updates.replacements.length; i++) {
60867               graph = graph.replace(updates.replacements[i]);
60868             }
60869
60870             if (updates.removeIds.length) {
60871               graph = actionDeleteMultiple(updates.removeIds)(graph);
60872             }
60873
60874             return graph;
60875           }
60876
60877           function mergeMembers(remote, target) {
60878             if (_option === 'force_local' || fastDeepEqual(target.members, remote.members)) {
60879               return target;
60880             }
60881
60882             if (_option === 'force_remote') {
60883               return target.update({
60884                 members: remote.members
60885               });
60886             }
60887
60888             _conflicts.push(_t.html('merge_remote_changes.conflict.memberlist', {
60889               user: {
60890                 html: user(remote.user)
60891               }
60892             }));
60893
60894             return target;
60895           }
60896
60897           function mergeTags(base, remote, target) {
60898             if (_option === 'force_local' || fastDeepEqual(target.tags, remote.tags)) {
60899               return target;
60900             }
60901
60902             if (_option === 'force_remote') {
60903               return target.update({
60904                 tags: remote.tags
60905               });
60906             }
60907
60908             var ccount = _conflicts.length;
60909             var o = base.tags || {};
60910             var a = target.tags || {};
60911             var b = remote.tags || {};
60912             var keys = utilArrayUnion(utilArrayUnion(Object.keys(o), Object.keys(a)), Object.keys(b)).filter(function (k) {
60913               return !discardTags[k];
60914             });
60915             var tags = Object.assign({}, a); // shallow copy
60916
60917             var changed = false;
60918
60919             for (var i = 0; i < keys.length; i++) {
60920               var k = keys[i];
60921
60922               if (o[k] !== b[k] && a[k] !== b[k]) {
60923                 // changed remotely..
60924                 if (o[k] !== a[k]) {
60925                   // changed locally..
60926                   _conflicts.push(_t.html('merge_remote_changes.conflict.tags', {
60927                     tag: k,
60928                     local: a[k],
60929                     remote: b[k],
60930                     user: {
60931                       html: user(remote.user)
60932                     }
60933                   }));
60934                 } else {
60935                   // unchanged locally, accept remote change..
60936                   if (b.hasOwnProperty(k)) {
60937                     tags[k] = b[k];
60938                   } else {
60939                     delete tags[k];
60940                   }
60941
60942                   changed = true;
60943                 }
60944               }
60945             }
60946
60947             return changed && _conflicts.length === ccount ? target.update({
60948               tags: tags
60949             }) : target;
60950           } //  `graph.base()` is the common ancestor of the two graphs.
60951           //  `localGraph` contains user's edits up to saving
60952           //  `remoteGraph` contains remote edits to modified nodes
60953           //  `graph` must be a descendent of `localGraph` and may include
60954           //      some conflict resolution actions performed on it.
60955           //
60956           //                  --- ... --- `localGraph` -- ... -- `graph`
60957           //                 /
60958           //  `graph.base()` --- ... --- `remoteGraph`
60959           //
60960
60961
60962           var action = function action(graph) {
60963             var updates = {
60964               replacements: [],
60965               removeIds: []
60966             };
60967             var base = graph.base().entities[id];
60968             var local = localGraph.entity(id);
60969             var remote = remoteGraph.entity(id);
60970             var target = osmEntity(local, {
60971               version: remote.version
60972             }); // delete/undelete
60973
60974             if (!remote.visible) {
60975               if (_option === 'force_remote') {
60976                 return actionDeleteMultiple([id])(graph);
60977               } else if (_option === 'force_local') {
60978                 if (target.type === 'way') {
60979                   target = mergeChildren(target, utilArrayUniq(local.nodes), updates, graph);
60980                   graph = updateChildren(updates, graph);
60981                 }
60982
60983                 return graph.replace(target);
60984               } else {
60985                 _conflicts.push(_t.html('merge_remote_changes.conflict.deleted', {
60986                   user: {
60987                     html: user(remote.user)
60988                   }
60989                 }));
60990
60991                 return graph; // do nothing
60992               }
60993             } // merge
60994
60995
60996             if (target.type === 'node') {
60997               target = mergeLocation(remote, target);
60998             } else if (target.type === 'way') {
60999               // pull in any child nodes that may not be present locally..
61000               graph.rebase(remoteGraph.childNodes(remote), [graph], false);
61001               target = mergeNodes(base, remote, target);
61002               target = mergeChildren(target, utilArrayUnion(local.nodes, remote.nodes), updates, graph);
61003             } else if (target.type === 'relation') {
61004               target = mergeMembers(remote, target);
61005             }
61006
61007             target = mergeTags(base, remote, target);
61008
61009             if (!_conflicts.length) {
61010               graph = updateChildren(updates, graph).replace(target);
61011             }
61012
61013             return graph;
61014           };
61015
61016           action.withOption = function (opt) {
61017             _option = opt;
61018             return action;
61019           };
61020
61021           action.conflicts = function () {
61022             return _conflicts;
61023           };
61024
61025           return action;
61026         }
61027
61028         // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
61029
61030         function actionMove(moveIDs, tryDelta, projection, cache) {
61031           var _delta = tryDelta;
61032
61033           function setupCache(graph) {
61034             function canMove(nodeID) {
61035               // Allow movement of any node that is in the selectedIDs list..
61036               if (moveIDs.indexOf(nodeID) !== -1) return true; // Allow movement of a vertex where 2 ways meet..
61037
61038               var parents = graph.parentWays(graph.entity(nodeID));
61039               if (parents.length < 3) return true; // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
61040
61041               var parentsMoving = parents.every(function (way) {
61042                 return cache.moving[way.id];
61043               });
61044               if (!parentsMoving) delete cache.moving[nodeID];
61045               return parentsMoving;
61046             }
61047
61048             function cacheEntities(ids) {
61049               for (var i = 0; i < ids.length; i++) {
61050                 var id = ids[i];
61051                 if (cache.moving[id]) continue;
61052                 cache.moving[id] = true;
61053                 var entity = graph.hasEntity(id);
61054                 if (!entity) continue;
61055
61056                 if (entity.type === 'node') {
61057                   cache.nodes.push(id);
61058                   cache.startLoc[id] = entity.loc;
61059                 } else if (entity.type === 'way') {
61060                   cache.ways.push(id);
61061                   cacheEntities(entity.nodes);
61062                 } else {
61063                   cacheEntities(entity.members.map(function (member) {
61064                     return member.id;
61065                   }));
61066                 }
61067               }
61068             }
61069
61070             function cacheIntersections(ids) {
61071               function isEndpoint(way, id) {
61072                 return !way.isClosed() && !!way.affix(id);
61073               }
61074
61075               for (var i = 0; i < ids.length; i++) {
61076                 var id = ids[i]; // consider only intersections with 1 moved and 1 unmoved way.
61077
61078                 var childNodes = graph.childNodes(graph.entity(id));
61079
61080                 for (var j = 0; j < childNodes.length; j++) {
61081                   var node = childNodes[j];
61082                   var parents = graph.parentWays(node);
61083                   if (parents.length !== 2) continue;
61084                   var moved = graph.entity(id);
61085                   var unmoved = null;
61086
61087                   for (var k = 0; k < parents.length; k++) {
61088                     var way = parents[k];
61089
61090                     if (!cache.moving[way.id]) {
61091                       unmoved = way;
61092                       break;
61093                     }
61094                   }
61095
61096                   if (!unmoved) continue; // exclude ways that are overly connected..
61097
61098                   if (utilArrayIntersection(moved.nodes, unmoved.nodes).length > 2) continue;
61099                   if (moved.isArea() || unmoved.isArea()) continue;
61100                   cache.intersections.push({
61101                     nodeId: node.id,
61102                     movedId: moved.id,
61103                     unmovedId: unmoved.id,
61104                     movedIsEP: isEndpoint(moved, node.id),
61105                     unmovedIsEP: isEndpoint(unmoved, node.id)
61106                   });
61107                 }
61108               }
61109             }
61110
61111             if (!cache) {
61112               cache = {};
61113             }
61114
61115             if (!cache.ok) {
61116               cache.moving = {};
61117               cache.intersections = [];
61118               cache.replacedVertex = {};
61119               cache.startLoc = {};
61120               cache.nodes = [];
61121               cache.ways = [];
61122               cacheEntities(moveIDs);
61123               cacheIntersections(cache.ways);
61124               cache.nodes = cache.nodes.filter(canMove);
61125               cache.ok = true;
61126             }
61127           } // Place a vertex where the moved vertex used to be, to preserve way shape..
61128           //
61129           //  Start:
61130           //      b ---- e
61131           //     / \
61132           //    /   \
61133           //   /     \
61134           //  a       c
61135           //
61136           //      *               node '*' added to preserve shape
61137           //     / \
61138           //    /   b ---- e      way `b,e` moved here:
61139           //   /     \
61140           //  a       c
61141           //
61142           //
61143
61144
61145           function replaceMovedVertex(nodeId, wayId, graph, delta) {
61146             var way = graph.entity(wayId);
61147             var moved = graph.entity(nodeId);
61148             var movedIndex = way.nodes.indexOf(nodeId);
61149             var len, prevIndex, nextIndex;
61150
61151             if (way.isClosed()) {
61152               len = way.nodes.length - 1;
61153               prevIndex = (movedIndex + len - 1) % len;
61154               nextIndex = (movedIndex + len + 1) % len;
61155             } else {
61156               len = way.nodes.length;
61157               prevIndex = movedIndex - 1;
61158               nextIndex = movedIndex + 1;
61159             }
61160
61161             var prev = graph.hasEntity(way.nodes[prevIndex]);
61162             var next = graph.hasEntity(way.nodes[nextIndex]); // Don't add orig vertex at endpoint..
61163
61164             if (!prev || !next) return graph;
61165             var key = wayId + '_' + nodeId;
61166             var orig = cache.replacedVertex[key];
61167
61168             if (!orig) {
61169               orig = osmNode();
61170               cache.replacedVertex[key] = orig;
61171               cache.startLoc[orig.id] = cache.startLoc[nodeId];
61172             }
61173
61174             var start, end;
61175
61176             if (delta) {
61177               start = projection(cache.startLoc[nodeId]);
61178               end = projection.invert(geoVecAdd(start, delta));
61179             } else {
61180               end = cache.startLoc[nodeId];
61181             }
61182
61183             orig = orig.move(end);
61184             var angle = Math.abs(geoAngle(orig, prev, projection) - geoAngle(orig, next, projection)) * 180 / Math.PI; // Don't add orig vertex if it would just make a straight line..
61185
61186             if (angle > 175 && angle < 185) return graph; // moving forward or backward along way?
61187
61188             var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection);
61189             var p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection);
61190             var d1 = geoPathLength(p1);
61191             var d2 = geoPathLength(p2);
61192             var insertAt = d1 <= d2 ? movedIndex : nextIndex; // moving around closed loop?
61193
61194             if (way.isClosed() && insertAt === 0) insertAt = len;
61195             way = way.addNode(orig.id, insertAt);
61196             return graph.replace(orig).replace(way);
61197           } // Remove duplicate vertex that might have been added by
61198           // replaceMovedVertex.  This is done after the unzorro checks.
61199
61200
61201           function removeDuplicateVertices(wayId, graph) {
61202             var way = graph.entity(wayId);
61203             var epsilon = 1e-6;
61204             var prev, curr;
61205
61206             function isInteresting(node, graph) {
61207               return graph.parentWays(node).length > 1 || graph.parentRelations(node).length || node.hasInterestingTags();
61208             }
61209
61210             for (var i = 0; i < way.nodes.length; i++) {
61211               curr = graph.entity(way.nodes[i]);
61212
61213               if (prev && curr && geoVecEqual(prev.loc, curr.loc, epsilon)) {
61214                 if (!isInteresting(prev, graph)) {
61215                   way = way.removeNode(prev.id);
61216                   graph = graph.replace(way).remove(prev);
61217                 } else if (!isInteresting(curr, graph)) {
61218                   way = way.removeNode(curr.id);
61219                   graph = graph.replace(way).remove(curr);
61220                 }
61221               }
61222
61223               prev = curr;
61224             }
61225
61226             return graph;
61227           } // Reorder nodes around intersections that have moved..
61228           //
61229           //  Start:                way1.nodes: b,e         (moving)
61230           //  a - b - c ----- d     way2.nodes: a,b,c,d     (static)
61231           //      |                 vertex: b
61232           //      e                 isEP1: true,  isEP2, false
61233           //
61234           //  way1 `b,e` moved here:
61235           //  a ----- c = b - d
61236           //              |
61237           //              e
61238           //
61239           //  reorder nodes         way1.nodes: b,e
61240           //  a ----- c - b - d     way2.nodes: a,c,b,d
61241           //              |
61242           //              e
61243           //
61244
61245
61246           function unZorroIntersection(intersection, graph) {
61247             var vertex = graph.entity(intersection.nodeId);
61248             var way1 = graph.entity(intersection.movedId);
61249             var way2 = graph.entity(intersection.unmovedId);
61250             var isEP1 = intersection.movedIsEP;
61251             var isEP2 = intersection.unmovedIsEP; // don't move the vertex if it is the endpoint of both ways.
61252
61253             if (isEP1 && isEP2) return graph;
61254             var nodes1 = graph.childNodes(way1).filter(function (n) {
61255               return n !== vertex;
61256             });
61257             var nodes2 = graph.childNodes(way2).filter(function (n) {
61258               return n !== vertex;
61259             });
61260             if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
61261             if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
61262             var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection);
61263             var edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection);
61264             var loc; // snap vertex to nearest edge (or some point between them)..
61265
61266             if (!isEP1 && !isEP2) {
61267               var epsilon = 1e-6,
61268                   maxIter = 10;
61269
61270               for (var i = 0; i < maxIter; i++) {
61271                 loc = geoVecInterp(edge1.loc, edge2.loc, 0.5);
61272                 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
61273                 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
61274                 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
61275               }
61276             } else if (!isEP1) {
61277               loc = edge1.loc;
61278             } else {
61279               loc = edge2.loc;
61280             }
61281
61282             graph = graph.replace(vertex.move(loc)); // if zorro happened, reorder nodes..
61283
61284             if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
61285               way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
61286               graph = graph.replace(way1);
61287             }
61288
61289             if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
61290               way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
61291               graph = graph.replace(way2);
61292             }
61293
61294             return graph;
61295           }
61296
61297           function cleanupIntersections(graph) {
61298             for (var i = 0; i < cache.intersections.length; i++) {
61299               var obj = cache.intersections[i];
61300               graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, _delta);
61301               graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
61302               graph = unZorroIntersection(obj, graph);
61303               graph = removeDuplicateVertices(obj.movedId, graph);
61304               graph = removeDuplicateVertices(obj.unmovedId, graph);
61305             }
61306
61307             return graph;
61308           } // check if moving way endpoint can cross an unmoved way, if so limit delta..
61309
61310
61311           function limitDelta(graph) {
61312             function moveNode(loc) {
61313               return geoVecAdd(projection(loc), _delta);
61314             }
61315
61316             for (var i = 0; i < cache.intersections.length; i++) {
61317               var obj = cache.intersections[i]; // Don't limit movement if this is vertex joins 2 endpoints..
61318
61319               if (obj.movedIsEP && obj.unmovedIsEP) continue; // Don't limit movement if this vertex is not an endpoint anyway..
61320
61321               if (!obj.movedIsEP) continue;
61322               var node = graph.entity(obj.nodeId);
61323               var start = projection(node.loc);
61324               var end = geoVecAdd(start, _delta);
61325               var movedNodes = graph.childNodes(graph.entity(obj.movedId));
61326               var movedPath = movedNodes.map(function (n) {
61327                 return moveNode(n.loc);
61328               });
61329               var unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId));
61330               var unmovedPath = unmovedNodes.map(function (n) {
61331                 return projection(n.loc);
61332               });
61333               var hits = geoPathIntersections(movedPath, unmovedPath);
61334
61335               for (var j = 0; i < hits.length; i++) {
61336                 if (geoVecEqual(hits[j], end)) continue;
61337                 var edge = geoChooseEdge(unmovedNodes, end, projection);
61338                 _delta = geoVecSubtract(projection(edge.loc), start);
61339               }
61340             }
61341           }
61342
61343           var action = function action(graph) {
61344             if (_delta[0] === 0 && _delta[1] === 0) return graph;
61345             setupCache(graph);
61346
61347             if (cache.intersections.length) {
61348               limitDelta(graph);
61349             }
61350
61351             for (var i = 0; i < cache.nodes.length; i++) {
61352               var node = graph.entity(cache.nodes[i]);
61353               var start = projection(node.loc);
61354               var end = geoVecAdd(start, _delta);
61355               graph = graph.replace(node.move(projection.invert(end)));
61356             }
61357
61358             if (cache.intersections.length) {
61359               graph = cleanupIntersections(graph);
61360             }
61361
61362             return graph;
61363           };
61364
61365           action.delta = function () {
61366             return _delta;
61367           };
61368
61369           return action;
61370         }
61371
61372         function actionMoveMember(relationId, fromIndex, toIndex) {
61373           return function (graph) {
61374             return graph.replace(graph.entity(relationId).moveMember(fromIndex, toIndex));
61375           };
61376         }
61377
61378         function actionMoveNode(nodeID, toLoc) {
61379           var action = function action(graph, t) {
61380             if (t === null || !isFinite(t)) t = 1;
61381             t = Math.min(Math.max(+t, 0), 1);
61382             var node = graph.entity(nodeID);
61383             return graph.replace(node.move(geoVecInterp(node.loc, toLoc, t)));
61384           };
61385
61386           action.transitionable = true;
61387           return action;
61388         }
61389
61390         function actionNoop() {
61391           return function (graph) {
61392             return graph;
61393           };
61394         }
61395
61396         function actionOrthogonalize(wayID, projection, vertexID, degThresh, ep) {
61397           var epsilon = ep || 1e-4;
61398           var threshold = degThresh || 13; // degrees within right or straight to alter
61399           // We test normalized dot products so we can compare as cos(angle)
61400
61401           var lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180);
61402           var upperThreshold = Math.cos(threshold * Math.PI / 180);
61403
61404           var action = function action(graph, t) {
61405             if (t === null || !isFinite(t)) t = 1;
61406             t = Math.min(Math.max(+t, 0), 1);
61407             var way = graph.entity(wayID);
61408             way = way.removeNode(''); // sanity check - remove any consecutive duplicates
61409
61410             if (way.tags.nonsquare) {
61411               var tags = Object.assign({}, way.tags); // since we're squaring, remove indication that this is physically unsquare
61412
61413               delete tags.nonsquare;
61414               way = way.update({
61415                 tags: tags
61416               });
61417             }
61418
61419             graph = graph.replace(way);
61420             var isClosed = way.isClosed();
61421             var nodes = graph.childNodes(way).slice(); // shallow copy
61422
61423             if (isClosed) nodes.pop();
61424
61425             if (vertexID !== undefined) {
61426               nodes = nodeSubset(nodes, vertexID, isClosed);
61427               if (nodes.length !== 3) return graph;
61428             } // note: all geometry functions here use the unclosed node/point/coord list
61429
61430
61431             var nodeCount = {};
61432             var points = [];
61433             var corner = {
61434               i: 0,
61435               dotp: 1
61436             };
61437             var node, point, loc, score, motions, i, j;
61438
61439             for (i = 0; i < nodes.length; i++) {
61440               node = nodes[i];
61441               nodeCount[node.id] = (nodeCount[node.id] || 0) + 1;
61442               points.push({
61443                 id: node.id,
61444                 coord: projection(node.loc)
61445               });
61446             }
61447
61448             if (points.length === 3) {
61449               // move only one vertex for right triangle
61450               for (i = 0; i < 1000; i++) {
61451                 motions = points.map(calcMotion);
61452                 points[corner.i].coord = geoVecAdd(points[corner.i].coord, motions[corner.i]);
61453                 score = corner.dotp;
61454
61455                 if (score < epsilon) {
61456                   break;
61457                 }
61458               }
61459
61460               node = graph.entity(nodes[corner.i].id);
61461               loc = projection.invert(points[corner.i].coord);
61462               graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
61463             } else {
61464               var straights = [];
61465               var simplified = []; // Remove points from nearly straight sections..
61466               // This produces a simplified shape to orthogonalize
61467
61468               for (i = 0; i < points.length; i++) {
61469                 point = points[i];
61470                 var dotp = 0;
61471
61472                 if (isClosed || i > 0 && i < points.length - 1) {
61473                   var a = points[(i - 1 + points.length) % points.length];
61474                   var b = points[(i + 1) % points.length];
61475                   dotp = Math.abs(geoOrthoNormalizedDotProduct(a.coord, b.coord, point.coord));
61476                 }
61477
61478                 if (dotp > upperThreshold) {
61479                   straights.push(point);
61480                 } else {
61481                   simplified.push(point);
61482                 }
61483               } // Orthogonalize the simplified shape
61484
61485
61486               var bestPoints = clonePoints(simplified);
61487               var originalPoints = clonePoints(simplified);
61488               score = Infinity;
61489
61490               for (i = 0; i < 1000; i++) {
61491                 motions = simplified.map(calcMotion);
61492
61493                 for (j = 0; j < motions.length; j++) {
61494                   simplified[j].coord = geoVecAdd(simplified[j].coord, motions[j]);
61495                 }
61496
61497                 var newScore = geoOrthoCalcScore(simplified, isClosed, epsilon, threshold);
61498
61499                 if (newScore < score) {
61500                   bestPoints = clonePoints(simplified);
61501                   score = newScore;
61502                 }
61503
61504                 if (score < epsilon) {
61505                   break;
61506                 }
61507               }
61508
61509               var bestCoords = bestPoints.map(function (p) {
61510                 return p.coord;
61511               });
61512               if (isClosed) bestCoords.push(bestCoords[0]); // move the nodes that should move
61513
61514               for (i = 0; i < bestPoints.length; i++) {
61515                 point = bestPoints[i];
61516
61517                 if (!geoVecEqual(originalPoints[i].coord, point.coord)) {
61518                   node = graph.entity(point.id);
61519                   loc = projection.invert(point.coord);
61520                   graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
61521                 }
61522               } // move the nodes along straight segments
61523
61524
61525               for (i = 0; i < straights.length; i++) {
61526                 point = straights[i];
61527                 if (nodeCount[point.id] > 1) continue; // skip self-intersections
61528
61529                 node = graph.entity(point.id);
61530
61531                 if (t === 1 && graph.parentWays(node).length === 1 && graph.parentRelations(node).length === 0 && !node.hasInterestingTags()) {
61532                   // remove uninteresting points..
61533                   graph = actionDeleteNode(node.id)(graph);
61534                 } else {
61535                   // move interesting points to the nearest edge..
61536                   var choice = geoVecProject(point.coord, bestCoords);
61537
61538                   if (choice) {
61539                     loc = projection.invert(choice.target);
61540                     graph = graph.replace(node.move(geoVecInterp(node.loc, loc, t)));
61541                   }
61542                 }
61543               }
61544             }
61545
61546             return graph;
61547
61548             function clonePoints(array) {
61549               return array.map(function (p) {
61550                 return {
61551                   id: p.id,
61552                   coord: [p.coord[0], p.coord[1]]
61553                 };
61554               });
61555             }
61556
61557             function calcMotion(point, i, array) {
61558               // don't try to move the endpoints of a non-closed way.
61559               if (!isClosed && (i === 0 || i === array.length - 1)) return [0, 0]; // don't try to move a node that appears more than once (self intersection)
61560
61561               if (nodeCount[array[i].id] > 1) return [0, 0];
61562               var a = array[(i - 1 + array.length) % array.length].coord;
61563               var origin = point.coord;
61564               var b = array[(i + 1) % array.length].coord;
61565               var p = geoVecSubtract(a, origin);
61566               var q = geoVecSubtract(b, origin);
61567               var scale = 2 * Math.min(geoVecLength(p), geoVecLength(q));
61568               p = geoVecNormalize(p);
61569               q = geoVecNormalize(q);
61570               var dotp = p[0] * q[0] + p[1] * q[1];
61571               var val = Math.abs(dotp);
61572
61573               if (val < lowerThreshold) {
61574                 // nearly orthogonal
61575                 corner.i = i;
61576                 corner.dotp = val;
61577                 var vec = geoVecNormalize(geoVecAdd(p, q));
61578                 return geoVecScale(vec, 0.1 * dotp * scale);
61579               }
61580
61581               return [0, 0]; // do nothing
61582             }
61583           }; // if we are only orthogonalizing one vertex,
61584           // get that vertex and the previous and next
61585
61586
61587           function nodeSubset(nodes, vertexID, isClosed) {
61588             var first = isClosed ? 0 : 1;
61589             var last = isClosed ? nodes.length : nodes.length - 1;
61590
61591             for (var i = first; i < last; i++) {
61592               if (nodes[i].id === vertexID) {
61593                 return [nodes[(i - 1 + nodes.length) % nodes.length], nodes[i], nodes[(i + 1) % nodes.length]];
61594               }
61595             }
61596
61597             return [];
61598           }
61599
61600           action.disabled = function (graph) {
61601             var way = graph.entity(wayID);
61602             way = way.removeNode(''); // sanity check - remove any consecutive duplicates
61603
61604             graph = graph.replace(way);
61605             var isClosed = way.isClosed();
61606             var nodes = graph.childNodes(way).slice(); // shallow copy
61607
61608             if (isClosed) nodes.pop();
61609             var allowStraightAngles = false;
61610
61611             if (vertexID !== undefined) {
61612               allowStraightAngles = true;
61613               nodes = nodeSubset(nodes, vertexID, isClosed);
61614               if (nodes.length !== 3) return 'end_vertex';
61615             }
61616
61617             var coords = nodes.map(function (n) {
61618               return projection(n.loc);
61619             });
61620             var score = geoOrthoCanOrthogonalize(coords, isClosed, epsilon, threshold, allowStraightAngles);
61621
61622             if (score === null) {
61623               return 'not_squarish';
61624             } else if (score === 0) {
61625               return 'square_enough';
61626             } else {
61627               return false;
61628             }
61629           };
61630
61631           action.transitionable = true;
61632           return action;
61633         }
61634
61635         //
61636         // `turn` must be an `osmTurn` object
61637         // see osm/intersection.js, pathToTurn()
61638         //
61639         // This specifies a restriction of type `restriction` when traveling from
61640         // `turn.from.way` toward `turn.to.way` via `turn.via.node` OR `turn.via.ways`.
61641         // (The action does not check that these entities form a valid intersection.)
61642         //
61643         // From, to, and via ways should be split before calling this action.
61644         // (old versions of the code would split the ways here, but we no longer do it)
61645         //
61646         // For testing convenience, accepts a restrictionID to assign to the new
61647         // relation. Normally, this will be undefined and the relation will
61648         // automatically be assigned a new ID.
61649         //
61650
61651         function actionRestrictTurn(turn, restrictionType, restrictionID) {
61652           return function (graph) {
61653             var fromWay = graph.entity(turn.from.way);
61654             var toWay = graph.entity(turn.to.way);
61655             var viaNode = turn.via.node && graph.entity(turn.via.node);
61656             var viaWays = turn.via.ways && turn.via.ways.map(function (id) {
61657               return graph.entity(id);
61658             });
61659             var members = [];
61660             members.push({
61661               id: fromWay.id,
61662               type: 'way',
61663               role: 'from'
61664             });
61665
61666             if (viaNode) {
61667               members.push({
61668                 id: viaNode.id,
61669                 type: 'node',
61670                 role: 'via'
61671               });
61672             } else if (viaWays) {
61673               viaWays.forEach(function (viaWay) {
61674                 members.push({
61675                   id: viaWay.id,
61676                   type: 'way',
61677                   role: 'via'
61678                 });
61679               });
61680             }
61681
61682             members.push({
61683               id: toWay.id,
61684               type: 'way',
61685               role: 'to'
61686             });
61687             return graph.replace(osmRelation({
61688               id: restrictionID,
61689               tags: {
61690                 type: 'restriction',
61691                 restriction: restrictionType
61692               },
61693               members: members
61694             }));
61695           };
61696         }
61697
61698         function actionRevert(id) {
61699           var action = function action(graph) {
61700             var entity = graph.hasEntity(id),
61701                 base = graph.base().entities[id];
61702
61703             if (entity && !base) {
61704               // entity will be removed..
61705               if (entity.type === 'node') {
61706                 graph.parentWays(entity).forEach(function (parent) {
61707                   parent = parent.removeNode(id);
61708                   graph = graph.replace(parent);
61709
61710                   if (parent.isDegenerate()) {
61711                     graph = actionDeleteWay(parent.id)(graph);
61712                   }
61713                 });
61714               }
61715
61716               graph.parentRelations(entity).forEach(function (parent) {
61717                 parent = parent.removeMembersWithID(id);
61718                 graph = graph.replace(parent);
61719
61720                 if (parent.isDegenerate()) {
61721                   graph = actionDeleteRelation(parent.id)(graph);
61722                 }
61723               });
61724             }
61725
61726             return graph.revert(id);
61727           };
61728
61729           return action;
61730         }
61731
61732         function actionRotate(rotateIds, pivot, angle, projection) {
61733           var action = function action(graph) {
61734             return graph.update(function (graph) {
61735               utilGetAllNodes(rotateIds, graph).forEach(function (node) {
61736                 var point = geoRotate([projection(node.loc)], angle, pivot)[0];
61737                 graph = graph.replace(node.move(projection.invert(point)));
61738               });
61739             });
61740           };
61741
61742           return action;
61743         }
61744
61745         function actionScale(ids, pivotLoc, scaleFactor, projection) {
61746           return function (graph) {
61747             return graph.update(function (graph) {
61748               var point, radial;
61749               utilGetAllNodes(ids, graph).forEach(function (node) {
61750                 point = projection(node.loc);
61751                 radial = [point[0] - pivotLoc[0], point[1] - pivotLoc[1]];
61752                 point = [pivotLoc[0] + scaleFactor * radial[0], pivotLoc[1] + scaleFactor * radial[1]];
61753                 graph = graph.replace(node.move(projection.invert(point)));
61754               });
61755             });
61756           };
61757         }
61758
61759         /* Align nodes along their common axis */
61760
61761         function actionStraightenNodes(nodeIDs, projection) {
61762           function positionAlongWay(a, o, b) {
61763             return geoVecDot(a, b, o) / geoVecDot(b, b, o);
61764           } // returns the endpoints of the long axis of symmetry of the `points` bounding rect
61765
61766
61767           function getEndpoints(points) {
61768             var ssr = geoGetSmallestSurroundingRectangle(points); // Choose line pq = axis of symmetry.
61769             // The shape's surrounding rectangle has 2 axes of symmetry.
61770             // Snap points to the long axis
61771
61772             var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2];
61773             var q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2];
61774             var p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2];
61775             var q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2];
61776             var isLong = geoVecLength(p1, q1) > geoVecLength(p2, q2);
61777
61778             if (isLong) {
61779               return [p1, q1];
61780             }
61781
61782             return [p2, q2];
61783           }
61784
61785           var action = function action(graph, t) {
61786             if (t === null || !isFinite(t)) t = 1;
61787             t = Math.min(Math.max(+t, 0), 1);
61788             var nodes = nodeIDs.map(function (id) {
61789               return graph.entity(id);
61790             });
61791             var points = nodes.map(function (n) {
61792               return projection(n.loc);
61793             });
61794             var endpoints = getEndpoints(points);
61795             var startPoint = endpoints[0];
61796             var endPoint = endpoints[1]; // Move points onto the line connecting the endpoints
61797
61798             for (var i = 0; i < points.length; i++) {
61799               var node = nodes[i];
61800               var point = points[i];
61801               var u = positionAlongWay(point, startPoint, endPoint);
61802               var point2 = geoVecInterp(startPoint, endPoint, u);
61803               var loc2 = projection.invert(point2);
61804               graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t)));
61805             }
61806
61807             return graph;
61808           };
61809
61810           action.disabled = function (graph) {
61811             var nodes = nodeIDs.map(function (id) {
61812               return graph.entity(id);
61813             });
61814             var points = nodes.map(function (n) {
61815               return projection(n.loc);
61816             });
61817             var endpoints = getEndpoints(points);
61818             var startPoint = endpoints[0];
61819             var endPoint = endpoints[1];
61820             var maxDistance = 0;
61821
61822             for (var i = 0; i < points.length; i++) {
61823               var point = points[i];
61824               var u = positionAlongWay(point, startPoint, endPoint);
61825               var p = geoVecInterp(startPoint, endPoint, u);
61826               var dist = geoVecLength(p, point);
61827
61828               if (!isNaN(dist) && dist > maxDistance) {
61829                 maxDistance = dist;
61830               }
61831             }
61832
61833             if (maxDistance < 0.0001) {
61834               return 'straight_enough';
61835             }
61836           };
61837
61838           action.transitionable = true;
61839           return action;
61840         }
61841
61842         /*
61843          * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
61844          */
61845
61846         function actionStraightenWay(selectedIDs, projection) {
61847           function positionAlongWay(a, o, b) {
61848             return geoVecDot(a, b, o) / geoVecDot(b, b, o);
61849           } // Return all selected ways as a continuous, ordered array of nodes
61850
61851
61852           function allNodes(graph) {
61853             var nodes = [];
61854             var startNodes = [];
61855             var endNodes = [];
61856             var remainingWays = [];
61857             var selectedWays = selectedIDs.filter(function (w) {
61858               return graph.entity(w).type === 'way';
61859             });
61860             var selectedNodes = selectedIDs.filter(function (n) {
61861               return graph.entity(n).type === 'node';
61862             });
61863
61864             for (var i = 0; i < selectedWays.length; i++) {
61865               var way = graph.entity(selectedWays[i]);
61866               nodes = way.nodes.slice(0);
61867               remainingWays.push(nodes);
61868               startNodes.push(nodes[0]);
61869               endNodes.push(nodes[nodes.length - 1]);
61870             } // Remove duplicate end/startNodes (duplicate nodes cannot be at the line end,
61871             //   and need to be removed so currNode difference calculation below works)
61872             // i.e. ["n-1", "n-1", "n-2"] => ["n-2"]
61873
61874
61875             startNodes = startNodes.filter(function (n) {
61876               return startNodes.indexOf(n) === startNodes.lastIndexOf(n);
61877             });
61878             endNodes = endNodes.filter(function (n) {
61879               return endNodes.indexOf(n) === endNodes.lastIndexOf(n);
61880             }); // Choose the initial endpoint to start from
61881
61882             var currNode = utilArrayDifference(startNodes, endNodes).concat(utilArrayDifference(endNodes, startNodes))[0];
61883             var nextWay = [];
61884             nodes = []; // Create nested function outside of loop to avoid "function in loop" lint error
61885
61886             var getNextWay = function getNextWay(currNode, remainingWays) {
61887               return remainingWays.filter(function (way) {
61888                 return way[0] === currNode || way[way.length - 1] === currNode;
61889               })[0];
61890             }; // Add nodes to end of nodes array, until all ways are added
61891
61892
61893             while (remainingWays.length) {
61894               nextWay = getNextWay(currNode, remainingWays);
61895               remainingWays = utilArrayDifference(remainingWays, [nextWay]);
61896
61897               if (nextWay[0] !== currNode) {
61898                 nextWay.reverse();
61899               }
61900
61901               nodes = nodes.concat(nextWay);
61902               currNode = nodes[nodes.length - 1];
61903             } // If user selected 2 nodes to straighten between, then slice nodes array to those nodes
61904
61905
61906             if (selectedNodes.length === 2) {
61907               var startNodeIdx = nodes.indexOf(selectedNodes[0]);
61908               var endNodeIdx = nodes.indexOf(selectedNodes[1]);
61909               var sortedStartEnd = [startNodeIdx, endNodeIdx];
61910               sortedStartEnd.sort(function (a, b) {
61911                 return a - b;
61912               });
61913               nodes = nodes.slice(sortedStartEnd[0], sortedStartEnd[1] + 1);
61914             }
61915
61916             return nodes.map(function (n) {
61917               return graph.entity(n);
61918             });
61919           }
61920
61921           function shouldKeepNode(node, graph) {
61922             return graph.parentWays(node).length > 1 || graph.parentRelations(node).length || node.hasInterestingTags();
61923           }
61924
61925           var action = function action(graph, t) {
61926             if (t === null || !isFinite(t)) t = 1;
61927             t = Math.min(Math.max(+t, 0), 1);
61928             var nodes = allNodes(graph);
61929             var points = nodes.map(function (n) {
61930               return projection(n.loc);
61931             });
61932             var startPoint = points[0];
61933             var endPoint = points[points.length - 1];
61934             var toDelete = [];
61935             var i;
61936
61937             for (i = 1; i < points.length - 1; i++) {
61938               var node = nodes[i];
61939               var point = points[i];
61940
61941               if (t < 1 || shouldKeepNode(node, graph)) {
61942                 var u = positionAlongWay(point, startPoint, endPoint);
61943                 var p = geoVecInterp(startPoint, endPoint, u);
61944                 var loc2 = projection.invert(p);
61945                 graph = graph.replace(node.move(geoVecInterp(node.loc, loc2, t)));
61946               } else {
61947                 // safe to delete
61948                 if (toDelete.indexOf(node) === -1) {
61949                   toDelete.push(node);
61950                 }
61951               }
61952             }
61953
61954             for (i = 0; i < toDelete.length; i++) {
61955               graph = actionDeleteNode(toDelete[i].id)(graph);
61956             }
61957
61958             return graph;
61959           };
61960
61961           action.disabled = function (graph) {
61962             // check way isn't too bendy
61963             var nodes = allNodes(graph);
61964             var points = nodes.map(function (n) {
61965               return projection(n.loc);
61966             });
61967             var startPoint = points[0];
61968             var endPoint = points[points.length - 1];
61969             var threshold = 0.2 * geoVecLength(startPoint, endPoint);
61970             var i;
61971
61972             if (threshold === 0) {
61973               return 'too_bendy';
61974             }
61975
61976             var maxDistance = 0;
61977
61978             for (i = 1; i < points.length - 1; i++) {
61979               var point = points[i];
61980               var u = positionAlongWay(point, startPoint, endPoint);
61981               var p = geoVecInterp(startPoint, endPoint, u);
61982               var dist = geoVecLength(p, point); // to bendy if point is off by 20% of total start/end distance in projected space
61983
61984               if (isNaN(dist) || dist > threshold) {
61985                 return 'too_bendy';
61986               } else if (dist > maxDistance) {
61987                 maxDistance = dist;
61988               }
61989             }
61990
61991             var keepingAllNodes = nodes.every(function (node, i) {
61992               return i === 0 || i === nodes.length - 1 || shouldKeepNode(node, graph);
61993             });
61994
61995             if (maxDistance < 0.0001 && // Allow straightening even if already straight in order to remove extraneous nodes
61996             keepingAllNodes) {
61997               return 'straight_enough';
61998             }
61999           };
62000
62001           action.transitionable = true;
62002           return action;
62003         }
62004
62005         //
62006         // `turn` must be an `osmTurn` object with a `restrictionID` property.
62007         // see osm/intersection.js, pathToTurn()
62008         //
62009
62010         function actionUnrestrictTurn(turn) {
62011           return function (graph) {
62012             return actionDeleteRelation(turn.restrictionID)(graph);
62013           };
62014         }
62015
62016         /* Reflect the given area around its axis of symmetry */
62017
62018         function actionReflect(reflectIds, projection) {
62019           var _useLongAxis = true;
62020
62021           var action = function action(graph, t) {
62022             if (t === null || !isFinite(t)) t = 1;
62023             t = Math.min(Math.max(+t, 0), 1);
62024             var nodes = utilGetAllNodes(reflectIds, graph);
62025             var points = nodes.map(function (n) {
62026               return projection(n.loc);
62027             });
62028             var ssr = geoGetSmallestSurroundingRectangle(points); // Choose line pq = axis of symmetry.
62029             // The shape's surrounding rectangle has 2 axes of symmetry.
62030             // Reflect across the longer axis by default.
62031
62032             var p1 = [(ssr.poly[0][0] + ssr.poly[1][0]) / 2, (ssr.poly[0][1] + ssr.poly[1][1]) / 2];
62033             var q1 = [(ssr.poly[2][0] + ssr.poly[3][0]) / 2, (ssr.poly[2][1] + ssr.poly[3][1]) / 2];
62034             var p2 = [(ssr.poly[3][0] + ssr.poly[4][0]) / 2, (ssr.poly[3][1] + ssr.poly[4][1]) / 2];
62035             var q2 = [(ssr.poly[1][0] + ssr.poly[2][0]) / 2, (ssr.poly[1][1] + ssr.poly[2][1]) / 2];
62036             var p, q;
62037             var isLong = geoVecLength(p1, q1) > geoVecLength(p2, q2);
62038
62039             if (_useLongAxis && isLong || !_useLongAxis && !isLong) {
62040               p = p1;
62041               q = q1;
62042             } else {
62043               p = p2;
62044               q = q2;
62045             } // reflect c across pq
62046             // http://math.stackexchange.com/questions/65503/point-reflection-over-a-line
62047
62048
62049             var dx = q[0] - p[0];
62050             var dy = q[1] - p[1];
62051             var a = (dx * dx - dy * dy) / (dx * dx + dy * dy);
62052             var b = 2 * dx * dy / (dx * dx + dy * dy);
62053
62054             for (var i = 0; i < nodes.length; i++) {
62055               var node = nodes[i];
62056               var c = projection(node.loc);
62057               var c2 = [a * (c[0] - p[0]) + b * (c[1] - p[1]) + p[0], b * (c[0] - p[0]) - a * (c[1] - p[1]) + p[1]];
62058               var loc2 = projection.invert(c2);
62059               node = node.move(geoVecInterp(node.loc, loc2, t));
62060               graph = graph.replace(node);
62061             }
62062
62063             return graph;
62064           };
62065
62066           action.useLongAxis = function (val) {
62067             if (!arguments.length) return _useLongAxis;
62068             _useLongAxis = val;
62069             return action;
62070           };
62071
62072           action.transitionable = true;
62073           return action;
62074         }
62075
62076         function actionUpgradeTags(entityId, oldTags, replaceTags) {
62077           return function (graph) {
62078             var entity = graph.entity(entityId);
62079             var tags = Object.assign({}, entity.tags); // shallow copy
62080
62081             var transferValue;
62082             var semiIndex;
62083
62084             for (var oldTagKey in oldTags) {
62085               if (!(oldTagKey in tags)) continue; // wildcard match
62086
62087               if (oldTags[oldTagKey] === '*') {
62088                 // note the value since we might need to transfer it
62089                 transferValue = tags[oldTagKey];
62090                 delete tags[oldTagKey]; // exact match
62091               } else if (oldTags[oldTagKey] === tags[oldTagKey]) {
62092                 delete tags[oldTagKey]; // match is within semicolon-delimited values
62093               } else {
62094                 var vals = tags[oldTagKey].split(';').filter(Boolean);
62095                 var oldIndex = vals.indexOf(oldTags[oldTagKey]);
62096
62097                 if (vals.length === 1 || oldIndex === -1) {
62098                   delete tags[oldTagKey];
62099                 } else {
62100                   if (replaceTags && replaceTags[oldTagKey]) {
62101                     // replacing a value within a semicolon-delimited value, note the index
62102                     semiIndex = oldIndex;
62103                   }
62104
62105                   vals.splice(oldIndex, 1);
62106                   tags[oldTagKey] = vals.join(';');
62107                 }
62108               }
62109             }
62110
62111             if (replaceTags) {
62112               for (var replaceKey in replaceTags) {
62113                 var replaceValue = replaceTags[replaceKey];
62114
62115                 if (replaceValue === '*') {
62116                   if (tags[replaceKey] && tags[replaceKey] !== 'no') {
62117                     // allow any pre-existing value except `no` (troll tag)
62118                     continue;
62119                   } else {
62120                     // otherwise assume `yes` is okay
62121                     tags[replaceKey] = 'yes';
62122                   }
62123                 } else if (replaceValue === '$1') {
62124                   tags[replaceKey] = transferValue;
62125                 } else {
62126                   if (tags[replaceKey] && oldTags[replaceKey] && semiIndex !== undefined) {
62127                     // don't override preexisting values
62128                     var existingVals = tags[replaceKey].split(';').filter(Boolean);
62129
62130                     if (existingVals.indexOf(replaceValue) === -1) {
62131                       existingVals.splice(semiIndex, 0, replaceValue);
62132                       tags[replaceKey] = existingVals.join(';');
62133                     }
62134                   } else {
62135                     tags[replaceKey] = replaceValue;
62136                   }
62137                 }
62138               }
62139             }
62140
62141             return graph.replace(entity.update({
62142               tags: tags
62143             }));
62144           };
62145         }
62146
62147         function behaviorEdit(context) {
62148           function behavior() {
62149             context.map().minzoom(context.minEditableZoom());
62150           }
62151
62152           behavior.off = function () {
62153             context.map().minzoom(0);
62154           };
62155
62156           return behavior;
62157         }
62158
62159         /*
62160            The hover behavior adds the `.hover` class on pointerover to all elements to which
62161            the identical datum is bound, and removes it on pointerout.
62162
62163            The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
62164            representation may consist of several elements scattered throughout the DOM hierarchy.
62165            Only one of these elements can have the :hover pseudo-class, but all of them will
62166            have the .hover class.
62167          */
62168
62169         function behaviorHover(context) {
62170           var dispatch = dispatch$8('hover');
62171
62172           var _selection = select(null);
62173
62174           var _newNodeId = null;
62175           var _initialNodeID = null;
62176
62177           var _altDisables;
62178
62179           var _ignoreVertex;
62180
62181           var _targets = []; // use pointer events on supported platforms; fallback to mouse events
62182
62183           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
62184
62185           function keydown(d3_event) {
62186             if (_altDisables && d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
62187               _selection.selectAll('.hover').classed('hover-suppressed', true).classed('hover', false);
62188
62189               _selection.classed('hover-disabled', true);
62190
62191               dispatch.call('hover', this, null);
62192             }
62193           }
62194
62195           function keyup(d3_event) {
62196             if (_altDisables && d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
62197               _selection.selectAll('.hover-suppressed').classed('hover-suppressed', false).classed('hover', true);
62198
62199               _selection.classed('hover-disabled', false);
62200
62201               dispatch.call('hover', this, _targets);
62202             }
62203           }
62204
62205           function behavior(selection) {
62206             _selection = selection;
62207             _targets = [];
62208
62209             if (_initialNodeID) {
62210               _newNodeId = _initialNodeID;
62211               _initialNodeID = null;
62212             } else {
62213               _newNodeId = null;
62214             }
62215
62216             _selection.on(_pointerPrefix + 'over.hover', pointerover).on(_pointerPrefix + 'out.hover', pointerout) // treat pointerdown as pointerover for touch devices
62217             .on(_pointerPrefix + 'down.hover', pointerover);
62218
62219             select(window).on(_pointerPrefix + 'up.hover pointercancel.hover', pointerout, true).on('keydown.hover', keydown).on('keyup.hover', keyup);
62220
62221             function eventTarget(d3_event) {
62222               var datum = d3_event.target && d3_event.target.__data__;
62223               if (_typeof(datum) !== 'object') return null;
62224
62225               if (!(datum instanceof osmEntity) && datum.properties && datum.properties.entity instanceof osmEntity) {
62226                 return datum.properties.entity;
62227               }
62228
62229               return datum;
62230             }
62231
62232             function pointerover(d3_event) {
62233               // ignore mouse hovers with buttons pressed unless dragging
62234               if (context.mode().id.indexOf('drag') === -1 && (!d3_event.pointerType || d3_event.pointerType === 'mouse') && d3_event.buttons) return;
62235               var target = eventTarget(d3_event);
62236
62237               if (target && _targets.indexOf(target) === -1) {
62238                 _targets.push(target);
62239
62240                 updateHover(d3_event, _targets);
62241               }
62242             }
62243
62244             function pointerout(d3_event) {
62245               var target = eventTarget(d3_event);
62246
62247               var index = _targets.indexOf(target);
62248
62249               if (index !== -1) {
62250                 _targets.splice(index);
62251
62252                 updateHover(d3_event, _targets);
62253               }
62254             }
62255
62256             function allowsVertex(d) {
62257               return d.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(d, context.graph());
62258             }
62259
62260             function modeAllowsHover(target) {
62261               var mode = context.mode();
62262
62263               if (mode.id === 'add-point') {
62264                 return mode.preset.matchGeometry('vertex') || target.type !== 'way' && target.geometry(context.graph()) !== 'vertex';
62265               }
62266
62267               return true;
62268             }
62269
62270             function updateHover(d3_event, targets) {
62271               _selection.selectAll('.hover').classed('hover', false);
62272
62273               _selection.selectAll('.hover-suppressed').classed('hover-suppressed', false);
62274
62275               var mode = context.mode();
62276
62277               if (!_newNodeId && (mode.id === 'draw-line' || mode.id === 'draw-area')) {
62278                 var node = targets.find(function (target) {
62279                   return target instanceof osmEntity && target.type === 'node';
62280                 });
62281                 _newNodeId = node && node.id;
62282               }
62283
62284               targets = targets.filter(function (datum) {
62285                 if (datum instanceof osmEntity) {
62286                   // If drawing a way, don't hover on a node that was just placed. #3974
62287                   return datum.id !== _newNodeId && (datum.type !== 'node' || !_ignoreVertex || allowsVertex(datum)) && modeAllowsHover(datum);
62288                 }
62289
62290                 return true;
62291               });
62292               var selector = '';
62293
62294               for (var i in targets) {
62295                 var datum = targets[i]; // What are we hovering over?
62296
62297                 if (datum.__featurehash__) {
62298                   // hovering custom data
62299                   selector += ', .data' + datum.__featurehash__;
62300                 } else if (datum instanceof QAItem) {
62301                   selector += ', .' + datum.service + '.itemId-' + datum.id;
62302                 } else if (datum instanceof osmNote) {
62303                   selector += ', .note-' + datum.id;
62304                 } else if (datum instanceof osmEntity) {
62305                   selector += ', .' + datum.id;
62306
62307                   if (datum.type === 'relation') {
62308                     for (var j in datum.members) {
62309                       selector += ', .' + datum.members[j].id;
62310                     }
62311                   }
62312                 }
62313               }
62314
62315               var suppressed = _altDisables && d3_event && d3_event.altKey;
62316
62317               if (selector.trim().length) {
62318                 // remove the first comma
62319                 selector = selector.slice(1);
62320
62321                 _selection.selectAll(selector).classed(suppressed ? 'hover-suppressed' : 'hover', true);
62322               }
62323
62324               dispatch.call('hover', this, !suppressed && targets);
62325             }
62326           }
62327
62328           behavior.off = function (selection) {
62329             selection.selectAll('.hover').classed('hover', false);
62330             selection.selectAll('.hover-suppressed').classed('hover-suppressed', false);
62331             selection.classed('hover-disabled', false);
62332             selection.on(_pointerPrefix + 'over.hover', null).on(_pointerPrefix + 'out.hover', null).on(_pointerPrefix + 'down.hover', null);
62333             select(window).on(_pointerPrefix + 'up.hover pointercancel.hover', null, true).on('keydown.hover', null).on('keyup.hover', null);
62334           };
62335
62336           behavior.altDisables = function (val) {
62337             if (!arguments.length) return _altDisables;
62338             _altDisables = val;
62339             return behavior;
62340           };
62341
62342           behavior.ignoreVertex = function (val) {
62343             if (!arguments.length) return _ignoreVertex;
62344             _ignoreVertex = val;
62345             return behavior;
62346           };
62347
62348           behavior.initialNodeID = function (nodeId) {
62349             _initialNodeID = nodeId;
62350             return behavior;
62351           };
62352
62353           return utilRebind(behavior, dispatch, 'on');
62354         }
62355
62356         var _disableSpace = false;
62357         var _lastSpace = null;
62358         function behaviorDraw(context) {
62359           var dispatch = dispatch$8('move', 'down', 'downcancel', 'click', 'clickWay', 'clickNode', 'undo', 'cancel', 'finish');
62360           var keybinding = utilKeybinding('draw');
62361
62362           var _hover = behaviorHover(context).altDisables(true).ignoreVertex(true).on('hover', context.ui().sidebar.hover);
62363
62364           var _edit = behaviorEdit(context);
62365
62366           var _closeTolerance = 4;
62367           var _tolerance = 12;
62368           var _mouseLeave = false;
62369           var _lastMouse = null;
62370
62371           var _lastPointerUpEvent;
62372
62373           var _downPointer; // use pointer events on supported platforms; fallback to mouse events
62374
62375
62376           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse'; // related code
62377           // - `mode/drag_node.js` `datum()`
62378
62379
62380           function datum(d3_event) {
62381             var mode = context.mode();
62382             var isNote = mode && mode.id.indexOf('note') !== -1;
62383             if (d3_event.altKey || isNote) return {};
62384             var element;
62385
62386             if (d3_event.type === 'keydown') {
62387               element = _lastMouse && _lastMouse.target;
62388             } else {
62389               element = d3_event.target;
62390             } // When drawing, snap only to touch targets..
62391             // (this excludes area fills and active drawing elements)
62392
62393
62394             var d = element.__data__;
62395             return d && d.properties && d.properties.target ? d : {};
62396           }
62397
62398           function pointerdown(d3_event) {
62399             if (_downPointer) return;
62400             var pointerLocGetter = utilFastMouse(this);
62401             _downPointer = {
62402               id: d3_event.pointerId || 'mouse',
62403               pointerLocGetter: pointerLocGetter,
62404               downTime: +new Date(),
62405               downLoc: pointerLocGetter(d3_event)
62406             };
62407             dispatch.call('down', this, d3_event, datum(d3_event));
62408           }
62409
62410           function pointerup(d3_event) {
62411             if (!_downPointer || _downPointer.id !== (d3_event.pointerId || 'mouse')) return;
62412             var downPointer = _downPointer;
62413             _downPointer = null;
62414             _lastPointerUpEvent = d3_event;
62415             if (downPointer.isCancelled) return;
62416             var t2 = +new Date();
62417             var p2 = downPointer.pointerLocGetter(d3_event);
62418             var dist = geoVecLength(downPointer.downLoc, p2);
62419
62420             if (dist < _closeTolerance || dist < _tolerance && t2 - downPointer.downTime < 500) {
62421               // Prevent a quick second click
62422               select(window).on('click.draw-block', function () {
62423                 d3_event.stopPropagation();
62424               }, true);
62425               context.map().dblclickZoomEnable(false);
62426               window.setTimeout(function () {
62427                 context.map().dblclickZoomEnable(true);
62428                 select(window).on('click.draw-block', null);
62429               }, 500);
62430               click(d3_event, p2);
62431             }
62432           }
62433
62434           function pointermove(d3_event) {
62435             if (_downPointer && _downPointer.id === (d3_event.pointerId || 'mouse') && !_downPointer.isCancelled) {
62436               var p2 = _downPointer.pointerLocGetter(d3_event);
62437
62438               var dist = geoVecLength(_downPointer.downLoc, p2);
62439
62440               if (dist >= _closeTolerance) {
62441                 _downPointer.isCancelled = true;
62442                 dispatch.call('downcancel', this);
62443               }
62444             }
62445
62446             if (d3_event.pointerType && d3_event.pointerType !== 'mouse' || d3_event.buttons || _downPointer) return; // HACK: Mobile Safari likes to send one or more `mouse` type pointermove
62447             // events immediately after non-mouse pointerup events; detect and ignore them.
62448
62449             if (_lastPointerUpEvent && _lastPointerUpEvent.pointerType !== 'mouse' && d3_event.timeStamp - _lastPointerUpEvent.timeStamp < 100) return;
62450             _lastMouse = d3_event;
62451             dispatch.call('move', this, d3_event, datum(d3_event));
62452           }
62453
62454           function pointercancel(d3_event) {
62455             if (_downPointer && _downPointer.id === (d3_event.pointerId || 'mouse')) {
62456               if (!_downPointer.isCancelled) {
62457                 dispatch.call('downcancel', this);
62458               }
62459
62460               _downPointer = null;
62461             }
62462           }
62463
62464           function mouseenter() {
62465             _mouseLeave = false;
62466           }
62467
62468           function mouseleave() {
62469             _mouseLeave = true;
62470           }
62471
62472           function allowsVertex(d) {
62473             return d.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(d, context.graph());
62474           } // related code
62475           // - `mode/drag_node.js`     `doMove()`
62476           // - `behavior/draw.js`      `click()`
62477           // - `behavior/draw_way.js`  `move()`
62478
62479
62480           function click(d3_event, loc) {
62481             var d = datum(d3_event);
62482             var target = d && d.properties && d.properties.entity;
62483             var mode = context.mode();
62484
62485             if (target && target.type === 'node' && allowsVertex(target)) {
62486               // Snap to a node
62487               dispatch.call('clickNode', this, target, d);
62488               return;
62489             } else if (target && target.type === 'way' && (mode.id !== 'add-point' || mode.preset.matchGeometry('vertex'))) {
62490               // Snap to a way
62491               var choice = geoChooseEdge(context.graph().childNodes(target), loc, context.projection, context.activeID());
62492
62493               if (choice) {
62494                 var edge = [target.nodes[choice.index - 1], target.nodes[choice.index]];
62495                 dispatch.call('clickWay', this, choice.loc, edge, d);
62496                 return;
62497               }
62498             } else if (mode.id !== 'add-point' || mode.preset.matchGeometry('point')) {
62499               var locLatLng = context.projection.invert(loc);
62500               dispatch.call('click', this, locLatLng, d);
62501             }
62502           } // treat a spacebar press like a click
62503
62504
62505           function space(d3_event) {
62506             d3_event.preventDefault();
62507             d3_event.stopPropagation();
62508             var currSpace = context.map().mouse();
62509
62510             if (_disableSpace && _lastSpace) {
62511               var dist = geoVecLength(_lastSpace, currSpace);
62512
62513               if (dist > _tolerance) {
62514                 _disableSpace = false;
62515               }
62516             }
62517
62518             if (_disableSpace || _mouseLeave || !_lastMouse) return; // user must move mouse or release space bar to allow another click
62519
62520             _lastSpace = currSpace;
62521             _disableSpace = true;
62522             select(window).on('keyup.space-block', function () {
62523               d3_event.preventDefault();
62524               d3_event.stopPropagation();
62525               _disableSpace = false;
62526               select(window).on('keyup.space-block', null);
62527             }); // get the current mouse position
62528
62529             var loc = context.map().mouse() || // or the map center if the mouse has never entered the map
62530             context.projection(context.map().center());
62531             click(d3_event, loc);
62532           }
62533
62534           function backspace(d3_event) {
62535             d3_event.preventDefault();
62536             dispatch.call('undo');
62537           }
62538
62539           function del(d3_event) {
62540             d3_event.preventDefault();
62541             dispatch.call('cancel');
62542           }
62543
62544           function ret(d3_event) {
62545             d3_event.preventDefault();
62546             dispatch.call('finish');
62547           }
62548
62549           function behavior(selection) {
62550             context.install(_hover);
62551             context.install(_edit);
62552             _downPointer = null;
62553             keybinding.on('⌫', backspace).on('⌦', del).on('⎋', ret).on('↩', ret).on('space', space).on('⌥space', space);
62554             selection.on('mouseenter.draw', mouseenter).on('mouseleave.draw', mouseleave).on(_pointerPrefix + 'down.draw', pointerdown).on(_pointerPrefix + 'move.draw', pointermove);
62555             select(window).on(_pointerPrefix + 'up.draw', pointerup, true).on('pointercancel.draw', pointercancel, true);
62556             select(document).call(keybinding);
62557             return behavior;
62558           }
62559
62560           behavior.off = function (selection) {
62561             context.ui().sidebar.hover.cancel();
62562             context.uninstall(_hover);
62563             context.uninstall(_edit);
62564             selection.on('mouseenter.draw', null).on('mouseleave.draw', null).on(_pointerPrefix + 'down.draw', null).on(_pointerPrefix + 'move.draw', null);
62565             select(window).on(_pointerPrefix + 'up.draw', null).on('pointercancel.draw', null); // note: keyup.space-block, click.draw-block should remain
62566
62567             select(document).call(keybinding.unbind);
62568           };
62569
62570           behavior.hover = function () {
62571             return _hover;
62572           };
62573
62574           return utilRebind(behavior, dispatch, 'on');
62575         }
62576
62577         function initRange(domain, range) {
62578           switch (arguments.length) {
62579             case 0:
62580               break;
62581
62582             case 1:
62583               this.range(domain);
62584               break;
62585
62586             default:
62587               this.range(range).domain(domain);
62588               break;
62589           }
62590
62591           return this;
62592         }
62593
62594         function constants(x) {
62595           return function () {
62596             return x;
62597           };
62598         }
62599
62600         function number(x) {
62601           return +x;
62602         }
62603
62604         var unit = [0, 1];
62605         function identity$1(x) {
62606           return x;
62607         }
62608
62609         function normalize(a, b) {
62610           return (b -= a = +a) ? function (x) {
62611             return (x - a) / b;
62612           } : constants(isNaN(b) ? NaN : 0.5);
62613         }
62614
62615         function clamper(a, b) {
62616           var t;
62617           if (a > b) t = a, a = b, b = t;
62618           return function (x) {
62619             return Math.max(a, Math.min(b, x));
62620           };
62621         } // normalize(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
62622         // interpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding range value x in [a,b].
62623
62624
62625         function bimap(domain, range, interpolate) {
62626           var d0 = domain[0],
62627               d1 = domain[1],
62628               r0 = range[0],
62629               r1 = range[1];
62630           if (d1 < d0) d0 = normalize(d1, d0), r0 = interpolate(r1, r0);else d0 = normalize(d0, d1), r0 = interpolate(r0, r1);
62631           return function (x) {
62632             return r0(d0(x));
62633           };
62634         }
62635
62636         function polymap(domain, range, interpolate) {
62637           var j = Math.min(domain.length, range.length) - 1,
62638               d = new Array(j),
62639               r = new Array(j),
62640               i = -1; // Reverse descending domains.
62641
62642           if (domain[j] < domain[0]) {
62643             domain = domain.slice().reverse();
62644             range = range.slice().reverse();
62645           }
62646
62647           while (++i < j) {
62648             d[i] = normalize(domain[i], domain[i + 1]);
62649             r[i] = interpolate(range[i], range[i + 1]);
62650           }
62651
62652           return function (x) {
62653             var i = bisectRight(domain, x, 1, j) - 1;
62654             return r[i](d[i](x));
62655           };
62656         }
62657
62658         function copy(source, target) {
62659           return target.domain(source.domain()).range(source.range()).interpolate(source.interpolate()).clamp(source.clamp()).unknown(source.unknown());
62660         }
62661         function transformer() {
62662           var domain = unit,
62663               range = unit,
62664               interpolate = interpolate$1,
62665               transform,
62666               untransform,
62667               unknown,
62668               clamp = identity$1,
62669               piecewise,
62670               output,
62671               input;
62672
62673           function rescale() {
62674             var n = Math.min(domain.length, range.length);
62675             if (clamp !== identity$1) clamp = clamper(domain[0], domain[n - 1]);
62676             piecewise = n > 2 ? polymap : bimap;
62677             output = input = null;
62678             return scale;
62679           }
62680
62681           function scale(x) {
62682             return x == null || isNaN(x = +x) ? unknown : (output || (output = piecewise(domain.map(transform), range, interpolate)))(transform(clamp(x)));
62683           }
62684
62685           scale.invert = function (y) {
62686             return clamp(untransform((input || (input = piecewise(range, domain.map(transform), d3_interpolateNumber)))(y)));
62687           };
62688
62689           scale.domain = function (_) {
62690             return arguments.length ? (domain = Array.from(_, number), rescale()) : domain.slice();
62691           };
62692
62693           scale.range = function (_) {
62694             return arguments.length ? (range = Array.from(_), rescale()) : range.slice();
62695           };
62696
62697           scale.rangeRound = function (_) {
62698             return range = Array.from(_), interpolate = interpolateRound, rescale();
62699           };
62700
62701           scale.clamp = function (_) {
62702             return arguments.length ? (clamp = _ ? true : identity$1, rescale()) : clamp !== identity$1;
62703           };
62704
62705           scale.interpolate = function (_) {
62706             return arguments.length ? (interpolate = _, rescale()) : interpolate;
62707           };
62708
62709           scale.unknown = function (_) {
62710             return arguments.length ? (unknown = _, scale) : unknown;
62711           };
62712
62713           return function (t, u) {
62714             transform = t, untransform = u;
62715             return rescale();
62716           };
62717         }
62718         function continuous() {
62719           return transformer()(identity$1, identity$1);
62720         }
62721
62722         function formatDecimal (x) {
62723           return Math.abs(x = Math.round(x)) >= 1e21 ? x.toLocaleString("en").replace(/,/g, "") : x.toString(10);
62724         } // Computes the decimal coefficient and exponent of the specified number x with
62725         // significant digits p, where x is positive and p is in [1, 21] or undefined.
62726         // For example, formatDecimalParts(1.23) returns ["123", 0].
62727
62728         function formatDecimalParts(x, p) {
62729           if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
62730
62731           var i,
62732               coefficient = x.slice(0, i); // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
62733           // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
62734
62735           return [coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, +x.slice(i + 1)];
62736         }
62737
62738         function exponent (x) {
62739           return x = formatDecimalParts(Math.abs(x)), x ? x[1] : NaN;
62740         }
62741
62742         function formatGroup (grouping, thousands) {
62743           return function (value, width) {
62744             var i = value.length,
62745                 t = [],
62746                 j = 0,
62747                 g = grouping[0],
62748                 length = 0;
62749
62750             while (i > 0 && g > 0) {
62751               if (length + g + 1 > width) g = Math.max(1, width - length);
62752               t.push(value.substring(i -= g, i + g));
62753               if ((length += g + 1) > width) break;
62754               g = grouping[j = (j + 1) % grouping.length];
62755             }
62756
62757             return t.reverse().join(thousands);
62758           };
62759         }
62760
62761         function formatNumerals (numerals) {
62762           return function (value) {
62763             return value.replace(/[0-9]/g, function (i) {
62764               return numerals[+i];
62765             });
62766           };
62767         }
62768
62769         // [[fill]align][sign][symbol][0][width][,][.precision][~][type]
62770         var re = /^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;
62771         function formatSpecifier(specifier) {
62772           if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
62773           var match;
62774           return new FormatSpecifier({
62775             fill: match[1],
62776             align: match[2],
62777             sign: match[3],
62778             symbol: match[4],
62779             zero: match[5],
62780             width: match[6],
62781             comma: match[7],
62782             precision: match[8] && match[8].slice(1),
62783             trim: match[9],
62784             type: match[10]
62785           });
62786         }
62787         formatSpecifier.prototype = FormatSpecifier.prototype; // instanceof
62788
62789         function FormatSpecifier(specifier) {
62790           this.fill = specifier.fill === undefined ? " " : specifier.fill + "";
62791           this.align = specifier.align === undefined ? ">" : specifier.align + "";
62792           this.sign = specifier.sign === undefined ? "-" : specifier.sign + "";
62793           this.symbol = specifier.symbol === undefined ? "" : specifier.symbol + "";
62794           this.zero = !!specifier.zero;
62795           this.width = specifier.width === undefined ? undefined : +specifier.width;
62796           this.comma = !!specifier.comma;
62797           this.precision = specifier.precision === undefined ? undefined : +specifier.precision;
62798           this.trim = !!specifier.trim;
62799           this.type = specifier.type === undefined ? "" : specifier.type + "";
62800         }
62801
62802         FormatSpecifier.prototype.toString = function () {
62803           return this.fill + this.align + this.sign + this.symbol + (this.zero ? "0" : "") + (this.width === undefined ? "" : Math.max(1, this.width | 0)) + (this.comma ? "," : "") + (this.precision === undefined ? "" : "." + Math.max(0, this.precision | 0)) + (this.trim ? "~" : "") + this.type;
62804         };
62805
62806         // Trims insignificant zeros, e.g., replaces 1.2000k with 1.2k.
62807         function formatTrim (s) {
62808           out: for (var n = s.length, i = 1, i0 = -1, i1; i < n; ++i) {
62809             switch (s[i]) {
62810               case ".":
62811                 i0 = i1 = i;
62812                 break;
62813
62814               case "0":
62815                 if (i0 === 0) i0 = i;
62816                 i1 = i;
62817                 break;
62818
62819               default:
62820                 if (!+s[i]) break out;
62821                 if (i0 > 0) i0 = 0;
62822                 break;
62823             }
62824           }
62825
62826           return i0 > 0 ? s.slice(0, i0) + s.slice(i1 + 1) : s;
62827         }
62828
62829         var $$5 = _export;
62830         var uncurryThis$3 = functionUncurryThis;
62831         var fails$3 = fails$V;
62832         var thisNumberValue = thisNumberValue$3;
62833
62834         var un$ToPrecision = uncurryThis$3(1.0.toPrecision);
62835
62836         var FORCED$1 = fails$3(function () {
62837           // IE7-
62838           return un$ToPrecision(1, undefined) !== '1';
62839         }) || !fails$3(function () {
62840           // V8 ~ Android 4.3-
62841           un$ToPrecision({});
62842         });
62843
62844         // `Number.prototype.toPrecision` method
62845         // https://tc39.es/ecma262/#sec-number.prototype.toprecision
62846         $$5({ target: 'Number', proto: true, forced: FORCED$1 }, {
62847           toPrecision: function toPrecision(precision) {
62848             return precision === undefined
62849               ? un$ToPrecision(thisNumberValue(this))
62850               : un$ToPrecision(thisNumberValue(this), precision);
62851           }
62852         });
62853
62854         var prefixExponent;
62855         function formatPrefixAuto (x, p) {
62856           var d = formatDecimalParts(x, p);
62857           if (!d) return x + "";
62858           var coefficient = d[0],
62859               exponent = d[1],
62860               i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
62861               n = coefficient.length;
62862           return i === n ? coefficient : i > n ? coefficient + new Array(i - n + 1).join("0") : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) : "0." + new Array(1 - i).join("0") + formatDecimalParts(x, Math.max(0, p + i - 1))[0]; // less than 1y!
62863         }
62864
62865         function formatRounded (x, p) {
62866           var d = formatDecimalParts(x, p);
62867           if (!d) return x + "";
62868           var coefficient = d[0],
62869               exponent = d[1];
62870           return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) : coefficient + new Array(exponent - coefficient.length + 2).join("0");
62871         }
62872
62873         var formatTypes = {
62874           "%": function _(x, p) {
62875             return (x * 100).toFixed(p);
62876           },
62877           "b": function b(x) {
62878             return Math.round(x).toString(2);
62879           },
62880           "c": function c(x) {
62881             return x + "";
62882           },
62883           "d": formatDecimal,
62884           "e": function e(x, p) {
62885             return x.toExponential(p);
62886           },
62887           "f": function f(x, p) {
62888             return x.toFixed(p);
62889           },
62890           "g": function g(x, p) {
62891             return x.toPrecision(p);
62892           },
62893           "o": function o(x) {
62894             return Math.round(x).toString(8);
62895           },
62896           "p": function p(x, _p) {
62897             return formatRounded(x * 100, _p);
62898           },
62899           "r": formatRounded,
62900           "s": formatPrefixAuto,
62901           "X": function X(x) {
62902             return Math.round(x).toString(16).toUpperCase();
62903           },
62904           "x": function x(_x) {
62905             return Math.round(_x).toString(16);
62906           }
62907         };
62908
62909         function identity (x) {
62910           return x;
62911         }
62912
62913         var map$1 = Array.prototype.map,
62914             prefixes = ["y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y"];
62915         function formatLocale (locale) {
62916           var group = locale.grouping === undefined || locale.thousands === undefined ? identity : formatGroup(map$1.call(locale.grouping, Number), locale.thousands + ""),
62917               currencyPrefix = locale.currency === undefined ? "" : locale.currency[0] + "",
62918               currencySuffix = locale.currency === undefined ? "" : locale.currency[1] + "",
62919               decimal = locale.decimal === undefined ? "." : locale.decimal + "",
62920               numerals = locale.numerals === undefined ? identity : formatNumerals(map$1.call(locale.numerals, String)),
62921               percent = locale.percent === undefined ? "%" : locale.percent + "",
62922               minus = locale.minus === undefined ? "−" : locale.minus + "",
62923               nan = locale.nan === undefined ? "NaN" : locale.nan + "";
62924
62925           function newFormat(specifier) {
62926             specifier = formatSpecifier(specifier);
62927             var fill = specifier.fill,
62928                 align = specifier.align,
62929                 sign = specifier.sign,
62930                 symbol = specifier.symbol,
62931                 zero = specifier.zero,
62932                 width = specifier.width,
62933                 comma = specifier.comma,
62934                 precision = specifier.precision,
62935                 trim = specifier.trim,
62936                 type = specifier.type; // The "n" type is an alias for ",g".
62937
62938             if (type === "n") comma = true, type = "g"; // The "" type, and any invalid type, is an alias for ".12~g".
62939             else if (!formatTypes[type]) precision === undefined && (precision = 12), trim = true, type = "g"; // If zero fill is specified, padding goes after sign and before digits.
62940
62941             if (zero || fill === "0" && align === "=") zero = true, fill = "0", align = "="; // Compute the prefix and suffix.
62942             // For SI-prefix, the suffix is lazily computed.
62943
62944             var prefix = symbol === "$" ? currencyPrefix : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
62945                 suffix = symbol === "$" ? currencySuffix : /[%p]/.test(type) ? percent : ""; // What format function should we use?
62946             // Is this an integer type?
62947             // Can this type generate exponential notation?
62948
62949             var formatType = formatTypes[type],
62950                 maybeSuffix = /[defgprs%]/.test(type); // Set the default precision if not specified,
62951             // or clamp the specified precision to the supported range.
62952             // For significant precision, it must be in [1, 21].
62953             // For fixed precision, it must be in [0, 20].
62954
62955             precision = precision === undefined ? 6 : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) : Math.max(0, Math.min(20, precision));
62956
62957             function format(value) {
62958               var valuePrefix = prefix,
62959                   valueSuffix = suffix,
62960                   i,
62961                   n,
62962                   c;
62963
62964               if (type === "c") {
62965                 valueSuffix = formatType(value) + valueSuffix;
62966                 value = "";
62967               } else {
62968                 value = +value; // Determine the sign. -0 is not less than 0, but 1 / -0 is!
62969
62970                 var valueNegative = value < 0 || 1 / value < 0; // Perform the initial formatting.
62971
62972                 value = isNaN(value) ? nan : formatType(Math.abs(value), precision); // Trim insignificant zeros.
62973
62974                 if (trim) value = formatTrim(value); // If a negative value rounds to zero after formatting, and no explicit positive sign is requested, hide the sign.
62975
62976                 if (valueNegative && +value === 0 && sign !== "+") valueNegative = false; // Compute the prefix and suffix.
62977
62978                 valuePrefix = (valueNegative ? sign === "(" ? sign : minus : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
62979                 valueSuffix = (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + valueSuffix + (valueNegative && sign === "(" ? ")" : ""); // Break the formatted value into the integer “value” part that can be
62980                 // grouped, and fractional or exponential “suffix” part that is not.
62981
62982                 if (maybeSuffix) {
62983                   i = -1, n = value.length;
62984
62985                   while (++i < n) {
62986                     if (c = value.charCodeAt(i), 48 > c || c > 57) {
62987                       valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
62988                       value = value.slice(0, i);
62989                       break;
62990                     }
62991                   }
62992                 }
62993               } // If the fill character is not "0", grouping is applied before padding.
62994
62995
62996               if (comma && !zero) value = group(value, Infinity); // Compute the padding.
62997
62998               var length = valuePrefix.length + value.length + valueSuffix.length,
62999                   padding = length < width ? new Array(width - length + 1).join(fill) : ""; // If the fill character is "0", grouping is applied after padding.
63000
63001               if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; // Reconstruct the final output based on the desired alignment.
63002
63003               switch (align) {
63004                 case "<":
63005                   value = valuePrefix + value + valueSuffix + padding;
63006                   break;
63007
63008                 case "=":
63009                   value = valuePrefix + padding + value + valueSuffix;
63010                   break;
63011
63012                 case "^":
63013                   value = padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
63014                   break;
63015
63016                 default:
63017                   value = padding + valuePrefix + value + valueSuffix;
63018                   break;
63019               }
63020
63021               return numerals(value);
63022             }
63023
63024             format.toString = function () {
63025               return specifier + "";
63026             };
63027
63028             return format;
63029           }
63030
63031           function formatPrefix(specifier, value) {
63032             var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
63033                 e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3,
63034                 k = Math.pow(10, -e),
63035                 prefix = prefixes[8 + e / 3];
63036             return function (value) {
63037               return f(k * value) + prefix;
63038             };
63039           }
63040
63041           return {
63042             format: newFormat,
63043             formatPrefix: formatPrefix
63044           };
63045         }
63046
63047         var locale;
63048         var format$1;
63049         var formatPrefix;
63050         defaultLocale({
63051           thousands: ",",
63052           grouping: [3],
63053           currency: ["$", ""]
63054         });
63055         function defaultLocale(definition) {
63056           locale = formatLocale(definition);
63057           format$1 = locale.format;
63058           formatPrefix = locale.formatPrefix;
63059           return locale;
63060         }
63061
63062         function precisionFixed (step) {
63063           return Math.max(0, -exponent(Math.abs(step)));
63064         }
63065
63066         function precisionPrefix (step, value) {
63067           return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step)));
63068         }
63069
63070         function precisionRound (step, max) {
63071           step = Math.abs(step), max = Math.abs(max) - step;
63072           return Math.max(0, exponent(max) - exponent(step)) + 1;
63073         }
63074
63075         function tickFormat(start, stop, count, specifier) {
63076           var step = tickStep(start, stop, count),
63077               precision;
63078           specifier = formatSpecifier(specifier == null ? ",f" : specifier);
63079
63080           switch (specifier.type) {
63081             case "s":
63082               {
63083                 var value = Math.max(Math.abs(start), Math.abs(stop));
63084                 if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
63085                 return formatPrefix(specifier, value);
63086               }
63087
63088             case "":
63089             case "e":
63090             case "g":
63091             case "p":
63092             case "r":
63093               {
63094                 if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
63095                 break;
63096               }
63097
63098             case "f":
63099             case "%":
63100               {
63101                 if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
63102                 break;
63103               }
63104           }
63105
63106           return format$1(specifier);
63107         }
63108
63109         function linearish(scale) {
63110           var domain = scale.domain;
63111
63112           scale.ticks = function (count) {
63113             var d = domain();
63114             return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
63115           };
63116
63117           scale.tickFormat = function (count, specifier) {
63118             var d = domain();
63119             return tickFormat(d[0], d[d.length - 1], count == null ? 10 : count, specifier);
63120           };
63121
63122           scale.nice = function (count) {
63123             if (count == null) count = 10;
63124             var d = domain();
63125             var i0 = 0;
63126             var i1 = d.length - 1;
63127             var start = d[i0];
63128             var stop = d[i1];
63129             var prestep;
63130             var step;
63131             var maxIter = 10;
63132
63133             if (stop < start) {
63134               step = start, start = stop, stop = step;
63135               step = i0, i0 = i1, i1 = step;
63136             }
63137
63138             while (maxIter-- > 0) {
63139               step = tickIncrement(start, stop, count);
63140
63141               if (step === prestep) {
63142                 d[i0] = start;
63143                 d[i1] = stop;
63144                 return domain(d);
63145               } else if (step > 0) {
63146                 start = Math.floor(start / step) * step;
63147                 stop = Math.ceil(stop / step) * step;
63148               } else if (step < 0) {
63149                 start = Math.ceil(start * step) / step;
63150                 stop = Math.floor(stop * step) / step;
63151               } else {
63152                 break;
63153               }
63154
63155               prestep = step;
63156             }
63157
63158             return scale;
63159           };
63160
63161           return scale;
63162         }
63163         function linear() {
63164           var scale = continuous();
63165
63166           scale.copy = function () {
63167             return copy(scale, linear());
63168           };
63169
63170           initRange.apply(scale, arguments);
63171           return linearish(scale);
63172         }
63173
63174         // eslint-disable-next-line es/no-math-expm1 -- safe
63175         var $expm1 = Math.expm1;
63176         var exp$1 = Math.exp;
63177
63178         // `Math.expm1` method implementation
63179         // https://tc39.es/ecma262/#sec-math.expm1
63180         var mathExpm1 = (!$expm1
63181           // Old FF bug
63182           || $expm1(10) > 22025.465794806719 || $expm1(10) < 22025.4657948067165168
63183           // Tor Browser bug
63184           || $expm1(-2e-17) != -2e-17
63185         ) ? function expm1(x) {
63186           return (x = +x) == 0 ? x : x > -1e-6 && x < 1e-6 ? x + x * x / 2 : exp$1(x) - 1;
63187         } : $expm1;
63188
63189         function quantize() {
63190           var x0 = 0,
63191               x1 = 1,
63192               n = 1,
63193               domain = [0.5],
63194               range = [0, 1],
63195               unknown;
63196
63197           function scale(x) {
63198             return x != null && x <= x ? range[bisectRight(domain, x, 0, n)] : unknown;
63199           }
63200
63201           function rescale() {
63202             var i = -1;
63203             domain = new Array(n);
63204
63205             while (++i < n) {
63206               domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
63207             }
63208
63209             return scale;
63210           }
63211
63212           scale.domain = function (_) {
63213             var _ref, _ref2;
63214
63215             return arguments.length ? ((_ref = _, _ref2 = _slicedToArray(_ref, 2), x0 = _ref2[0], x1 = _ref2[1], _ref), x0 = +x0, x1 = +x1, rescale()) : [x0, x1];
63216           };
63217
63218           scale.range = function (_) {
63219             return arguments.length ? (n = (range = Array.from(_)).length - 1, rescale()) : range.slice();
63220           };
63221
63222           scale.invertExtent = function (y) {
63223             var i = range.indexOf(y);
63224             return i < 0 ? [NaN, NaN] : i < 1 ? [x0, domain[0]] : i >= n ? [domain[n - 1], x1] : [domain[i - 1], domain[i]];
63225           };
63226
63227           scale.unknown = function (_) {
63228             return arguments.length ? (unknown = _, scale) : scale;
63229           };
63230
63231           scale.thresholds = function () {
63232             return domain.slice();
63233           };
63234
63235           scale.copy = function () {
63236             return quantize().domain([x0, x1]).range(range).unknown(unknown);
63237           };
63238
63239           return initRange.apply(linearish(scale), arguments);
63240         }
63241
63242         var global$3 = global$1o;
63243         var uncurryThis$2 = functionUncurryThis;
63244         var fails$2 = fails$V;
63245         var padStart = stringPad.start;
63246
63247         var RangeError$2 = global$3.RangeError;
63248         var abs$1 = Math.abs;
63249         var DatePrototype = Date.prototype;
63250         var n$DateToISOString = DatePrototype.toISOString;
63251         var getTime = uncurryThis$2(DatePrototype.getTime);
63252         var getUTCDate = uncurryThis$2(DatePrototype.getUTCDate);
63253         var getUTCFullYear = uncurryThis$2(DatePrototype.getUTCFullYear);
63254         var getUTCHours = uncurryThis$2(DatePrototype.getUTCHours);
63255         var getUTCMilliseconds = uncurryThis$2(DatePrototype.getUTCMilliseconds);
63256         var getUTCMinutes = uncurryThis$2(DatePrototype.getUTCMinutes);
63257         var getUTCMonth = uncurryThis$2(DatePrototype.getUTCMonth);
63258         var getUTCSeconds = uncurryThis$2(DatePrototype.getUTCSeconds);
63259
63260         // `Date.prototype.toISOString` method implementation
63261         // https://tc39.es/ecma262/#sec-date.prototype.toisostring
63262         // PhantomJS / old WebKit fails here:
63263         var dateToIsoString = (fails$2(function () {
63264           return n$DateToISOString.call(new Date(-5e13 - 1)) != '0385-07-25T07:06:39.999Z';
63265         }) || !fails$2(function () {
63266           n$DateToISOString.call(new Date(NaN));
63267         })) ? function toISOString() {
63268           if (!isFinite(getTime(this))) throw RangeError$2('Invalid time value');
63269           var date = this;
63270           var year = getUTCFullYear(date);
63271           var milliseconds = getUTCMilliseconds(date);
63272           var sign = year < 0 ? '-' : year > 9999 ? '+' : '';
63273           return sign + padStart(abs$1(year), sign ? 6 : 4, 0) +
63274             '-' + padStart(getUTCMonth(date) + 1, 2, 0) +
63275             '-' + padStart(getUTCDate(date), 2, 0) +
63276             'T' + padStart(getUTCHours(date), 2, 0) +
63277             ':' + padStart(getUTCMinutes(date), 2, 0) +
63278             ':' + padStart(getUTCSeconds(date), 2, 0) +
63279             '.' + padStart(milliseconds, 3, 0) +
63280             'Z';
63281         } : n$DateToISOString;
63282
63283         var $$4 = _export;
63284         var toISOString = dateToIsoString;
63285
63286         // `Date.prototype.toISOString` method
63287         // https://tc39.es/ecma262/#sec-date.prototype.toisostring
63288         // PhantomJS / old WebKit has a broken implementations
63289         $$4({ target: 'Date', proto: true, forced: Date.prototype.toISOString !== toISOString }, {
63290           toISOString: toISOString
63291         });
63292
63293         function behaviorBreathe() {
63294           var duration = 800;
63295           var steps = 4;
63296           var selector = '.selected.shadow, .selected .shadow';
63297
63298           var _selected = select(null);
63299
63300           var _classed = '';
63301           var _params = {};
63302           var _done = false;
63303
63304           var _timer;
63305
63306           function ratchetyInterpolator(a, b, steps, units) {
63307             a = parseFloat(a);
63308             b = parseFloat(b);
63309             var sample = quantize().domain([0, 1]).range(d3_quantize(d3_interpolateNumber(a, b), steps));
63310             return function (t) {
63311               return String(sample(t)) + (units || '');
63312             };
63313           }
63314
63315           function reset(selection) {
63316             selection.style('stroke-opacity', null).style('stroke-width', null).style('fill-opacity', null).style('r', null);
63317           }
63318
63319           function setAnimationParams(transition, fromTo) {
63320             var toFrom = fromTo === 'from' ? 'to' : 'from';
63321             transition.styleTween('stroke-opacity', function (d) {
63322               return ratchetyInterpolator(_params[d.id][toFrom].opacity, _params[d.id][fromTo].opacity, steps);
63323             }).styleTween('stroke-width', function (d) {
63324               return ratchetyInterpolator(_params[d.id][toFrom].width, _params[d.id][fromTo].width, steps, 'px');
63325             }).styleTween('fill-opacity', function (d) {
63326               return ratchetyInterpolator(_params[d.id][toFrom].opacity, _params[d.id][fromTo].opacity, steps);
63327             }).styleTween('r', function (d) {
63328               return ratchetyInterpolator(_params[d.id][toFrom].width, _params[d.id][fromTo].width, steps, 'px');
63329             });
63330           }
63331
63332           function calcAnimationParams(selection) {
63333             selection.call(reset).each(function (d) {
63334               var s = select(this);
63335               var tag = s.node().tagName;
63336               var p = {
63337                 'from': {},
63338                 'to': {}
63339               };
63340               var opacity;
63341               var width; // determine base opacity and width
63342
63343               if (tag === 'circle') {
63344                 opacity = parseFloat(s.style('fill-opacity') || 0.5);
63345                 width = parseFloat(s.style('r') || 15.5);
63346               } else {
63347                 opacity = parseFloat(s.style('stroke-opacity') || 0.7);
63348                 width = parseFloat(s.style('stroke-width') || 10);
63349               } // calculate from/to interpolation params..
63350
63351
63352               p.tag = tag;
63353               p.from.opacity = opacity * 0.6;
63354               p.to.opacity = opacity * 1.25;
63355               p.from.width = width * 0.7;
63356               p.to.width = width * (tag === 'circle' ? 1.5 : 1);
63357               _params[d.id] = p;
63358             });
63359           }
63360
63361           function run(surface, fromTo) {
63362             var toFrom = fromTo === 'from' ? 'to' : 'from';
63363             var currSelected = surface.selectAll(selector);
63364             var currClassed = surface.attr('class');
63365
63366             if (_done || currSelected.empty()) {
63367               _selected.call(reset);
63368
63369               _selected = select(null);
63370               return;
63371             }
63372
63373             if (!fastDeepEqual(currSelected.data(), _selected.data()) || currClassed !== _classed) {
63374               _selected.call(reset);
63375
63376               _classed = currClassed;
63377               _selected = currSelected.call(calcAnimationParams);
63378             }
63379
63380             var didCallNextRun = false;
63381
63382             _selected.transition().duration(duration).call(setAnimationParams, fromTo).on('end', function () {
63383               // `end` event is called for each selected element, but we want
63384               // it to run only once
63385               if (!didCallNextRun) {
63386                 surface.call(run, toFrom);
63387                 didCallNextRun = true;
63388               } // if entity was deselected, remove breathe styling
63389
63390
63391               if (!select(this).classed('selected')) {
63392                 reset(select(this));
63393               }
63394             });
63395           }
63396
63397           function behavior(surface) {
63398             _done = false;
63399             _timer = timer(function () {
63400               // wait for elements to actually become selected
63401               if (surface.selectAll(selector).empty()) {
63402                 return false;
63403               }
63404
63405               surface.call(run, 'from');
63406
63407               _timer.stop();
63408
63409               return true;
63410             }, 20);
63411           }
63412
63413           behavior.restartIfNeeded = function (surface) {
63414             if (_selected.empty()) {
63415               surface.call(run, 'from');
63416
63417               if (_timer) {
63418                 _timer.stop();
63419               }
63420             }
63421           };
63422
63423           behavior.off = function () {
63424             _done = true;
63425
63426             if (_timer) {
63427               _timer.stop();
63428             }
63429
63430             _selected.interrupt().call(reset);
63431           };
63432
63433           return behavior;
63434         }
63435
63436         /* Creates a keybinding behavior for an operation */
63437         function behaviorOperation(context) {
63438           var _operation;
63439
63440           function keypress(d3_event) {
63441             // prevent operations during low zoom selection
63442             if (!context.map().withinEditableZoom()) return;
63443             if (_operation.availableForKeypress && !_operation.availableForKeypress()) return;
63444             d3_event.preventDefault();
63445
63446             var disabled = _operation.disabled();
63447
63448             if (disabled) {
63449               context.ui().flash.duration(4000).iconName('#iD-operation-' + _operation.id).iconClass('operation disabled').label(_operation.tooltip)();
63450             } else {
63451               context.ui().flash.duration(2000).iconName('#iD-operation-' + _operation.id).iconClass('operation').label(_operation.annotation() || _operation.title)();
63452               if (_operation.point) _operation.point(null);
63453
63454               _operation();
63455             }
63456           }
63457
63458           function behavior() {
63459             if (_operation && _operation.available()) {
63460               context.keybinding().on(_operation.keys, keypress);
63461             }
63462
63463             return behavior;
63464           }
63465
63466           behavior.off = function () {
63467             context.keybinding().off(_operation.keys);
63468           };
63469
63470           behavior.which = function (_) {
63471             if (!arguments.length) return _operation;
63472             _operation = _;
63473             return behavior;
63474           };
63475
63476           return behavior;
63477         }
63478
63479         function operationCircularize(context, selectedIDs) {
63480           var _extent;
63481
63482           var _actions = selectedIDs.map(getAction).filter(Boolean);
63483
63484           var _amount = _actions.length === 1 ? 'single' : 'multiple';
63485
63486           var _coords = utilGetAllNodes(selectedIDs, context.graph()).map(function (n) {
63487             return n.loc;
63488           });
63489
63490           function getAction(entityID) {
63491             var entity = context.entity(entityID);
63492             if (entity.type !== 'way' || new Set(entity.nodes).size <= 1) return null;
63493
63494             if (!_extent) {
63495               _extent = entity.extent(context.graph());
63496             } else {
63497               _extent = _extent.extend(entity.extent(context.graph()));
63498             }
63499
63500             return actionCircularize(entityID, context.projection);
63501           }
63502
63503           var operation = function operation() {
63504             if (!_actions.length) return;
63505
63506             var combinedAction = function combinedAction(graph, t) {
63507               _actions.forEach(function (action) {
63508                 if (!action.disabled(graph)) {
63509                   graph = action(graph, t);
63510                 }
63511               });
63512
63513               return graph;
63514             };
63515
63516             combinedAction.transitionable = true;
63517             context.perform(combinedAction, operation.annotation());
63518             window.setTimeout(function () {
63519               context.validator().validate();
63520             }, 300); // after any transition
63521           };
63522
63523           operation.available = function () {
63524             return _actions.length && selectedIDs.length === _actions.length;
63525           }; // don't cache this because the visible extent could change
63526
63527
63528           operation.disabled = function () {
63529             if (!_actions.length) return '';
63530
63531             var actionDisableds = _actions.map(function (action) {
63532               return action.disabled(context.graph());
63533             }).filter(Boolean);
63534
63535             if (actionDisableds.length === _actions.length) {
63536               // none of the features can be circularized
63537               if (new Set(actionDisableds).size > 1) {
63538                 return 'multiple_blockers';
63539               }
63540
63541               return actionDisableds[0];
63542             } else if (_extent.percentContainedIn(context.map().extent()) < 0.8) {
63543               return 'too_large';
63544             } else if (someMissing()) {
63545               return 'not_downloaded';
63546             } else if (selectedIDs.some(context.hasHiddenConnections)) {
63547               return 'connected_to_hidden';
63548             }
63549
63550             return false;
63551
63552             function someMissing() {
63553               if (context.inIntro()) return false;
63554               var osm = context.connection();
63555
63556               if (osm) {
63557                 var missing = _coords.filter(function (loc) {
63558                   return !osm.isDataLoaded(loc);
63559                 });
63560
63561                 if (missing.length) {
63562                   missing.forEach(function (loc) {
63563                     context.loadTileAtLoc(loc);
63564                   });
63565                   return true;
63566                 }
63567               }
63568
63569               return false;
63570             }
63571           };
63572
63573           operation.tooltip = function () {
63574             var disable = operation.disabled();
63575             return disable ? _t('operations.circularize.' + disable + '.' + _amount) : _t('operations.circularize.description.' + _amount);
63576           };
63577
63578           operation.annotation = function () {
63579             return _t('operations.circularize.annotation.feature', {
63580               n: _actions.length
63581             });
63582           };
63583
63584           operation.id = 'circularize';
63585           operation.keys = [_t('operations.circularize.key')];
63586           operation.title = _t('operations.circularize.title');
63587           operation.behavior = behaviorOperation(context).which(operation);
63588           return operation;
63589         }
63590
63591         // For example, ⌘Z -> Ctrl+Z
63592
63593         var uiCmd = function uiCmd(code) {
63594           var detected = utilDetect();
63595
63596           if (detected.os === 'mac') {
63597             return code;
63598           }
63599
63600           if (detected.os === 'win') {
63601             if (code === '⌘⇧Z') return 'Ctrl+Y';
63602           }
63603
63604           var result = '',
63605               replacements = {
63606             '⌘': 'Ctrl',
63607             '⇧': 'Shift',
63608             '⌥': 'Alt',
63609             '⌫': 'Backspace',
63610             '⌦': 'Delete'
63611           };
63612
63613           for (var i = 0; i < code.length; i++) {
63614             if (code[i] in replacements) {
63615               result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
63616             } else {
63617               result += code[i];
63618             }
63619           }
63620
63621           return result;
63622         }; // return a display-focused string for a given keyboard code
63623
63624         uiCmd.display = function (code) {
63625           if (code.length !== 1) return code;
63626           var detected = utilDetect();
63627           var mac = detected.os === 'mac';
63628           var replacements = {
63629             '⌘': mac ? '⌘ ' + _t('shortcuts.key.cmd') : _t('shortcuts.key.ctrl'),
63630             '⇧': mac ? '⇧ ' + _t('shortcuts.key.shift') : _t('shortcuts.key.shift'),
63631             '⌥': mac ? '⌥ ' + _t('shortcuts.key.option') : _t('shortcuts.key.alt'),
63632             '⌃': mac ? '⌃ ' + _t('shortcuts.key.ctrl') : _t('shortcuts.key.ctrl'),
63633             '⌫': mac ? '⌫ ' + _t('shortcuts.key.delete') : _t('shortcuts.key.backspace'),
63634             '⌦': mac ? '⌦ ' + _t('shortcuts.key.del') : _t('shortcuts.key.del'),
63635             '↖': mac ? '↖ ' + _t('shortcuts.key.pgup') : _t('shortcuts.key.pgup'),
63636             '↘': mac ? '↘ ' + _t('shortcuts.key.pgdn') : _t('shortcuts.key.pgdn'),
63637             '⇞': mac ? '⇞ ' + _t('shortcuts.key.home') : _t('shortcuts.key.home'),
63638             '⇟': mac ? '⇟ ' + _t('shortcuts.key.end') : _t('shortcuts.key.end'),
63639             '↵': mac ? '⏎ ' + _t('shortcuts.key.return') : _t('shortcuts.key.enter'),
63640             '⎋': mac ? '⎋ ' + _t('shortcuts.key.esc') : _t('shortcuts.key.esc'),
63641             '☰': mac ? '☰ ' + _t('shortcuts.key.menu') : _t('shortcuts.key.menu')
63642           };
63643           return replacements[code] || code;
63644         };
63645
63646         function operationDelete(context, selectedIDs) {
63647           var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
63648           var action = actionDeleteMultiple(selectedIDs);
63649           var nodes = utilGetAllNodes(selectedIDs, context.graph());
63650           var coords = nodes.map(function (n) {
63651             return n.loc;
63652           });
63653           var extent = utilTotalExtent(selectedIDs, context.graph());
63654
63655           var operation = function operation() {
63656             var nextSelectedID;
63657             var nextSelectedLoc;
63658
63659             if (selectedIDs.length === 1) {
63660               var id = selectedIDs[0];
63661               var entity = context.entity(id);
63662               var geometry = entity.geometry(context.graph());
63663               var parents = context.graph().parentWays(entity);
63664               var parent = parents[0]; // Select the next closest node in the way.
63665
63666               if (geometry === 'vertex') {
63667                 var nodes = parent.nodes;
63668                 var i = nodes.indexOf(id);
63669
63670                 if (i === 0) {
63671                   i++;
63672                 } else if (i === nodes.length - 1) {
63673                   i--;
63674                 } else {
63675                   var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc);
63676                   var b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
63677                   i = a < b ? i - 1 : i + 1;
63678                 }
63679
63680                 nextSelectedID = nodes[i];
63681                 nextSelectedLoc = context.entity(nextSelectedID).loc;
63682               }
63683             }
63684
63685             context.perform(action, operation.annotation());
63686             context.validator().validate();
63687
63688             if (nextSelectedID && nextSelectedLoc) {
63689               if (context.hasEntity(nextSelectedID)) {
63690                 context.enter(modeSelect(context, [nextSelectedID]).follow(true));
63691               } else {
63692                 context.map().centerEase(nextSelectedLoc);
63693                 context.enter(modeBrowse(context));
63694               }
63695             } else {
63696               context.enter(modeBrowse(context));
63697             }
63698           };
63699
63700           operation.available = function () {
63701             return true;
63702           };
63703
63704           operation.disabled = function () {
63705             if (extent.percentContainedIn(context.map().extent()) < 0.8) {
63706               return 'too_large';
63707             } else if (someMissing()) {
63708               return 'not_downloaded';
63709             } else if (selectedIDs.some(context.hasHiddenConnections)) {
63710               return 'connected_to_hidden';
63711             } else if (selectedIDs.some(protectedMember)) {
63712               return 'part_of_relation';
63713             } else if (selectedIDs.some(incompleteRelation)) {
63714               return 'incomplete_relation';
63715             } else if (selectedIDs.some(hasWikidataTag)) {
63716               return 'has_wikidata_tag';
63717             }
63718
63719             return false;
63720
63721             function someMissing() {
63722               if (context.inIntro()) return false;
63723               var osm = context.connection();
63724
63725               if (osm) {
63726                 var missing = coords.filter(function (loc) {
63727                   return !osm.isDataLoaded(loc);
63728                 });
63729
63730                 if (missing.length) {
63731                   missing.forEach(function (loc) {
63732                     context.loadTileAtLoc(loc);
63733                   });
63734                   return true;
63735                 }
63736               }
63737
63738               return false;
63739             }
63740
63741             function hasWikidataTag(id) {
63742               var entity = context.entity(id);
63743               return entity.tags.wikidata && entity.tags.wikidata.trim().length > 0;
63744             }
63745
63746             function incompleteRelation(id) {
63747               var entity = context.entity(id);
63748               return entity.type === 'relation' && !entity.isComplete(context.graph());
63749             }
63750
63751             function protectedMember(id) {
63752               var entity = context.entity(id);
63753               if (entity.type !== 'way') return false;
63754               var parents = context.graph().parentRelations(entity);
63755
63756               for (var i = 0; i < parents.length; i++) {
63757                 var parent = parents[i];
63758                 var type = parent.tags.type;
63759                 var role = parent.memberById(id).role || 'outer';
63760
63761                 if (type === 'route' || type === 'boundary' || type === 'multipolygon' && role === 'outer') {
63762                   return true;
63763                 }
63764               }
63765
63766               return false;
63767             }
63768           };
63769
63770           operation.tooltip = function () {
63771             var disable = operation.disabled();
63772             return disable ? _t('operations.delete.' + disable + '.' + multi) : _t('operations.delete.description.' + multi);
63773           };
63774
63775           operation.annotation = function () {
63776             return selectedIDs.length === 1 ? _t('operations.delete.annotation.' + context.graph().geometry(selectedIDs[0])) : _t('operations.delete.annotation.feature', {
63777               n: selectedIDs.length
63778             });
63779           };
63780
63781           operation.id = 'delete';
63782           operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
63783           operation.title = _t('operations.delete.title');
63784           operation.behavior = behaviorOperation(context).which(operation);
63785           return operation;
63786         }
63787
63788         function operationOrthogonalize(context, selectedIDs) {
63789           var _extent;
63790
63791           var _type;
63792
63793           var _actions = selectedIDs.map(chooseAction).filter(Boolean);
63794
63795           var _amount = _actions.length === 1 ? 'single' : 'multiple';
63796
63797           var _coords = utilGetAllNodes(selectedIDs, context.graph()).map(function (n) {
63798             return n.loc;
63799           });
63800
63801           function chooseAction(entityID) {
63802             var entity = context.entity(entityID);
63803             var geometry = entity.geometry(context.graph());
63804
63805             if (!_extent) {
63806               _extent = entity.extent(context.graph());
63807             } else {
63808               _extent = _extent.extend(entity.extent(context.graph()));
63809             } // square a line/area
63810
63811
63812             if (entity.type === 'way' && new Set(entity.nodes).size > 2) {
63813               if (_type && _type !== 'feature') return null;
63814               _type = 'feature';
63815               return actionOrthogonalize(entityID, context.projection); // square a single vertex
63816             } else if (geometry === 'vertex') {
63817               if (_type && _type !== 'corner') return null;
63818               _type = 'corner';
63819               var graph = context.graph();
63820               var parents = graph.parentWays(entity);
63821
63822               if (parents.length === 1) {
63823                 var way = parents[0];
63824
63825                 if (way.nodes.indexOf(entityID) !== -1) {
63826                   return actionOrthogonalize(way.id, context.projection, entityID);
63827                 }
63828               }
63829             }
63830
63831             return null;
63832           }
63833
63834           var operation = function operation() {
63835             if (!_actions.length) return;
63836
63837             var combinedAction = function combinedAction(graph, t) {
63838               _actions.forEach(function (action) {
63839                 if (!action.disabled(graph)) {
63840                   graph = action(graph, t);
63841                 }
63842               });
63843
63844               return graph;
63845             };
63846
63847             combinedAction.transitionable = true;
63848             context.perform(combinedAction, operation.annotation());
63849             window.setTimeout(function () {
63850               context.validator().validate();
63851             }, 300); // after any transition
63852           };
63853
63854           operation.available = function () {
63855             return _actions.length && selectedIDs.length === _actions.length;
63856           }; // don't cache this because the visible extent could change
63857
63858
63859           operation.disabled = function () {
63860             if (!_actions.length) return '';
63861
63862             var actionDisableds = _actions.map(function (action) {
63863               return action.disabled(context.graph());
63864             }).filter(Boolean);
63865
63866             if (actionDisableds.length === _actions.length) {
63867               // none of the features can be squared
63868               if (new Set(actionDisableds).size > 1) {
63869                 return 'multiple_blockers';
63870               }
63871
63872               return actionDisableds[0];
63873             } else if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
63874               return 'too_large';
63875             } else if (someMissing()) {
63876               return 'not_downloaded';
63877             } else if (selectedIDs.some(context.hasHiddenConnections)) {
63878               return 'connected_to_hidden';
63879             }
63880
63881             return false;
63882
63883             function someMissing() {
63884               if (context.inIntro()) return false;
63885               var osm = context.connection();
63886
63887               if (osm) {
63888                 var missing = _coords.filter(function (loc) {
63889                   return !osm.isDataLoaded(loc);
63890                 });
63891
63892                 if (missing.length) {
63893                   missing.forEach(function (loc) {
63894                     context.loadTileAtLoc(loc);
63895                   });
63896                   return true;
63897                 }
63898               }
63899
63900               return false;
63901             }
63902           };
63903
63904           operation.tooltip = function () {
63905             var disable = operation.disabled();
63906             return disable ? _t('operations.orthogonalize.' + disable + '.' + _amount) : _t('operations.orthogonalize.description.' + _type + '.' + _amount);
63907           };
63908
63909           operation.annotation = function () {
63910             return _t('operations.orthogonalize.annotation.' + _type, {
63911               n: _actions.length
63912             });
63913           };
63914
63915           operation.id = 'orthogonalize';
63916           operation.keys = [_t('operations.orthogonalize.key')];
63917           operation.title = _t('operations.orthogonalize.title');
63918           operation.behavior = behaviorOperation(context).which(operation);
63919           return operation;
63920         }
63921
63922         function operationReflectShort(context, selectedIDs) {
63923           return operationReflect(context, selectedIDs, 'short');
63924         }
63925         function operationReflectLong(context, selectedIDs) {
63926           return operationReflect(context, selectedIDs, 'long');
63927         }
63928         function operationReflect(context, selectedIDs, axis) {
63929           axis = axis || 'long';
63930           var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
63931           var nodes = utilGetAllNodes(selectedIDs, context.graph());
63932           var coords = nodes.map(function (n) {
63933             return n.loc;
63934           });
63935           var extent = utilTotalExtent(selectedIDs, context.graph());
63936
63937           var operation = function operation() {
63938             var action = actionReflect(selectedIDs, context.projection).useLongAxis(Boolean(axis === 'long'));
63939             context.perform(action, operation.annotation());
63940             window.setTimeout(function () {
63941               context.validator().validate();
63942             }, 300); // after any transition
63943           };
63944
63945           operation.available = function () {
63946             return nodes.length >= 3;
63947           }; // don't cache this because the visible extent could change
63948
63949
63950           operation.disabled = function () {
63951             if (extent.percentContainedIn(context.map().extent()) < 0.8) {
63952               return 'too_large';
63953             } else if (someMissing()) {
63954               return 'not_downloaded';
63955             } else if (selectedIDs.some(context.hasHiddenConnections)) {
63956               return 'connected_to_hidden';
63957             } else if (selectedIDs.some(incompleteRelation)) {
63958               return 'incomplete_relation';
63959             }
63960
63961             return false;
63962
63963             function someMissing() {
63964               if (context.inIntro()) return false;
63965               var osm = context.connection();
63966
63967               if (osm) {
63968                 var missing = coords.filter(function (loc) {
63969                   return !osm.isDataLoaded(loc);
63970                 });
63971
63972                 if (missing.length) {
63973                   missing.forEach(function (loc) {
63974                     context.loadTileAtLoc(loc);
63975                   });
63976                   return true;
63977                 }
63978               }
63979
63980               return false;
63981             }
63982
63983             function incompleteRelation(id) {
63984               var entity = context.entity(id);
63985               return entity.type === 'relation' && !entity.isComplete(context.graph());
63986             }
63987           };
63988
63989           operation.tooltip = function () {
63990             var disable = operation.disabled();
63991             return disable ? _t('operations.reflect.' + disable + '.' + multi) : _t('operations.reflect.description.' + axis + '.' + multi);
63992           };
63993
63994           operation.annotation = function () {
63995             return _t('operations.reflect.annotation.' + axis + '.feature', {
63996               n: selectedIDs.length
63997             });
63998           };
63999
64000           operation.id = 'reflect-' + axis;
64001           operation.keys = [_t('operations.reflect.key.' + axis)];
64002           operation.title = _t('operations.reflect.title.' + axis);
64003           operation.behavior = behaviorOperation(context).which(operation);
64004           return operation;
64005         }
64006
64007         function operationMove(context, selectedIDs) {
64008           var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
64009           var nodes = utilGetAllNodes(selectedIDs, context.graph());
64010           var coords = nodes.map(function (n) {
64011             return n.loc;
64012           });
64013           var extent = utilTotalExtent(selectedIDs, context.graph());
64014
64015           var operation = function operation() {
64016             context.enter(modeMove(context, selectedIDs));
64017           };
64018
64019           operation.available = function () {
64020             return selectedIDs.length > 0;
64021           };
64022
64023           operation.disabled = function () {
64024             if (extent.percentContainedIn(context.map().extent()) < 0.8) {
64025               return 'too_large';
64026             } else if (someMissing()) {
64027               return 'not_downloaded';
64028             } else if (selectedIDs.some(context.hasHiddenConnections)) {
64029               return 'connected_to_hidden';
64030             } else if (selectedIDs.some(incompleteRelation)) {
64031               return 'incomplete_relation';
64032             }
64033
64034             return false;
64035
64036             function someMissing() {
64037               if (context.inIntro()) return false;
64038               var osm = context.connection();
64039
64040               if (osm) {
64041                 var missing = coords.filter(function (loc) {
64042                   return !osm.isDataLoaded(loc);
64043                 });
64044
64045                 if (missing.length) {
64046                   missing.forEach(function (loc) {
64047                     context.loadTileAtLoc(loc);
64048                   });
64049                   return true;
64050                 }
64051               }
64052
64053               return false;
64054             }
64055
64056             function incompleteRelation(id) {
64057               var entity = context.entity(id);
64058               return entity.type === 'relation' && !entity.isComplete(context.graph());
64059             }
64060           };
64061
64062           operation.tooltip = function () {
64063             var disable = operation.disabled();
64064             return disable ? _t('operations.move.' + disable + '.' + multi) : _t('operations.move.description.' + multi);
64065           };
64066
64067           operation.annotation = function () {
64068             return selectedIDs.length === 1 ? _t('operations.move.annotation.' + context.graph().geometry(selectedIDs[0])) : _t('operations.move.annotation.feature', {
64069               n: selectedIDs.length
64070             });
64071           };
64072
64073           operation.id = 'move';
64074           operation.keys = [_t('operations.move.key')];
64075           operation.title = _t('operations.move.title');
64076           operation.behavior = behaviorOperation(context).which(operation);
64077           operation.mouseOnly = true;
64078           return operation;
64079         }
64080
64081         function modeRotate(context, entityIDs) {
64082           var _tolerancePx = 4; // see also behaviorDrag, behaviorSelect, modeMove
64083
64084           var mode = {
64085             id: 'rotate',
64086             button: 'browse'
64087           };
64088           var keybinding = utilKeybinding('rotate');
64089           var behaviors = [behaviorEdit(context), operationCircularize(context, entityIDs).behavior, operationDelete(context, entityIDs).behavior, operationMove(context, entityIDs).behavior, operationOrthogonalize(context, entityIDs).behavior, operationReflectLong(context, entityIDs).behavior, operationReflectShort(context, entityIDs).behavior];
64090           var annotation = entityIDs.length === 1 ? _t('operations.rotate.annotation.' + context.graph().geometry(entityIDs[0])) : _t('operations.rotate.annotation.feature', {
64091             n: entityIDs.length
64092           });
64093
64094           var _prevGraph;
64095
64096           var _prevAngle;
64097
64098           var _prevTransform;
64099
64100           var _pivot; // use pointer events on supported platforms; fallback to mouse events
64101
64102
64103           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
64104
64105           function doRotate(d3_event) {
64106             var fn;
64107
64108             if (context.graph() !== _prevGraph) {
64109               fn = context.perform;
64110             } else {
64111               fn = context.replace;
64112             } // projection changed, recalculate _pivot
64113
64114
64115             var projection = context.projection;
64116             var currTransform = projection.transform();
64117
64118             if (!_prevTransform || currTransform.k !== _prevTransform.k || currTransform.x !== _prevTransform.x || currTransform.y !== _prevTransform.y) {
64119               var nodes = utilGetAllNodes(entityIDs, context.graph());
64120               var points = nodes.map(function (n) {
64121                 return projection(n.loc);
64122               });
64123               _pivot = getPivot(points);
64124               _prevAngle = undefined;
64125             }
64126
64127             var currMouse = context.map().mouse(d3_event);
64128             var currAngle = Math.atan2(currMouse[1] - _pivot[1], currMouse[0] - _pivot[0]);
64129             if (typeof _prevAngle === 'undefined') _prevAngle = currAngle;
64130             var delta = currAngle - _prevAngle;
64131             fn(actionRotate(entityIDs, _pivot, delta, projection));
64132             _prevTransform = currTransform;
64133             _prevAngle = currAngle;
64134             _prevGraph = context.graph();
64135           }
64136
64137           function getPivot(points) {
64138             var _pivot;
64139
64140             if (points.length === 1) {
64141               _pivot = points[0];
64142             } else if (points.length === 2) {
64143               _pivot = geoVecInterp(points[0], points[1], 0.5);
64144             } else {
64145               var polygonHull = d3_polygonHull(points);
64146
64147               if (polygonHull.length === 2) {
64148                 _pivot = geoVecInterp(points[0], points[1], 0.5);
64149               } else {
64150                 _pivot = d3_polygonCentroid(d3_polygonHull(points));
64151               }
64152             }
64153
64154             return _pivot;
64155           }
64156
64157           function finish(d3_event) {
64158             d3_event.stopPropagation();
64159             context.replace(actionNoop(), annotation);
64160             context.enter(modeSelect(context, entityIDs));
64161           }
64162
64163           function cancel() {
64164             if (_prevGraph) context.pop(); // remove the rotate
64165
64166             context.enter(modeSelect(context, entityIDs));
64167           }
64168
64169           function undone() {
64170             context.enter(modeBrowse(context));
64171           }
64172
64173           mode.enter = function () {
64174             _prevGraph = null;
64175             context.features().forceVisible(entityIDs);
64176             behaviors.forEach(context.install);
64177             var downEvent;
64178             context.surface().on(_pointerPrefix + 'down.modeRotate', function (d3_event) {
64179               downEvent = d3_event;
64180             });
64181             select(window).on(_pointerPrefix + 'move.modeRotate', doRotate, true).on(_pointerPrefix + 'up.modeRotate', function (d3_event) {
64182               if (!downEvent) return;
64183               var mapNode = context.container().select('.main-map').node();
64184               var pointGetter = utilFastMouse(mapNode);
64185               var p1 = pointGetter(downEvent);
64186               var p2 = pointGetter(d3_event);
64187               var dist = geoVecLength(p1, p2);
64188               if (dist <= _tolerancePx) finish(d3_event);
64189               downEvent = null;
64190             }, true);
64191             context.history().on('undone.modeRotate', undone);
64192             keybinding.on('⎋', cancel).on('↩', finish);
64193             select(document).call(keybinding);
64194           };
64195
64196           mode.exit = function () {
64197             behaviors.forEach(context.uninstall);
64198             context.surface().on(_pointerPrefix + 'down.modeRotate', null);
64199             select(window).on(_pointerPrefix + 'move.modeRotate', null, true).on(_pointerPrefix + 'up.modeRotate', null, true);
64200             context.history().on('undone.modeRotate', null);
64201             select(document).call(keybinding.unbind);
64202             context.features().forceVisible([]);
64203           };
64204
64205           mode.selectedIDs = function () {
64206             if (!arguments.length) return entityIDs; // no assign
64207
64208             return mode;
64209           };
64210
64211           return mode;
64212         }
64213
64214         function operationRotate(context, selectedIDs) {
64215           var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
64216           var nodes = utilGetAllNodes(selectedIDs, context.graph());
64217           var coords = nodes.map(function (n) {
64218             return n.loc;
64219           });
64220           var extent = utilTotalExtent(selectedIDs, context.graph());
64221
64222           var operation = function operation() {
64223             context.enter(modeRotate(context, selectedIDs));
64224           };
64225
64226           operation.available = function () {
64227             return nodes.length >= 2;
64228           };
64229
64230           operation.disabled = function () {
64231             if (extent.percentContainedIn(context.map().extent()) < 0.8) {
64232               return 'too_large';
64233             } else if (someMissing()) {
64234               return 'not_downloaded';
64235             } else if (selectedIDs.some(context.hasHiddenConnections)) {
64236               return 'connected_to_hidden';
64237             } else if (selectedIDs.some(incompleteRelation)) {
64238               return 'incomplete_relation';
64239             }
64240
64241             return false;
64242
64243             function someMissing() {
64244               if (context.inIntro()) return false;
64245               var osm = context.connection();
64246
64247               if (osm) {
64248                 var missing = coords.filter(function (loc) {
64249                   return !osm.isDataLoaded(loc);
64250                 });
64251
64252                 if (missing.length) {
64253                   missing.forEach(function (loc) {
64254                     context.loadTileAtLoc(loc);
64255                   });
64256                   return true;
64257                 }
64258               }
64259
64260               return false;
64261             }
64262
64263             function incompleteRelation(id) {
64264               var entity = context.entity(id);
64265               return entity.type === 'relation' && !entity.isComplete(context.graph());
64266             }
64267           };
64268
64269           operation.tooltip = function () {
64270             var disable = operation.disabled();
64271             return disable ? _t('operations.rotate.' + disable + '.' + multi) : _t('operations.rotate.description.' + multi);
64272           };
64273
64274           operation.annotation = function () {
64275             return selectedIDs.length === 1 ? _t('operations.rotate.annotation.' + context.graph().geometry(selectedIDs[0])) : _t('operations.rotate.annotation.feature', {
64276               n: selectedIDs.length
64277             });
64278           };
64279
64280           operation.id = 'rotate';
64281           operation.keys = [_t('operations.rotate.key')];
64282           operation.title = _t('operations.rotate.title');
64283           operation.behavior = behaviorOperation(context).which(operation);
64284           operation.mouseOnly = true;
64285           return operation;
64286         }
64287
64288         function modeMove(context, entityIDs, baseGraph) {
64289           var _tolerancePx = 4; // see also behaviorDrag, behaviorSelect, modeRotate
64290
64291           var mode = {
64292             id: 'move',
64293             button: 'browse'
64294           };
64295           var keybinding = utilKeybinding('move');
64296           var behaviors = [behaviorEdit(context), operationCircularize(context, entityIDs).behavior, operationDelete(context, entityIDs).behavior, operationOrthogonalize(context, entityIDs).behavior, operationReflectLong(context, entityIDs).behavior, operationReflectShort(context, entityIDs).behavior, operationRotate(context, entityIDs).behavior];
64297           var annotation = entityIDs.length === 1 ? _t('operations.move.annotation.' + context.graph().geometry(entityIDs[0])) : _t('operations.move.annotation.feature', {
64298             n: entityIDs.length
64299           });
64300
64301           var _prevGraph;
64302
64303           var _cache;
64304
64305           var _origin;
64306
64307           var _nudgeInterval; // use pointer events on supported platforms; fallback to mouse events
64308
64309
64310           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
64311
64312           function doMove(nudge) {
64313             nudge = nudge || [0, 0];
64314             var fn;
64315
64316             if (_prevGraph !== context.graph()) {
64317               _cache = {};
64318               _origin = context.map().mouseCoordinates();
64319               fn = context.perform;
64320             } else {
64321               fn = context.overwrite;
64322             }
64323
64324             var currMouse = context.map().mouse();
64325             var origMouse = context.projection(_origin);
64326             var delta = geoVecSubtract(geoVecSubtract(currMouse, origMouse), nudge);
64327             fn(actionMove(entityIDs, delta, context.projection, _cache));
64328             _prevGraph = context.graph();
64329           }
64330
64331           function startNudge(nudge) {
64332             if (_nudgeInterval) window.clearInterval(_nudgeInterval);
64333             _nudgeInterval = window.setInterval(function () {
64334               context.map().pan(nudge);
64335               doMove(nudge);
64336             }, 50);
64337           }
64338
64339           function stopNudge() {
64340             if (_nudgeInterval) {
64341               window.clearInterval(_nudgeInterval);
64342               _nudgeInterval = null;
64343             }
64344           }
64345
64346           function move() {
64347             doMove();
64348             var nudge = geoViewportEdge(context.map().mouse(), context.map().dimensions());
64349
64350             if (nudge) {
64351               startNudge(nudge);
64352             } else {
64353               stopNudge();
64354             }
64355           }
64356
64357           function finish(d3_event) {
64358             d3_event.stopPropagation();
64359             context.replace(actionNoop(), annotation);
64360             context.enter(modeSelect(context, entityIDs));
64361             stopNudge();
64362           }
64363
64364           function cancel() {
64365             if (baseGraph) {
64366               while (context.graph() !== baseGraph) {
64367                 context.pop();
64368               } // reset to baseGraph
64369
64370
64371               context.enter(modeBrowse(context));
64372             } else {
64373               if (_prevGraph) context.pop(); // remove the move
64374
64375               context.enter(modeSelect(context, entityIDs));
64376             }
64377
64378             stopNudge();
64379           }
64380
64381           function undone() {
64382             context.enter(modeBrowse(context));
64383           }
64384
64385           mode.enter = function () {
64386             _origin = context.map().mouseCoordinates();
64387             _prevGraph = null;
64388             _cache = {};
64389             context.features().forceVisible(entityIDs);
64390             behaviors.forEach(context.install);
64391             var downEvent;
64392             context.surface().on(_pointerPrefix + 'down.modeMove', function (d3_event) {
64393               downEvent = d3_event;
64394             });
64395             select(window).on(_pointerPrefix + 'move.modeMove', move, true).on(_pointerPrefix + 'up.modeMove', function (d3_event) {
64396               if (!downEvent) return;
64397               var mapNode = context.container().select('.main-map').node();
64398               var pointGetter = utilFastMouse(mapNode);
64399               var p1 = pointGetter(downEvent);
64400               var p2 = pointGetter(d3_event);
64401               var dist = geoVecLength(p1, p2);
64402               if (dist <= _tolerancePx) finish(d3_event);
64403               downEvent = null;
64404             }, true);
64405             context.history().on('undone.modeMove', undone);
64406             keybinding.on('⎋', cancel).on('↩', finish);
64407             select(document).call(keybinding);
64408           };
64409
64410           mode.exit = function () {
64411             stopNudge();
64412             behaviors.forEach(function (behavior) {
64413               context.uninstall(behavior);
64414             });
64415             context.surface().on(_pointerPrefix + 'down.modeMove', null);
64416             select(window).on(_pointerPrefix + 'move.modeMove', null, true).on(_pointerPrefix + 'up.modeMove', null, true);
64417             context.history().on('undone.modeMove', null);
64418             select(document).call(keybinding.unbind);
64419             context.features().forceVisible([]);
64420           };
64421
64422           mode.selectedIDs = function () {
64423             if (!arguments.length) return entityIDs; // no assign
64424
64425             return mode;
64426           };
64427
64428           return mode;
64429         }
64430
64431         function behaviorPaste(context) {
64432           function doPaste(d3_event) {
64433             // prevent paste during low zoom selection
64434             if (!context.map().withinEditableZoom()) return;
64435             d3_event.preventDefault();
64436             var baseGraph = context.graph();
64437             var mouse = context.map().mouse();
64438             var projection = context.projection;
64439             var viewport = geoExtent(projection.clipExtent()).polygon();
64440             if (!geoPointInPolygon(mouse, viewport)) return;
64441             var oldIDs = context.copyIDs();
64442             if (!oldIDs.length) return;
64443             var extent = geoExtent();
64444             var oldGraph = context.copyGraph();
64445             var newIDs = [];
64446             var action = actionCopyEntities(oldIDs, oldGraph);
64447             context.perform(action);
64448             var copies = action.copies();
64449             var originals = new Set();
64450             Object.values(copies).forEach(function (entity) {
64451               originals.add(entity.id);
64452             });
64453
64454             for (var id in copies) {
64455               var oldEntity = oldGraph.entity(id);
64456               var newEntity = copies[id];
64457
64458               extent._extend(oldEntity.extent(oldGraph)); // Exclude child nodes from newIDs if their parent way was also copied.
64459
64460
64461               var parents = context.graph().parentWays(newEntity);
64462               var parentCopied = parents.some(function (parent) {
64463                 return originals.has(parent.id);
64464               });
64465
64466               if (!parentCopied) {
64467                 newIDs.push(newEntity.id);
64468               }
64469             } // Put pasted objects where mouse pointer is..
64470
64471
64472             var copyPoint = context.copyLonLat() && projection(context.copyLonLat()) || projection(extent.center());
64473             var delta = geoVecSubtract(mouse, copyPoint);
64474             context.perform(actionMove(newIDs, delta, projection));
64475             context.enter(modeMove(context, newIDs, baseGraph));
64476           }
64477
64478           function behavior() {
64479             context.keybinding().on(uiCmd('⌘V'), doPaste);
64480             return behavior;
64481           }
64482
64483           behavior.off = function () {
64484             context.keybinding().off(uiCmd('⌘V'));
64485           };
64486
64487           return behavior;
64488         }
64489
64490         /*
64491             `behaviorDrag` is like `d3_behavior.drag`, with the following differences:
64492
64493             * The `origin` function is expected to return an [x, y] tuple rather than an
64494               {x, y} object.
64495             * The events are `start`, `move`, and `end`.
64496               (https://github.com/mbostock/d3/issues/563)
64497             * The `start` event is not dispatched until the first cursor movement occurs.
64498               (https://github.com/mbostock/d3/pull/368)
64499             * The `move` event has a `point` and `delta` [x, y] tuple properties rather
64500               than `x`, `y`, `dx`, and `dy` properties.
64501             * The `end` event is not dispatched if no movement occurs.
64502             * An `off` function is available that unbinds the drag's internal event handlers.
64503          */
64504
64505         function behaviorDrag() {
64506           var dispatch = dispatch$8('start', 'move', 'end'); // see also behaviorSelect
64507
64508           var _tolerancePx = 1; // keep this low to facilitate pixel-perfect micromapping
64509
64510           var _penTolerancePx = 4; // styluses can be touchy so require greater movement - #1981
64511
64512           var _origin = null;
64513           var _selector = '';
64514
64515           var _targetNode;
64516
64517           var _targetEntity;
64518
64519           var _surface;
64520
64521           var _pointerId; // use pointer events on supported platforms; fallback to mouse events
64522
64523
64524           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
64525
64526           var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect');
64527
64528           var d3_event_userSelectSuppress = function d3_event_userSelectSuppress() {
64529             var selection$1 = selection();
64530             var select = selection$1.style(d3_event_userSelectProperty);
64531             selection$1.style(d3_event_userSelectProperty, 'none');
64532             return function () {
64533               selection$1.style(d3_event_userSelectProperty, select);
64534             };
64535           };
64536
64537           function pointerdown(d3_event) {
64538             if (_pointerId) return;
64539             _pointerId = d3_event.pointerId || 'mouse';
64540             _targetNode = this; // only force reflow once per drag
64541
64542             var pointerLocGetter = utilFastMouse(_surface || _targetNode.parentNode);
64543             var offset;
64544             var startOrigin = pointerLocGetter(d3_event);
64545             var started = false;
64546             var selectEnable = d3_event_userSelectSuppress();
64547             select(window).on(_pointerPrefix + 'move.drag', pointermove).on(_pointerPrefix + 'up.drag pointercancel.drag', pointerup, true);
64548
64549             if (_origin) {
64550               offset = _origin.call(_targetNode, _targetEntity);
64551               offset = [offset[0] - startOrigin[0], offset[1] - startOrigin[1]];
64552             } else {
64553               offset = [0, 0];
64554             }
64555
64556             d3_event.stopPropagation();
64557
64558             function pointermove(d3_event) {
64559               if (_pointerId !== (d3_event.pointerId || 'mouse')) return;
64560               var p = pointerLocGetter(d3_event);
64561
64562               if (!started) {
64563                 var dist = geoVecLength(startOrigin, p);
64564                 var tolerance = d3_event.pointerType === 'pen' ? _penTolerancePx : _tolerancePx; // don't start until the drag has actually moved somewhat
64565
64566                 if (dist < tolerance) return;
64567                 started = true;
64568                 dispatch.call('start', this, d3_event, _targetEntity); // Don't send a `move` event in the same cycle as `start` since dragging
64569                 // a midpoint will convert the target to a node.
64570               } else {
64571                 startOrigin = p;
64572                 d3_event.stopPropagation();
64573                 d3_event.preventDefault();
64574                 var dx = p[0] - startOrigin[0];
64575                 var dy = p[1] - startOrigin[1];
64576                 dispatch.call('move', this, d3_event, _targetEntity, [p[0] + offset[0], p[1] + offset[1]], [dx, dy]);
64577               }
64578             }
64579
64580             function pointerup(d3_event) {
64581               if (_pointerId !== (d3_event.pointerId || 'mouse')) return;
64582               _pointerId = null;
64583
64584               if (started) {
64585                 dispatch.call('end', this, d3_event, _targetEntity);
64586                 d3_event.preventDefault();
64587               }
64588
64589               select(window).on(_pointerPrefix + 'move.drag', null).on(_pointerPrefix + 'up.drag pointercancel.drag', null);
64590               selectEnable();
64591             }
64592           }
64593
64594           function behavior(selection) {
64595             var matchesSelector = utilPrefixDOMProperty('matchesSelector');
64596             var delegate = pointerdown;
64597
64598             if (_selector) {
64599               delegate = function delegate(d3_event) {
64600                 var root = this;
64601                 var target = d3_event.target;
64602
64603                 for (; target && target !== root; target = target.parentNode) {
64604                   var datum = target.__data__;
64605                   _targetEntity = datum instanceof osmNote ? datum : datum && datum.properties && datum.properties.entity;
64606
64607                   if (_targetEntity && target[matchesSelector](_selector)) {
64608                     return pointerdown.call(target, d3_event);
64609                   }
64610                 }
64611               };
64612             }
64613
64614             selection.on(_pointerPrefix + 'down.drag' + _selector, delegate);
64615           }
64616
64617           behavior.off = function (selection) {
64618             selection.on(_pointerPrefix + 'down.drag' + _selector, null);
64619           };
64620
64621           behavior.selector = function (_) {
64622             if (!arguments.length) return _selector;
64623             _selector = _;
64624             return behavior;
64625           };
64626
64627           behavior.origin = function (_) {
64628             if (!arguments.length) return _origin;
64629             _origin = _;
64630             return behavior;
64631           };
64632
64633           behavior.cancel = function () {
64634             select(window).on(_pointerPrefix + 'move.drag', null).on(_pointerPrefix + 'up.drag pointercancel.drag', null);
64635             return behavior;
64636           };
64637
64638           behavior.targetNode = function (_) {
64639             if (!arguments.length) return _targetNode;
64640             _targetNode = _;
64641             return behavior;
64642           };
64643
64644           behavior.targetEntity = function (_) {
64645             if (!arguments.length) return _targetEntity;
64646             _targetEntity = _;
64647             return behavior;
64648           };
64649
64650           behavior.surface = function (_) {
64651             if (!arguments.length) return _surface;
64652             _surface = _;
64653             return behavior;
64654           };
64655
64656           return utilRebind(behavior, dispatch, 'on');
64657         }
64658
64659         function modeDragNode(context) {
64660           var mode = {
64661             id: 'drag-node',
64662             button: 'browse'
64663           };
64664           var hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover);
64665           var edit = behaviorEdit(context);
64666
64667           var _nudgeInterval;
64668
64669           var _restoreSelectedIDs = [];
64670           var _wasMidpoint = false;
64671           var _isCancelled = false;
64672
64673           var _activeEntity;
64674
64675           var _startLoc;
64676
64677           var _lastLoc;
64678
64679           function startNudge(d3_event, entity, nudge) {
64680             if (_nudgeInterval) window.clearInterval(_nudgeInterval);
64681             _nudgeInterval = window.setInterval(function () {
64682               context.map().pan(nudge);
64683               doMove(d3_event, entity, nudge);
64684             }, 50);
64685           }
64686
64687           function stopNudge() {
64688             if (_nudgeInterval) {
64689               window.clearInterval(_nudgeInterval);
64690               _nudgeInterval = null;
64691             }
64692           }
64693
64694           function moveAnnotation(entity) {
64695             return _t('operations.move.annotation.' + entity.geometry(context.graph()));
64696           }
64697
64698           function connectAnnotation(nodeEntity, targetEntity) {
64699             var nodeGeometry = nodeEntity.geometry(context.graph());
64700             var targetGeometry = targetEntity.geometry(context.graph());
64701
64702             if (nodeGeometry === 'vertex' && targetGeometry === 'vertex') {
64703               var nodeParentWayIDs = context.graph().parentWays(nodeEntity);
64704               var targetParentWayIDs = context.graph().parentWays(targetEntity);
64705               var sharedParentWays = utilArrayIntersection(nodeParentWayIDs, targetParentWayIDs); // if both vertices are part of the same way
64706
64707               if (sharedParentWays.length !== 0) {
64708                 // if the nodes are next to each other, they are merged
64709                 if (sharedParentWays[0].areAdjacent(nodeEntity.id, targetEntity.id)) {
64710                   return _t('operations.connect.annotation.from_vertex.to_adjacent_vertex');
64711                 }
64712
64713                 return _t('operations.connect.annotation.from_vertex.to_sibling_vertex');
64714               }
64715             }
64716
64717             return _t('operations.connect.annotation.from_' + nodeGeometry + '.to_' + targetGeometry);
64718           }
64719
64720           function shouldSnapToNode(target) {
64721             if (!_activeEntity) return false;
64722             return _activeEntity.geometry(context.graph()) !== 'vertex' || target.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(target, context.graph());
64723           }
64724
64725           function origin(entity) {
64726             return context.projection(entity.loc);
64727           }
64728
64729           function keydown(d3_event) {
64730             if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
64731               if (context.surface().classed('nope')) {
64732                 context.surface().classed('nope-suppressed', true);
64733               }
64734
64735               context.surface().classed('nope', false).classed('nope-disabled', true);
64736             }
64737           }
64738
64739           function keyup(d3_event) {
64740             if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
64741               if (context.surface().classed('nope-suppressed')) {
64742                 context.surface().classed('nope', true);
64743               }
64744
64745               context.surface().classed('nope-suppressed', false).classed('nope-disabled', false);
64746             }
64747           }
64748
64749           function start(d3_event, entity) {
64750             _wasMidpoint = entity.type === 'midpoint';
64751             var hasHidden = context.features().hasHiddenConnections(entity, context.graph());
64752             _isCancelled = !context.editable() || d3_event.shiftKey || hasHidden;
64753
64754             if (_isCancelled) {
64755               if (hasHidden) {
64756                 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t('modes.drag_node.connected_to_hidden'))();
64757               }
64758
64759               return drag.cancel();
64760             }
64761
64762             if (_wasMidpoint) {
64763               var midpoint = entity;
64764               entity = osmNode();
64765               context.perform(actionAddMidpoint(midpoint, entity));
64766               entity = context.entity(entity.id); // get post-action entity
64767
64768               var vertex = context.surface().selectAll('.' + entity.id);
64769               drag.targetNode(vertex.node()).targetEntity(entity);
64770             } else {
64771               context.perform(actionNoop());
64772             }
64773
64774             _activeEntity = entity;
64775             _startLoc = entity.loc;
64776             hover.ignoreVertex(entity.geometry(context.graph()) === 'vertex');
64777             context.surface().selectAll('.' + _activeEntity.id).classed('active', true);
64778             context.enter(mode);
64779           } // related code
64780           // - `behavior/draw.js` `datum()`
64781
64782
64783           function datum(d3_event) {
64784             if (!d3_event || d3_event.altKey) {
64785               return {};
64786             } else {
64787               // When dragging, snap only to touch targets..
64788               // (this excludes area fills and active drawing elements)
64789               var d = d3_event.target.__data__;
64790               return d && d.properties && d.properties.target ? d : {};
64791             }
64792           }
64793
64794           function doMove(d3_event, entity, nudge) {
64795             nudge = nudge || [0, 0];
64796             var currPoint = d3_event && d3_event.point || context.projection(_lastLoc);
64797             var currMouse = geoVecSubtract(currPoint, nudge);
64798             var loc = context.projection.invert(currMouse);
64799             var target, edge;
64800
64801             if (!_nudgeInterval) {
64802               // If not nudging at the edge of the viewport, try to snap..
64803               // related code
64804               // - `mode/drag_node.js`     `doMove()`
64805               // - `behavior/draw.js`      `click()`
64806               // - `behavior/draw_way.js`  `move()`
64807               var d = datum(d3_event);
64808               target = d && d.properties && d.properties.entity;
64809               var targetLoc = target && target.loc;
64810               var targetNodes = d && d.properties && d.properties.nodes;
64811
64812               if (targetLoc) {
64813                 // snap to node/vertex - a point target with `.loc`
64814                 if (shouldSnapToNode(target)) {
64815                   loc = targetLoc;
64816                 }
64817               } else if (targetNodes) {
64818                 // snap to way - a line target with `.nodes`
64819                 edge = geoChooseEdge(targetNodes, context.map().mouse(), context.projection, end.id);
64820
64821                 if (edge) {
64822                   loc = edge.loc;
64823                 }
64824               }
64825             }
64826
64827             context.replace(actionMoveNode(entity.id, loc)); // Below here: validations
64828
64829             var isInvalid = false; // Check if this connection to `target` could cause relations to break..
64830
64831             if (target) {
64832               isInvalid = hasRelationConflict(entity, target, edge, context.graph());
64833             } // Check if this drag causes the geometry to break..
64834
64835
64836             if (!isInvalid) {
64837               isInvalid = hasInvalidGeometry(entity, context.graph());
64838             }
64839
64840             var nope = context.surface().classed('nope');
64841
64842             if (isInvalid === 'relation' || isInvalid === 'restriction') {
64843               if (!nope) {
64844                 // about to nope - show hint
64845                 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html('operations.connect.' + isInvalid, {
64846                   relation: _mainPresetIndex.item('type/restriction').name()
64847                 }))();
64848               }
64849             } else if (isInvalid) {
64850               var errorID = isInvalid === 'line' ? 'lines' : 'areas';
64851               context.ui().flash.duration(3000).iconName('#iD-icon-no').label(_t.html('self_intersection.error.' + errorID))();
64852             } else {
64853               if (nope) {
64854                 // about to un-nope, remove hint
64855                 context.ui().flash.duration(1).label('')();
64856               }
64857             }
64858
64859             var nopeDisabled = context.surface().classed('nope-disabled');
64860
64861             if (nopeDisabled) {
64862               context.surface().classed('nope', false).classed('nope-suppressed', isInvalid);
64863             } else {
64864               context.surface().classed('nope', isInvalid).classed('nope-suppressed', false);
64865             }
64866
64867             _lastLoc = loc;
64868           } // Uses `actionConnect.disabled()` to know whether this connection is ok..
64869
64870
64871           function hasRelationConflict(entity, target, edge, graph) {
64872             var testGraph = graph.update(); // copy
64873             // if snapping to way - add midpoint there and consider that the target..
64874
64875             if (edge) {
64876               var midpoint = osmNode();
64877               var action = actionAddMidpoint({
64878                 loc: edge.loc,
64879                 edge: [target.nodes[edge.index - 1], target.nodes[edge.index]]
64880               }, midpoint);
64881               testGraph = action(testGraph);
64882               target = midpoint;
64883             } // can we connect to it?
64884
64885
64886             var ids = [entity.id, target.id];
64887             return actionConnect(ids).disabled(testGraph);
64888           }
64889
64890           function hasInvalidGeometry(entity, graph) {
64891             var parents = graph.parentWays(entity);
64892             var i, j, k;
64893
64894             for (i = 0; i < parents.length; i++) {
64895               var parent = parents[i];
64896               var nodes = [];
64897               var activeIndex = null; // which multipolygon ring contains node being dragged
64898               // test any parent multipolygons for valid geometry
64899
64900               var relations = graph.parentRelations(parent);
64901
64902               for (j = 0; j < relations.length; j++) {
64903                 if (!relations[j].isMultipolygon()) continue;
64904                 var rings = osmJoinWays(relations[j].members, graph); // find active ring and test it for self intersections
64905
64906                 for (k = 0; k < rings.length; k++) {
64907                   nodes = rings[k].nodes;
64908
64909                   if (nodes.find(function (n) {
64910                     return n.id === entity.id;
64911                   })) {
64912                     activeIndex = k;
64913
64914                     if (geoHasSelfIntersections(nodes, entity.id)) {
64915                       return 'multipolygonMember';
64916                     }
64917                   }
64918
64919                   rings[k].coords = nodes.map(function (n) {
64920                     return n.loc;
64921                   });
64922                 } // test active ring for intersections with other rings in the multipolygon
64923
64924
64925                 for (k = 0; k < rings.length; k++) {
64926                   if (k === activeIndex) continue; // make sure active ring doesn't cross passive rings
64927
64928                   if (geoHasLineIntersections(rings[activeIndex].nodes, rings[k].nodes, entity.id)) {
64929                     return 'multipolygonRing';
64930                   }
64931                 }
64932               } // If we still haven't tested this node's parent way for self-intersections.
64933               // (because it's not a member of a multipolygon), test it now.
64934
64935
64936               if (activeIndex === null) {
64937                 nodes = parent.nodes.map(function (nodeID) {
64938                   return graph.entity(nodeID);
64939                 });
64940
64941                 if (nodes.length && geoHasSelfIntersections(nodes, entity.id)) {
64942                   return parent.geometry(graph);
64943                 }
64944               }
64945             }
64946
64947             return false;
64948           }
64949
64950           function move(d3_event, entity, point) {
64951             if (_isCancelled) return;
64952             d3_event.stopPropagation();
64953             context.surface().classed('nope-disabled', d3_event.altKey);
64954             _lastLoc = context.projection.invert(point);
64955             doMove(d3_event, entity);
64956             var nudge = geoViewportEdge(point, context.map().dimensions());
64957
64958             if (nudge) {
64959               startNudge(d3_event, entity, nudge);
64960             } else {
64961               stopNudge();
64962             }
64963           }
64964
64965           function end(d3_event, entity) {
64966             if (_isCancelled) return;
64967             var wasPoint = entity.geometry(context.graph()) === 'point';
64968             var d = datum(d3_event);
64969             var nope = d && d.properties && d.properties.nope || context.surface().classed('nope');
64970             var target = d && d.properties && d.properties.entity; // entity to snap to
64971
64972             if (nope) {
64973               // bounce back
64974               context.perform(_actionBounceBack(entity.id, _startLoc));
64975             } else if (target && target.type === 'way') {
64976               var choice = geoChooseEdge(context.graph().childNodes(target), context.map().mouse(), context.projection, entity.id);
64977               context.replace(actionAddMidpoint({
64978                 loc: choice.loc,
64979                 edge: [target.nodes[choice.index - 1], target.nodes[choice.index]]
64980               }, entity), connectAnnotation(entity, target));
64981             } else if (target && target.type === 'node' && shouldSnapToNode(target)) {
64982               context.replace(actionConnect([target.id, entity.id]), connectAnnotation(entity, target));
64983             } else if (_wasMidpoint) {
64984               context.replace(actionNoop(), _t('operations.add.annotation.vertex'));
64985             } else {
64986               context.replace(actionNoop(), moveAnnotation(entity));
64987             }
64988
64989             if (wasPoint) {
64990               context.enter(modeSelect(context, [entity.id]));
64991             } else {
64992               var reselection = _restoreSelectedIDs.filter(function (id) {
64993                 return context.graph().hasEntity(id);
64994               });
64995
64996               if (reselection.length) {
64997                 context.enter(modeSelect(context, reselection));
64998               } else {
64999                 context.enter(modeBrowse(context));
65000               }
65001             }
65002           }
65003
65004           function _actionBounceBack(nodeID, toLoc) {
65005             var moveNode = actionMoveNode(nodeID, toLoc);
65006
65007             var action = function action(graph, t) {
65008               // last time through, pop off the bounceback perform.
65009               // it will then overwrite the initial perform with a moveNode that does nothing
65010               if (t === 1) context.pop();
65011               return moveNode(graph, t);
65012             };
65013
65014             action.transitionable = true;
65015             return action;
65016           }
65017
65018           function cancel() {
65019             drag.cancel();
65020             context.enter(modeBrowse(context));
65021           }
65022
65023           var drag = behaviorDrag().selector('.layer-touch.points .target').surface(context.container().select('.main-map').node()).origin(origin).on('start', start).on('move', move).on('end', end);
65024
65025           mode.enter = function () {
65026             context.install(hover);
65027             context.install(edit);
65028             select(window).on('keydown.dragNode', keydown).on('keyup.dragNode', keyup);
65029             context.history().on('undone.drag-node', cancel);
65030           };
65031
65032           mode.exit = function () {
65033             context.ui().sidebar.hover.cancel();
65034             context.uninstall(hover);
65035             context.uninstall(edit);
65036             select(window).on('keydown.dragNode', null).on('keyup.dragNode', null);
65037             context.history().on('undone.drag-node', null);
65038             _activeEntity = null;
65039             context.surface().classed('nope', false).classed('nope-suppressed', false).classed('nope-disabled', false).selectAll('.active').classed('active', false);
65040             stopNudge();
65041           };
65042
65043           mode.selectedIDs = function () {
65044             if (!arguments.length) return _activeEntity ? [_activeEntity.id] : []; // no assign
65045
65046             return mode;
65047           };
65048
65049           mode.activeID = function () {
65050             if (!arguments.length) return _activeEntity && _activeEntity.id; // no assign
65051
65052             return mode;
65053           };
65054
65055           mode.restoreSelectedIDs = function (_) {
65056             if (!arguments.length) return _restoreSelectedIDs;
65057             _restoreSelectedIDs = _;
65058             return mode;
65059           };
65060
65061           mode.behavior = drag;
65062           return mode;
65063         }
65064
65065         var $$3 = _export;
65066         var NativePromise = nativePromiseConstructor;
65067         var fails$1 = fails$V;
65068         var getBuiltIn = getBuiltIn$b;
65069         var isCallable = isCallable$r;
65070         var speciesConstructor = speciesConstructor$5;
65071         var promiseResolve = promiseResolve$2;
65072         var redefine$1 = redefine$h.exports;
65073
65074         // Safari bug https://bugs.webkit.org/show_bug.cgi?id=200829
65075         var NON_GENERIC = !!NativePromise && fails$1(function () {
65076           // eslint-disable-next-line unicorn/no-thenable -- required for testing
65077           NativePromise.prototype['finally'].call({ then: function () { /* empty */ } }, function () { /* empty */ });
65078         });
65079
65080         // `Promise.prototype.finally` method
65081         // https://tc39.es/ecma262/#sec-promise.prototype.finally
65082         $$3({ target: 'Promise', proto: true, real: true, forced: NON_GENERIC }, {
65083           'finally': function (onFinally) {
65084             var C = speciesConstructor(this, getBuiltIn('Promise'));
65085             var isFunction = isCallable(onFinally);
65086             return this.then(
65087               isFunction ? function (x) {
65088                 return promiseResolve(C, onFinally()).then(function () { return x; });
65089               } : onFinally,
65090               isFunction ? function (e) {
65091                 return promiseResolve(C, onFinally()).then(function () { throw e; });
65092               } : onFinally
65093             );
65094           }
65095         });
65096
65097         // makes sure that native promise-based APIs `Promise#finally` properly works with patched `Promise#then`
65098         if (isCallable(NativePromise)) {
65099           var method = getBuiltIn('Promise').prototype['finally'];
65100           if (NativePromise.prototype['finally'] !== method) {
65101             redefine$1(NativePromise.prototype, 'finally', method, { unsafe: true });
65102           }
65103         }
65104
65105         function quickselect(arr, k, left, right, compare) {
65106           quickselectStep(arr, k, left || 0, right || arr.length - 1, compare || defaultCompare);
65107         }
65108
65109         function quickselectStep(arr, k, left, right, compare) {
65110           while (right > left) {
65111             if (right - left > 600) {
65112               var n = right - left + 1;
65113               var m = k - left + 1;
65114               var z = Math.log(n);
65115               var s = 0.5 * Math.exp(2 * z / 3);
65116               var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
65117               var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
65118               var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
65119               quickselectStep(arr, k, newLeft, newRight, compare);
65120             }
65121
65122             var t = arr[k];
65123             var i = left;
65124             var j = right;
65125             swap(arr, left, k);
65126             if (compare(arr[right], t) > 0) swap(arr, left, right);
65127
65128             while (i < j) {
65129               swap(arr, i, j);
65130               i++;
65131               j--;
65132
65133               while (compare(arr[i], t) < 0) {
65134                 i++;
65135               }
65136
65137               while (compare(arr[j], t) > 0) {
65138                 j--;
65139               }
65140             }
65141
65142             if (compare(arr[left], t) === 0) swap(arr, left, j);else {
65143               j++;
65144               swap(arr, j, right);
65145             }
65146             if (j <= k) left = j + 1;
65147             if (k <= j) right = j - 1;
65148           }
65149         }
65150
65151         function swap(arr, i, j) {
65152           var tmp = arr[i];
65153           arr[i] = arr[j];
65154           arr[j] = tmp;
65155         }
65156
65157         function defaultCompare(a, b) {
65158           return a < b ? -1 : a > b ? 1 : 0;
65159         }
65160
65161         var RBush = /*#__PURE__*/function () {
65162           function RBush() {
65163             var maxEntries = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 9;
65164
65165             _classCallCheck$1(this, RBush);
65166
65167             // max entries in a node is 9 by default; min node fill is 40% for best performance
65168             this._maxEntries = Math.max(4, maxEntries);
65169             this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
65170             this.clear();
65171           }
65172
65173           _createClass$1(RBush, [{
65174             key: "all",
65175             value: function all() {
65176               return this._all(this.data, []);
65177             }
65178           }, {
65179             key: "search",
65180             value: function search(bbox) {
65181               var node = this.data;
65182               var result = [];
65183               if (!intersects(bbox, node)) return result;
65184               var toBBox = this.toBBox;
65185               var nodesToSearch = [];
65186
65187               while (node) {
65188                 for (var i = 0; i < node.children.length; i++) {
65189                   var child = node.children[i];
65190                   var childBBox = node.leaf ? toBBox(child) : child;
65191
65192                   if (intersects(bbox, childBBox)) {
65193                     if (node.leaf) result.push(child);else if (contains(bbox, childBBox)) this._all(child, result);else nodesToSearch.push(child);
65194                   }
65195                 }
65196
65197                 node = nodesToSearch.pop();
65198               }
65199
65200               return result;
65201             }
65202           }, {
65203             key: "collides",
65204             value: function collides(bbox) {
65205               var node = this.data;
65206               if (!intersects(bbox, node)) return false;
65207               var nodesToSearch = [];
65208
65209               while (node) {
65210                 for (var i = 0; i < node.children.length; i++) {
65211                   var child = node.children[i];
65212                   var childBBox = node.leaf ? this.toBBox(child) : child;
65213
65214                   if (intersects(bbox, childBBox)) {
65215                     if (node.leaf || contains(bbox, childBBox)) return true;
65216                     nodesToSearch.push(child);
65217                   }
65218                 }
65219
65220                 node = nodesToSearch.pop();
65221               }
65222
65223               return false;
65224             }
65225           }, {
65226             key: "load",
65227             value: function load(data) {
65228               if (!(data && data.length)) return this;
65229
65230               if (data.length < this._minEntries) {
65231                 for (var i = 0; i < data.length; i++) {
65232                   this.insert(data[i]);
65233                 }
65234
65235                 return this;
65236               } // recursively build the tree with the given data from scratch using OMT algorithm
65237
65238
65239               var node = this._build(data.slice(), 0, data.length - 1, 0);
65240
65241               if (!this.data.children.length) {
65242                 // save as is if tree is empty
65243                 this.data = node;
65244               } else if (this.data.height === node.height) {
65245                 // split root if trees have the same height
65246                 this._splitRoot(this.data, node);
65247               } else {
65248                 if (this.data.height < node.height) {
65249                   // swap trees if inserted one is bigger
65250                   var tmpNode = this.data;
65251                   this.data = node;
65252                   node = tmpNode;
65253                 } // insert the small tree into the large tree at appropriate level
65254
65255
65256                 this._insert(node, this.data.height - node.height - 1, true);
65257               }
65258
65259               return this;
65260             }
65261           }, {
65262             key: "insert",
65263             value: function insert(item) {
65264               if (item) this._insert(item, this.data.height - 1);
65265               return this;
65266             }
65267           }, {
65268             key: "clear",
65269             value: function clear() {
65270               this.data = createNode([]);
65271               return this;
65272             }
65273           }, {
65274             key: "remove",
65275             value: function remove(item, equalsFn) {
65276               if (!item) return this;
65277               var node = this.data;
65278               var bbox = this.toBBox(item);
65279               var path = [];
65280               var indexes = [];
65281               var i, parent, goingUp; // depth-first iterative tree traversal
65282
65283               while (node || path.length) {
65284                 if (!node) {
65285                   // go up
65286                   node = path.pop();
65287                   parent = path[path.length - 1];
65288                   i = indexes.pop();
65289                   goingUp = true;
65290                 }
65291
65292                 if (node.leaf) {
65293                   // check current node
65294                   var index = findItem(item, node.children, equalsFn);
65295
65296                   if (index !== -1) {
65297                     // item found, remove the item and condense tree upwards
65298                     node.children.splice(index, 1);
65299                     path.push(node);
65300
65301                     this._condense(path);
65302
65303                     return this;
65304                   }
65305                 }
65306
65307                 if (!goingUp && !node.leaf && contains(node, bbox)) {
65308                   // go down
65309                   path.push(node);
65310                   indexes.push(i);
65311                   i = 0;
65312                   parent = node;
65313                   node = node.children[0];
65314                 } else if (parent) {
65315                   // go right
65316                   i++;
65317                   node = parent.children[i];
65318                   goingUp = false;
65319                 } else node = null; // nothing found
65320
65321               }
65322
65323               return this;
65324             }
65325           }, {
65326             key: "toBBox",
65327             value: function toBBox(item) {
65328               return item;
65329             }
65330           }, {
65331             key: "compareMinX",
65332             value: function compareMinX(a, b) {
65333               return a.minX - b.minX;
65334             }
65335           }, {
65336             key: "compareMinY",
65337             value: function compareMinY(a, b) {
65338               return a.minY - b.minY;
65339             }
65340           }, {
65341             key: "toJSON",
65342             value: function toJSON() {
65343               return this.data;
65344             }
65345           }, {
65346             key: "fromJSON",
65347             value: function fromJSON(data) {
65348               this.data = data;
65349               return this;
65350             }
65351           }, {
65352             key: "_all",
65353             value: function _all(node, result) {
65354               var nodesToSearch = [];
65355
65356               while (node) {
65357                 if (node.leaf) result.push.apply(result, _toConsumableArray(node.children));else nodesToSearch.push.apply(nodesToSearch, _toConsumableArray(node.children));
65358                 node = nodesToSearch.pop();
65359               }
65360
65361               return result;
65362             }
65363           }, {
65364             key: "_build",
65365             value: function _build(items, left, right, height) {
65366               var N = right - left + 1;
65367               var M = this._maxEntries;
65368               var node;
65369
65370               if (N <= M) {
65371                 // reached leaf level; return leaf
65372                 node = createNode(items.slice(left, right + 1));
65373                 calcBBox(node, this.toBBox);
65374                 return node;
65375               }
65376
65377               if (!height) {
65378                 // target height of the bulk-loaded tree
65379                 height = Math.ceil(Math.log(N) / Math.log(M)); // target number of root entries to maximize storage utilization
65380
65381                 M = Math.ceil(N / Math.pow(M, height - 1));
65382               }
65383
65384               node = createNode([]);
65385               node.leaf = false;
65386               node.height = height; // split the items into M mostly square tiles
65387
65388               var N2 = Math.ceil(N / M);
65389               var N1 = N2 * Math.ceil(Math.sqrt(M));
65390               multiSelect(items, left, right, N1, this.compareMinX);
65391
65392               for (var i = left; i <= right; i += N1) {
65393                 var right2 = Math.min(i + N1 - 1, right);
65394                 multiSelect(items, i, right2, N2, this.compareMinY);
65395
65396                 for (var j = i; j <= right2; j += N2) {
65397                   var right3 = Math.min(j + N2 - 1, right2); // pack each entry recursively
65398
65399                   node.children.push(this._build(items, j, right3, height - 1));
65400                 }
65401               }
65402
65403               calcBBox(node, this.toBBox);
65404               return node;
65405             }
65406           }, {
65407             key: "_chooseSubtree",
65408             value: function _chooseSubtree(bbox, node, level, path) {
65409               while (true) {
65410                 path.push(node);
65411                 if (node.leaf || path.length - 1 === level) break;
65412                 var minArea = Infinity;
65413                 var minEnlargement = Infinity;
65414                 var targetNode = void 0;
65415
65416                 for (var i = 0; i < node.children.length; i++) {
65417                   var child = node.children[i];
65418                   var area = bboxArea(child);
65419                   var enlargement = enlargedArea(bbox, child) - area; // choose entry with the least area enlargement
65420
65421                   if (enlargement < minEnlargement) {
65422                     minEnlargement = enlargement;
65423                     minArea = area < minArea ? area : minArea;
65424                     targetNode = child;
65425                   } else if (enlargement === minEnlargement) {
65426                     // otherwise choose one with the smallest area
65427                     if (area < minArea) {
65428                       minArea = area;
65429                       targetNode = child;
65430                     }
65431                   }
65432                 }
65433
65434                 node = targetNode || node.children[0];
65435               }
65436
65437               return node;
65438             }
65439           }, {
65440             key: "_insert",
65441             value: function _insert(item, level, isNode) {
65442               var bbox = isNode ? item : this.toBBox(item);
65443               var insertPath = []; // find the best node for accommodating the item, saving all nodes along the path too
65444
65445               var node = this._chooseSubtree(bbox, this.data, level, insertPath); // put the item into the node
65446
65447
65448               node.children.push(item);
65449               extend$1(node, bbox); // split on node overflow; propagate upwards if necessary
65450
65451               while (level >= 0) {
65452                 if (insertPath[level].children.length > this._maxEntries) {
65453                   this._split(insertPath, level);
65454
65455                   level--;
65456                 } else break;
65457               } // adjust bboxes along the insertion path
65458
65459
65460               this._adjustParentBBoxes(bbox, insertPath, level);
65461             } // split overflowed node into two
65462
65463           }, {
65464             key: "_split",
65465             value: function _split(insertPath, level) {
65466               var node = insertPath[level];
65467               var M = node.children.length;
65468               var m = this._minEntries;
65469
65470               this._chooseSplitAxis(node, m, M);
65471
65472               var splitIndex = this._chooseSplitIndex(node, m, M);
65473
65474               var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
65475               newNode.height = node.height;
65476               newNode.leaf = node.leaf;
65477               calcBBox(node, this.toBBox);
65478               calcBBox(newNode, this.toBBox);
65479               if (level) insertPath[level - 1].children.push(newNode);else this._splitRoot(node, newNode);
65480             }
65481           }, {
65482             key: "_splitRoot",
65483             value: function _splitRoot(node, newNode) {
65484               // split root node
65485               this.data = createNode([node, newNode]);
65486               this.data.height = node.height + 1;
65487               this.data.leaf = false;
65488               calcBBox(this.data, this.toBBox);
65489             }
65490           }, {
65491             key: "_chooseSplitIndex",
65492             value: function _chooseSplitIndex(node, m, M) {
65493               var index;
65494               var minOverlap = Infinity;
65495               var minArea = Infinity;
65496
65497               for (var i = m; i <= M - m; i++) {
65498                 var bbox1 = distBBox(node, 0, i, this.toBBox);
65499                 var bbox2 = distBBox(node, i, M, this.toBBox);
65500                 var overlap = intersectionArea(bbox1, bbox2);
65501                 var area = bboxArea(bbox1) + bboxArea(bbox2); // choose distribution with minimum overlap
65502
65503                 if (overlap < minOverlap) {
65504                   minOverlap = overlap;
65505                   index = i;
65506                   minArea = area < minArea ? area : minArea;
65507                 } else if (overlap === minOverlap) {
65508                   // otherwise choose distribution with minimum area
65509                   if (area < minArea) {
65510                     minArea = area;
65511                     index = i;
65512                   }
65513                 }
65514               }
65515
65516               return index || M - m;
65517             } // sorts node children by the best axis for split
65518
65519           }, {
65520             key: "_chooseSplitAxis",
65521             value: function _chooseSplitAxis(node, m, M) {
65522               var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;
65523               var compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;
65524
65525               var xMargin = this._allDistMargin(node, m, M, compareMinX);
65526
65527               var yMargin = this._allDistMargin(node, m, M, compareMinY); // if total distributions margin value is minimal for x, sort by minX,
65528               // otherwise it's already sorted by minY
65529
65530
65531               if (xMargin < yMargin) node.children.sort(compareMinX);
65532             } // total margin of all possible split distributions where each node is at least m full
65533
65534           }, {
65535             key: "_allDistMargin",
65536             value: function _allDistMargin(node, m, M, compare) {
65537               node.children.sort(compare);
65538               var toBBox = this.toBBox;
65539               var leftBBox = distBBox(node, 0, m, toBBox);
65540               var rightBBox = distBBox(node, M - m, M, toBBox);
65541               var margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);
65542
65543               for (var i = m; i < M - m; i++) {
65544                 var child = node.children[i];
65545                 extend$1(leftBBox, node.leaf ? toBBox(child) : child);
65546                 margin += bboxMargin(leftBBox);
65547               }
65548
65549               for (var _i = M - m - 1; _i >= m; _i--) {
65550                 var _child = node.children[_i];
65551                 extend$1(rightBBox, node.leaf ? toBBox(_child) : _child);
65552                 margin += bboxMargin(rightBBox);
65553               }
65554
65555               return margin;
65556             }
65557           }, {
65558             key: "_adjustParentBBoxes",
65559             value: function _adjustParentBBoxes(bbox, path, level) {
65560               // adjust bboxes along the given tree path
65561               for (var i = level; i >= 0; i--) {
65562                 extend$1(path[i], bbox);
65563               }
65564             }
65565           }, {
65566             key: "_condense",
65567             value: function _condense(path) {
65568               // go through the path, removing empty nodes and updating bboxes
65569               for (var i = path.length - 1, siblings; i >= 0; i--) {
65570                 if (path[i].children.length === 0) {
65571                   if (i > 0) {
65572                     siblings = path[i - 1].children;
65573                     siblings.splice(siblings.indexOf(path[i]), 1);
65574                   } else this.clear();
65575                 } else calcBBox(path[i], this.toBBox);
65576               }
65577             }
65578           }]);
65579
65580           return RBush;
65581         }();
65582
65583         function findItem(item, items, equalsFn) {
65584           if (!equalsFn) return items.indexOf(item);
65585
65586           for (var i = 0; i < items.length; i++) {
65587             if (equalsFn(item, items[i])) return i;
65588           }
65589
65590           return -1;
65591         } // calculate node's bbox from bboxes of its children
65592
65593
65594         function calcBBox(node, toBBox) {
65595           distBBox(node, 0, node.children.length, toBBox, node);
65596         } // min bounding rectangle of node children from k to p-1
65597
65598
65599         function distBBox(node, k, p, toBBox, destNode) {
65600           if (!destNode) destNode = createNode(null);
65601           destNode.minX = Infinity;
65602           destNode.minY = Infinity;
65603           destNode.maxX = -Infinity;
65604           destNode.maxY = -Infinity;
65605
65606           for (var i = k; i < p; i++) {
65607             var child = node.children[i];
65608             extend$1(destNode, node.leaf ? toBBox(child) : child);
65609           }
65610
65611           return destNode;
65612         }
65613
65614         function extend$1(a, b) {
65615           a.minX = Math.min(a.minX, b.minX);
65616           a.minY = Math.min(a.minY, b.minY);
65617           a.maxX = Math.max(a.maxX, b.maxX);
65618           a.maxY = Math.max(a.maxY, b.maxY);
65619           return a;
65620         }
65621
65622         function compareNodeMinX(a, b) {
65623           return a.minX - b.minX;
65624         }
65625
65626         function compareNodeMinY(a, b) {
65627           return a.minY - b.minY;
65628         }
65629
65630         function bboxArea(a) {
65631           return (a.maxX - a.minX) * (a.maxY - a.minY);
65632         }
65633
65634         function bboxMargin(a) {
65635           return a.maxX - a.minX + (a.maxY - a.minY);
65636         }
65637
65638         function enlargedArea(a, b) {
65639           return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) * (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
65640         }
65641
65642         function intersectionArea(a, b) {
65643           var minX = Math.max(a.minX, b.minX);
65644           var minY = Math.max(a.minY, b.minY);
65645           var maxX = Math.min(a.maxX, b.maxX);
65646           var maxY = Math.min(a.maxY, b.maxY);
65647           return Math.max(0, maxX - minX) * Math.max(0, maxY - minY);
65648         }
65649
65650         function contains(a, b) {
65651           return a.minX <= b.minX && a.minY <= b.minY && b.maxX <= a.maxX && b.maxY <= a.maxY;
65652         }
65653
65654         function intersects(a, b) {
65655           return b.minX <= a.maxX && b.minY <= a.maxY && b.maxX >= a.minX && b.maxY >= a.minY;
65656         }
65657
65658         function createNode(children) {
65659           return {
65660             children: children,
65661             height: 1,
65662             leaf: true,
65663             minX: Infinity,
65664             minY: Infinity,
65665             maxX: -Infinity,
65666             maxY: -Infinity
65667           };
65668         } // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
65669         // combines selection algorithm with binary divide & conquer approach
65670
65671
65672         function multiSelect(arr, left, right, n, compare) {
65673           var stack = [left, right];
65674
65675           while (stack.length) {
65676             right = stack.pop();
65677             left = stack.pop();
65678             if (right - left <= n) continue;
65679             var mid = left + Math.ceil((right - left) / n / 2) * n;
65680             quickselect(arr, mid, left, right, compare);
65681             stack.push(left, mid, mid, right);
65682           }
65683         }
65684
65685         function responseText(response) {
65686           if (!response.ok) throw new Error(response.status + " " + response.statusText);
65687           return response.text();
65688         }
65689
65690         function d3_text (input, init) {
65691           return fetch(input, init).then(responseText);
65692         }
65693
65694         function responseJson(response) {
65695           if (!response.ok) throw new Error(response.status + " " + response.statusText);
65696           if (response.status === 204 || response.status === 205) return;
65697           return response.json();
65698         }
65699
65700         function d3_json (input, init) {
65701           return fetch(input, init).then(responseJson);
65702         }
65703
65704         function parser(type) {
65705           return function (input, init) {
65706             return d3_text(input, init).then(function (text) {
65707               return new DOMParser().parseFromString(text, type);
65708             });
65709           };
65710         }
65711
65712         var d3_xml = parser("application/xml");
65713         var svg = parser("image/svg+xml");
65714
65715         var tiler$6 = utilTiler();
65716         var dispatch$7 = dispatch$8('loaded');
65717         var _tileZoom$3 = 14;
65718         var _krUrlRoot = 'https://www.keepright.at';
65719         var _krData = {
65720           errorTypes: {},
65721           localizeStrings: {}
65722         }; // This gets reassigned if reset
65723
65724         var _cache$2;
65725
65726         var _krRuleset = [// no 20 - multiple node on same spot - these are mostly boundaries overlapping roads
65727         30, 40, 50, 60, 70, 90, 100, 110, 120, 130, 150, 160, 170, 180, 190, 191, 192, 193, 194, 195, 196, 197, 198, 200, 201, 202, 203, 204, 205, 206, 207, 208, 210, 220, 230, 231, 232, 270, 280, 281, 282, 283, 284, 285, 290, 291, 292, 293, 294, 295, 296, 297, 298, 300, 310, 311, 312, 313, 320, 350, 360, 370, 380, 390, 400, 401, 402, 410, 411, 412, 413];
65728
65729         function abortRequest$6(controller) {
65730           if (controller) {
65731             controller.abort();
65732           }
65733         }
65734
65735         function abortUnwantedRequests$3(cache, tiles) {
65736           Object.keys(cache.inflightTile).forEach(function (k) {
65737             var wanted = tiles.find(function (tile) {
65738               return k === tile.id;
65739             });
65740
65741             if (!wanted) {
65742               abortRequest$6(cache.inflightTile[k]);
65743               delete cache.inflightTile[k];
65744             }
65745           });
65746         }
65747
65748         function encodeIssueRtree$2(d) {
65749           return {
65750             minX: d.loc[0],
65751             minY: d.loc[1],
65752             maxX: d.loc[0],
65753             maxY: d.loc[1],
65754             data: d
65755           };
65756         } // Replace or remove QAItem from rtree
65757
65758
65759         function updateRtree$3(item, replace) {
65760           _cache$2.rtree.remove(item, function (a, b) {
65761             return a.data.id === b.data.id;
65762           });
65763
65764           if (replace) {
65765             _cache$2.rtree.insert(item);
65766           }
65767         }
65768
65769         function tokenReplacements(d) {
65770           if (!(d instanceof QAItem)) return;
65771           var replacements = {};
65772           var issueTemplate = _krData.errorTypes[d.whichType];
65773
65774           if (!issueTemplate) {
65775             /* eslint-disable no-console */
65776             console.log('No Template: ', d.whichType);
65777             console.log('  ', d.description);
65778             /* eslint-enable no-console */
65779
65780             return;
65781           } // some descriptions are just fixed text
65782
65783
65784           if (!issueTemplate.regex) return; // regex pattern should match description with variable details captured
65785
65786           var errorRegex = new RegExp(issueTemplate.regex, 'i');
65787           var errorMatch = errorRegex.exec(d.description);
65788
65789           if (!errorMatch) {
65790             /* eslint-disable no-console */
65791             console.log('Unmatched: ', d.whichType);
65792             console.log('  ', d.description);
65793             console.log('  ', errorRegex);
65794             /* eslint-enable no-console */
65795
65796             return;
65797           }
65798
65799           for (var i = 1; i < errorMatch.length; i++) {
65800             // skip first
65801             var capture = errorMatch[i];
65802             var idType = void 0;
65803             idType = 'IDs' in issueTemplate ? issueTemplate.IDs[i - 1] : '';
65804
65805             if (idType && capture) {
65806               // link IDs if present in the capture
65807               capture = parseError(capture, idType);
65808             } else {
65809               var compare = capture.toLowerCase();
65810
65811               if (_krData.localizeStrings[compare]) {
65812                 // some replacement strings can be localized
65813                 capture = _t('QA.keepRight.error_parts.' + _krData.localizeStrings[compare]);
65814               } else {
65815                 capture = unescape$3(capture);
65816               }
65817             }
65818
65819             replacements['var' + i] = capture;
65820           }
65821
65822           return replacements;
65823         }
65824
65825         function parseError(capture, idType) {
65826           var compare = capture.toLowerCase();
65827
65828           if (_krData.localizeStrings[compare]) {
65829             // some replacement strings can be localized
65830             capture = _t('QA.keepRight.error_parts.' + _krData.localizeStrings[compare]);
65831           }
65832
65833           switch (idType) {
65834             // link a string like "this node"
65835             case 'this':
65836               capture = linkErrorObject(capture);
65837               break;
65838
65839             case 'url':
65840               capture = linkURL(capture);
65841               break;
65842             // link an entity ID
65843
65844             case 'n':
65845             case 'w':
65846             case 'r':
65847               capture = linkEntity(idType + capture);
65848               break;
65849             // some errors have more complex ID lists/variance
65850
65851             case '20':
65852               capture = parse20(capture);
65853               break;
65854
65855             case '211':
65856               capture = parse211(capture);
65857               break;
65858
65859             case '231':
65860               capture = parse231(capture);
65861               break;
65862
65863             case '294':
65864               capture = parse294(capture);
65865               break;
65866
65867             case '370':
65868               capture = parse370(capture);
65869               break;
65870           }
65871
65872           return capture;
65873
65874           function linkErrorObject(d) {
65875             return {
65876               html: "<a class=\"error_object_link\">".concat(d, "</a>")
65877             };
65878           }
65879
65880           function linkEntity(d) {
65881             return {
65882               html: "<a class=\"error_entity_link\">".concat(d, "</a>")
65883             };
65884           }
65885
65886           function linkURL(d) {
65887             return {
65888               html: "<a class=\"kr_external_link\" target=\"_blank\" href=\"".concat(d, "\">").concat(d, "</a>")
65889             };
65890           } // arbitrary node list of form: #ID, #ID, #ID...
65891
65892
65893           function parse211(capture) {
65894             var newList = [];
65895             var items = capture.split(', ');
65896             items.forEach(function (item) {
65897               // ID has # at the front
65898               var id = linkEntity('n' + item.slice(1));
65899               newList.push(id);
65900             });
65901             return newList.join(', ');
65902           } // arbitrary way list of form: #ID(layer),#ID(layer),#ID(layer)...
65903
65904
65905           function parse231(capture) {
65906             var newList = []; // unfortunately 'layer' can itself contain commas, so we split on '),'
65907
65908             var items = capture.split('),');
65909             items.forEach(function (item) {
65910               var match = item.match(/\#(\d+)\((.+)\)?/);
65911
65912               if (match !== null && match.length > 2) {
65913                 newList.push(linkEntity('w' + match[1]) + ' ' + _t('QA.keepRight.errorTypes.231.layer', {
65914                   layer: match[2]
65915                 }));
65916               }
65917             });
65918             return newList.join(', ');
65919           } // arbitrary node/relation list of form: from node #ID,to relation #ID,to node #ID...
65920
65921
65922           function parse294(capture) {
65923             var newList = [];
65924             var items = capture.split(',');
65925             items.forEach(function (item) {
65926               // item of form "from/to node/relation #ID"
65927               item = item.split(' '); // to/from role is more clear in quotes
65928
65929               var role = "\"".concat(item[0], "\""); // first letter of node/relation provides the type
65930
65931               var idType = item[1].slice(0, 1); // ID has # at the front
65932
65933               var id = item[2].slice(1);
65934               id = linkEntity(idType + id);
65935               newList.push("".concat(role, " ").concat(item[1], " ").concat(id));
65936             });
65937             return newList.join(', ');
65938           } // may or may not include the string "(including the name 'name')"
65939
65940
65941           function parse370(capture) {
65942             if (!capture) return '';
65943             var match = capture.match(/\(including the name (\'.+\')\)/);
65944
65945             if (match && match.length) {
65946               return _t('QA.keepRight.errorTypes.370.including_the_name', {
65947                 name: match[1]
65948               });
65949             }
65950
65951             return '';
65952           } // arbitrary node list of form: #ID,#ID,#ID...
65953
65954
65955           function parse20(capture) {
65956             var newList = [];
65957             var items = capture.split(',');
65958             items.forEach(function (item) {
65959               // ID has # at the front
65960               var id = linkEntity('n' + item.slice(1));
65961               newList.push(id);
65962             });
65963             return newList.join(', ');
65964           }
65965         }
65966
65967         var serviceKeepRight = {
65968           title: 'keepRight',
65969           init: function init() {
65970             _mainFileFetcher.get('keepRight').then(function (d) {
65971               return _krData = d;
65972             });
65973
65974             if (!_cache$2) {
65975               this.reset();
65976             }
65977
65978             this.event = utilRebind(this, dispatch$7, 'on');
65979           },
65980           reset: function reset() {
65981             if (_cache$2) {
65982               Object.values(_cache$2.inflightTile).forEach(abortRequest$6);
65983             }
65984
65985             _cache$2 = {
65986               data: {},
65987               loadedTile: {},
65988               inflightTile: {},
65989               inflightPost: {},
65990               closed: {},
65991               rtree: new RBush()
65992             };
65993           },
65994           // KeepRight API:  http://osm.mueschelsoft.de/keepright/interfacing.php
65995           loadIssues: function loadIssues(projection) {
65996             var _this = this;
65997
65998             var options = {
65999               format: 'geojson',
66000               ch: _krRuleset
66001             }; // determine the needed tiles to cover the view
66002
66003             var tiles = tiler$6.zoomExtent([_tileZoom$3, _tileZoom$3]).getTiles(projection); // abort inflight requests that are no longer needed
66004
66005             abortUnwantedRequests$3(_cache$2, tiles); // issue new requests..
66006
66007             tiles.forEach(function (tile) {
66008               if (_cache$2.loadedTile[tile.id] || _cache$2.inflightTile[tile.id]) return;
66009
66010               var _tile$extent$rectangl = tile.extent.rectangle(),
66011                   _tile$extent$rectangl2 = _slicedToArray(_tile$extent$rectangl, 4),
66012                   left = _tile$extent$rectangl2[0],
66013                   top = _tile$extent$rectangl2[1],
66014                   right = _tile$extent$rectangl2[2],
66015                   bottom = _tile$extent$rectangl2[3];
66016
66017               var params = Object.assign({}, options, {
66018                 left: left,
66019                 bottom: bottom,
66020                 right: right,
66021                 top: top
66022               });
66023               var url = "".concat(_krUrlRoot, "/export.php?") + utilQsString(params);
66024               var controller = new AbortController();
66025               _cache$2.inflightTile[tile.id] = controller;
66026               d3_json(url, {
66027                 signal: controller.signal
66028               }).then(function (data) {
66029                 delete _cache$2.inflightTile[tile.id];
66030                 _cache$2.loadedTile[tile.id] = true;
66031
66032                 if (!data || !data.features || !data.features.length) {
66033                   throw new Error('No Data');
66034                 }
66035
66036                 data.features.forEach(function (feature) {
66037                   var _feature$properties = feature.properties,
66038                       itemType = _feature$properties.error_type,
66039                       id = _feature$properties.error_id,
66040                       _feature$properties$c = _feature$properties.comment,
66041                       comment = _feature$properties$c === void 0 ? null : _feature$properties$c,
66042                       objectId = _feature$properties.object_id,
66043                       objectType = _feature$properties.object_type,
66044                       schema = _feature$properties.schema,
66045                       title = _feature$properties.title;
66046                   var loc = feature.geometry.coordinates,
66047                       _feature$properties$d = feature.properties.description,
66048                       description = _feature$properties$d === void 0 ? '' : _feature$properties$d; // if there is a parent, save its error type e.g.:
66049                   //  Error 191 = "highway-highway"
66050                   //  Error 190 = "intersections without junctions"  (parent)
66051
66052                   var issueTemplate = _krData.errorTypes[itemType];
66053                   var parentIssueType = (Math.floor(itemType / 10) * 10).toString(); // try to handle error type directly, fallback to parent error type.
66054
66055                   var whichType = issueTemplate ? itemType : parentIssueType;
66056                   var whichTemplate = _krData.errorTypes[whichType]; // Rewrite a few of the errors at this point..
66057                   // This is done to make them easier to linkify and translate.
66058
66059                   switch (whichType) {
66060                     case '170':
66061                       description = "This feature has a FIXME tag: ".concat(description);
66062                       break;
66063
66064                     case '292':
66065                     case '293':
66066                       description = description.replace('A turn-', 'This turn-');
66067                       break;
66068
66069                     case '294':
66070                     case '295':
66071                     case '296':
66072                     case '297':
66073                     case '298':
66074                       description = "This turn-restriction~".concat(description);
66075                       break;
66076
66077                     case '300':
66078                       description = 'This highway is missing a maxspeed tag';
66079                       break;
66080
66081                     case '411':
66082                     case '412':
66083                     case '413':
66084                       description = "This feature~".concat(description);
66085                       break;
66086                   } // move markers slightly so it doesn't obscure the geometry,
66087                   // then move markers away from other coincident markers
66088
66089
66090                   var coincident = false;
66091
66092                   do {
66093                     // first time, move marker up. after that, move marker right.
66094                     var delta = coincident ? [0.00001, 0] : [0, 0.00001];
66095                     loc = geoVecAdd(loc, delta);
66096                     var bbox = geoExtent(loc).bbox();
66097                     coincident = _cache$2.rtree.search(bbox).length;
66098                   } while (coincident);
66099
66100                   var d = new QAItem(loc, _this, itemType, id, {
66101                     comment: comment,
66102                     description: description,
66103                     whichType: whichType,
66104                     parentIssueType: parentIssueType,
66105                     severity: whichTemplate.severity || 'error',
66106                     objectId: objectId,
66107                     objectType: objectType,
66108                     schema: schema,
66109                     title: title
66110                   });
66111                   d.replacements = tokenReplacements(d);
66112                   _cache$2.data[id] = d;
66113
66114                   _cache$2.rtree.insert(encodeIssueRtree$2(d));
66115                 });
66116                 dispatch$7.call('loaded');
66117               })["catch"](function () {
66118                 delete _cache$2.inflightTile[tile.id];
66119                 _cache$2.loadedTile[tile.id] = true;
66120               });
66121             });
66122           },
66123           postUpdate: function postUpdate(d, callback) {
66124             var _this2 = this;
66125
66126             if (_cache$2.inflightPost[d.id]) {
66127               return callback({
66128                 message: 'Error update already inflight',
66129                 status: -2
66130               }, d);
66131             }
66132
66133             var params = {
66134               schema: d.schema,
66135               id: d.id
66136             };
66137
66138             if (d.newStatus) {
66139               params.st = d.newStatus;
66140             }
66141
66142             if (d.newComment !== undefined) {
66143               params.co = d.newComment;
66144             } // NOTE: This throws a CORS err, but it seems successful.
66145             // We don't care too much about the response, so this is fine.
66146
66147
66148             var url = "".concat(_krUrlRoot, "/comment.php?") + utilQsString(params);
66149             var controller = new AbortController();
66150             _cache$2.inflightPost[d.id] = controller; // Since this is expected to throw an error just continue as if it worked
66151             // (worst case scenario the request truly fails and issue will show up if iD restarts)
66152
66153             d3_json(url, {
66154               signal: controller.signal
66155             })["finally"](function () {
66156               delete _cache$2.inflightPost[d.id];
66157
66158               if (d.newStatus === 'ignore') {
66159                 // ignore permanently (false positive)
66160                 _this2.removeItem(d);
66161               } else if (d.newStatus === 'ignore_t') {
66162                 // ignore temporarily (error fixed)
66163                 _this2.removeItem(d);
66164
66165                 _cache$2.closed["".concat(d.schema, ":").concat(d.id)] = true;
66166               } else {
66167                 d = _this2.replaceItem(d.update({
66168                   comment: d.newComment,
66169                   newComment: undefined,
66170                   newState: undefined
66171                 }));
66172               }
66173
66174               if (callback) callback(null, d);
66175             });
66176           },
66177           // Get all cached QAItems covering the viewport
66178           getItems: function getItems(projection) {
66179             var viewport = projection.clipExtent();
66180             var min = [viewport[0][0], viewport[1][1]];
66181             var max = [viewport[1][0], viewport[0][1]];
66182             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
66183             return _cache$2.rtree.search(bbox).map(function (d) {
66184               return d.data;
66185             });
66186           },
66187           // Get a QAItem from cache
66188           // NOTE: Don't change method name until UI v3 is merged
66189           getError: function getError(id) {
66190             return _cache$2.data[id];
66191           },
66192           // Replace a single QAItem in the cache
66193           replaceItem: function replaceItem(item) {
66194             if (!(item instanceof QAItem) || !item.id) return;
66195             _cache$2.data[item.id] = item;
66196             updateRtree$3(encodeIssueRtree$2(item), true); // true = replace
66197
66198             return item;
66199           },
66200           // Remove a single QAItem from the cache
66201           removeItem: function removeItem(item) {
66202             if (!(item instanceof QAItem) || !item.id) return;
66203             delete _cache$2.data[item.id];
66204             updateRtree$3(encodeIssueRtree$2(item), false); // false = remove
66205           },
66206           issueURL: function issueURL(item) {
66207             return "".concat(_krUrlRoot, "/report_map.php?schema=").concat(item.schema, "&error=").concat(item.id);
66208           },
66209           // Get an array of issues closed during this session.
66210           // Used to populate `closed:keepright` changeset tag
66211           getClosedIDs: function getClosedIDs() {
66212             return Object.keys(_cache$2.closed).sort();
66213           }
66214         };
66215
66216         var tiler$5 = utilTiler();
66217         var dispatch$6 = dispatch$8('loaded');
66218         var _tileZoom$2 = 14;
66219         var _impOsmUrls = {
66220           ow: 'https://grab.community.improve-osm.org/directionOfFlowService',
66221           mr: 'https://grab.community.improve-osm.org/missingGeoService',
66222           tr: 'https://grab.community.improve-osm.org/turnRestrictionService'
66223         };
66224         var _impOsmData = {
66225           icons: {}
66226         }; // This gets reassigned if reset
66227
66228         var _cache$1;
66229
66230         function abortRequest$5(i) {
66231           Object.values(i).forEach(function (controller) {
66232             if (controller) {
66233               controller.abort();
66234             }
66235           });
66236         }
66237
66238         function abortUnwantedRequests$2(cache, tiles) {
66239           Object.keys(cache.inflightTile).forEach(function (k) {
66240             var wanted = tiles.find(function (tile) {
66241               return k === tile.id;
66242             });
66243
66244             if (!wanted) {
66245               abortRequest$5(cache.inflightTile[k]);
66246               delete cache.inflightTile[k];
66247             }
66248           });
66249         }
66250
66251         function encodeIssueRtree$1(d) {
66252           return {
66253             minX: d.loc[0],
66254             minY: d.loc[1],
66255             maxX: d.loc[0],
66256             maxY: d.loc[1],
66257             data: d
66258           };
66259         } // Replace or remove QAItem from rtree
66260
66261
66262         function updateRtree$2(item, replace) {
66263           _cache$1.rtree.remove(item, function (a, b) {
66264             return a.data.id === b.data.id;
66265           });
66266
66267           if (replace) {
66268             _cache$1.rtree.insert(item);
66269           }
66270         }
66271
66272         function linkErrorObject(d) {
66273           return {
66274             html: "<a class=\"error_object_link\">".concat(d, "</a>")
66275           };
66276         }
66277
66278         function linkEntity(d) {
66279           return {
66280             html: "<a class=\"error_entity_link\">".concat(d, "</a>")
66281           };
66282         }
66283
66284         function pointAverage(points) {
66285           if (points.length) {
66286             var sum = points.reduce(function (acc, point) {
66287               return geoVecAdd(acc, [point.lon, point.lat]);
66288             }, [0, 0]);
66289             return geoVecScale(sum, 1 / points.length);
66290           } else {
66291             return [0, 0];
66292           }
66293         }
66294
66295         function relativeBearing(p1, p2) {
66296           var angle = Math.atan2(p2.lon - p1.lon, p2.lat - p1.lat);
66297
66298           if (angle < 0) {
66299             angle += 2 * Math.PI;
66300           } // Return degrees
66301
66302
66303           return angle * 180 / Math.PI;
66304         } // Assuming range [0,360)
66305
66306
66307         function cardinalDirection(bearing) {
66308           var dir = 45 * Math.round(bearing / 45);
66309           var compass = {
66310             0: 'north',
66311             45: 'northeast',
66312             90: 'east',
66313             135: 'southeast',
66314             180: 'south',
66315             225: 'southwest',
66316             270: 'west',
66317             315: 'northwest',
66318             360: 'north'
66319           };
66320           return _t("QA.improveOSM.directions.".concat(compass[dir]));
66321         } // Errors shouldn't obscure each other
66322
66323
66324         function preventCoincident$1(loc, bumpUp) {
66325           var coincident = false;
66326
66327           do {
66328             // first time, move marker up. after that, move marker right.
66329             var delta = coincident ? [0.00001, 0] : bumpUp ? [0, 0.00001] : [0, 0];
66330             loc = geoVecAdd(loc, delta);
66331             var bbox = geoExtent(loc).bbox();
66332             coincident = _cache$1.rtree.search(bbox).length;
66333           } while (coincident);
66334
66335           return loc;
66336         }
66337
66338         var serviceImproveOSM = {
66339           title: 'improveOSM',
66340           init: function init() {
66341             _mainFileFetcher.get('qa_data').then(function (d) {
66342               return _impOsmData = d.improveOSM;
66343             });
66344
66345             if (!_cache$1) {
66346               this.reset();
66347             }
66348
66349             this.event = utilRebind(this, dispatch$6, 'on');
66350           },
66351           reset: function reset() {
66352             if (_cache$1) {
66353               Object.values(_cache$1.inflightTile).forEach(abortRequest$5);
66354             }
66355
66356             _cache$1 = {
66357               data: {},
66358               loadedTile: {},
66359               inflightTile: {},
66360               inflightPost: {},
66361               closed: {},
66362               rtree: new RBush()
66363             };
66364           },
66365           loadIssues: function loadIssues(projection) {
66366             var _this = this;
66367
66368             var options = {
66369               client: 'iD',
66370               status: 'OPEN',
66371               zoom: '19' // Use a high zoom so that clusters aren't returned
66372
66373             }; // determine the needed tiles to cover the view
66374
66375             var tiles = tiler$5.zoomExtent([_tileZoom$2, _tileZoom$2]).getTiles(projection); // abort inflight requests that are no longer needed
66376
66377             abortUnwantedRequests$2(_cache$1, tiles); // issue new requests..
66378
66379             tiles.forEach(function (tile) {
66380               if (_cache$1.loadedTile[tile.id] || _cache$1.inflightTile[tile.id]) return;
66381
66382               var _tile$extent$rectangl = tile.extent.rectangle(),
66383                   _tile$extent$rectangl2 = _slicedToArray(_tile$extent$rectangl, 4),
66384                   east = _tile$extent$rectangl2[0],
66385                   north = _tile$extent$rectangl2[1],
66386                   west = _tile$extent$rectangl2[2],
66387                   south = _tile$extent$rectangl2[3];
66388
66389               var params = Object.assign({}, options, {
66390                 east: east,
66391                 south: south,
66392                 west: west,
66393                 north: north
66394               }); // 3 separate requests to store for each tile
66395
66396               var requests = {};
66397               Object.keys(_impOsmUrls).forEach(function (k) {
66398                 // We exclude WATER from missing geometry as it doesn't seem useful
66399                 // We use most confident one-way and turn restrictions only, still have false positives
66400                 var kParams = Object.assign({}, params, k === 'mr' ? {
66401                   type: 'PARKING,ROAD,BOTH,PATH'
66402                 } : {
66403                   confidenceLevel: 'C1'
66404                 });
66405                 var url = "".concat(_impOsmUrls[k], "/search?") + utilQsString(kParams);
66406                 var controller = new AbortController();
66407                 requests[k] = controller;
66408                 d3_json(url, {
66409                   signal: controller.signal
66410                 }).then(function (data) {
66411                   delete _cache$1.inflightTile[tile.id][k];
66412
66413                   if (!Object.keys(_cache$1.inflightTile[tile.id]).length) {
66414                     delete _cache$1.inflightTile[tile.id];
66415                     _cache$1.loadedTile[tile.id] = true;
66416                   } // Road segments at high zoom == oneways
66417
66418
66419                   if (data.roadSegments) {
66420                     data.roadSegments.forEach(function (feature) {
66421                       // Position error at the approximate middle of the segment
66422                       var points = feature.points,
66423                           wayId = feature.wayId,
66424                           fromNodeId = feature.fromNodeId,
66425                           toNodeId = feature.toNodeId;
66426                       var itemId = "".concat(wayId).concat(fromNodeId).concat(toNodeId);
66427                       var mid = points.length / 2;
66428                       var loc; // Even number of points, find midpoint of the middle two
66429                       // Odd number of points, use position of very middle point
66430
66431                       if (mid % 1 === 0) {
66432                         loc = pointAverage([points[mid - 1], points[mid]]);
66433                       } else {
66434                         mid = points[Math.floor(mid)];
66435                         loc = [mid.lon, mid.lat];
66436                       } // One-ways can land on same segment in opposite direction
66437
66438
66439                       loc = preventCoincident$1(loc, false);
66440                       var d = new QAItem(loc, _this, k, itemId, {
66441                         issueKey: k,
66442                         // used as a category
66443                         identifier: {
66444                           // used to post changes
66445                           wayId: wayId,
66446                           fromNodeId: fromNodeId,
66447                           toNodeId: toNodeId
66448                         },
66449                         objectId: wayId,
66450                         objectType: 'way'
66451                       }); // Variables used in the description
66452
66453                       d.replacements = {
66454                         percentage: feature.percentOfTrips,
66455                         num_trips: feature.numberOfTrips,
66456                         highway: linkErrorObject(_t('QA.keepRight.error_parts.highway')),
66457                         from_node: linkEntity('n' + feature.fromNodeId),
66458                         to_node: linkEntity('n' + feature.toNodeId)
66459                       };
66460                       _cache$1.data[d.id] = d;
66461
66462                       _cache$1.rtree.insert(encodeIssueRtree$1(d));
66463                     });
66464                   } // Tiles at high zoom == missing roads
66465
66466
66467                   if (data.tiles) {
66468                     data.tiles.forEach(function (feature) {
66469                       var type = feature.type,
66470                           x = feature.x,
66471                           y = feature.y,
66472                           numberOfTrips = feature.numberOfTrips;
66473                       var geoType = type.toLowerCase();
66474                       var itemId = "".concat(geoType).concat(x).concat(y).concat(numberOfTrips); // Average of recorded points should land on the missing geometry
66475                       // Missing geometry could happen to land on another error
66476
66477                       var loc = pointAverage(feature.points);
66478                       loc = preventCoincident$1(loc, false);
66479                       var d = new QAItem(loc, _this, "".concat(k, "-").concat(geoType), itemId, {
66480                         issueKey: k,
66481                         identifier: {
66482                           x: x,
66483                           y: y
66484                         }
66485                       });
66486                       d.replacements = {
66487                         num_trips: numberOfTrips,
66488                         geometry_type: _t("QA.improveOSM.geometry_types.".concat(geoType))
66489                       }; // -1 trips indicates data came from a 3rd party
66490
66491                       if (numberOfTrips === -1) {
66492                         d.desc = _t('QA.improveOSM.error_types.mr.description_alt', d.replacements);
66493                       }
66494
66495                       _cache$1.data[d.id] = d;
66496
66497                       _cache$1.rtree.insert(encodeIssueRtree$1(d));
66498                     });
66499                   } // Entities at high zoom == turn restrictions
66500
66501
66502                   if (data.entities) {
66503                     data.entities.forEach(function (feature) {
66504                       var point = feature.point,
66505                           id = feature.id,
66506                           segments = feature.segments,
66507                           numberOfPasses = feature.numberOfPasses,
66508                           turnType = feature.turnType;
66509                       var itemId = "".concat(id.replace(/[,:+#]/g, '_')); // Turn restrictions could be missing at same junction
66510                       // We also want to bump the error up so node is accessible
66511
66512                       var loc = preventCoincident$1([point.lon, point.lat], true); // Elements are presented in a strange way
66513
66514                       var ids = id.split(',');
66515                       var from_way = ids[0];
66516                       var via_node = ids[3];
66517                       var to_way = ids[2].split(':')[1];
66518                       var d = new QAItem(loc, _this, k, itemId, {
66519                         issueKey: k,
66520                         identifier: id,
66521                         objectId: via_node,
66522                         objectType: 'node'
66523                       }); // Travel direction along from_way clarifies the turn restriction
66524
66525                       var _segments$0$points = _slicedToArray(segments[0].points, 2),
66526                           p1 = _segments$0$points[0],
66527                           p2 = _segments$0$points[1];
66528
66529                       var dir_of_travel = cardinalDirection(relativeBearing(p1, p2)); // Variables used in the description
66530
66531                       d.replacements = {
66532                         num_passed: numberOfPasses,
66533                         num_trips: segments[0].numberOfTrips,
66534                         turn_restriction: turnType.toLowerCase(),
66535                         from_way: linkEntity('w' + from_way),
66536                         to_way: linkEntity('w' + to_way),
66537                         travel_direction: dir_of_travel,
66538                         junction: linkErrorObject(_t('QA.keepRight.error_parts.this_node'))
66539                       };
66540                       _cache$1.data[d.id] = d;
66541
66542                       _cache$1.rtree.insert(encodeIssueRtree$1(d));
66543
66544                       dispatch$6.call('loaded');
66545                     });
66546                   }
66547                 })["catch"](function () {
66548                   delete _cache$1.inflightTile[tile.id][k];
66549
66550                   if (!Object.keys(_cache$1.inflightTile[tile.id]).length) {
66551                     delete _cache$1.inflightTile[tile.id];
66552                     _cache$1.loadedTile[tile.id] = true;
66553                   }
66554                 });
66555               });
66556               _cache$1.inflightTile[tile.id] = requests;
66557             });
66558           },
66559           getComments: function getComments(item) {
66560             var _this2 = this;
66561
66562             // If comments already retrieved no need to do so again
66563             if (item.comments) {
66564               return Promise.resolve(item);
66565             }
66566
66567             var key = item.issueKey;
66568             var qParams = {};
66569
66570             if (key === 'ow') {
66571               qParams = item.identifier;
66572             } else if (key === 'mr') {
66573               qParams.tileX = item.identifier.x;
66574               qParams.tileY = item.identifier.y;
66575             } else if (key === 'tr') {
66576               qParams.targetId = item.identifier;
66577             }
66578
66579             var url = "".concat(_impOsmUrls[key], "/retrieveComments?") + utilQsString(qParams);
66580
66581             var cacheComments = function cacheComments(data) {
66582               // Assign directly for immediate use afterwards
66583               // comments are served newest to oldest
66584               item.comments = data.comments ? data.comments.reverse() : [];
66585
66586               _this2.replaceItem(item);
66587             };
66588
66589             return d3_json(url).then(cacheComments).then(function () {
66590               return item;
66591             });
66592           },
66593           postUpdate: function postUpdate(d, callback) {
66594             if (!serviceOsm.authenticated()) {
66595               // Username required in payload
66596               return callback({
66597                 message: 'Not Authenticated',
66598                 status: -3
66599               }, d);
66600             }
66601
66602             if (_cache$1.inflightPost[d.id]) {
66603               return callback({
66604                 message: 'Error update already inflight',
66605                 status: -2
66606               }, d);
66607             } // Payload can only be sent once username is established
66608
66609
66610             serviceOsm.userDetails(sendPayload.bind(this));
66611
66612             function sendPayload(err, user) {
66613               var _this3 = this;
66614
66615               if (err) {
66616                 return callback(err, d);
66617               }
66618
66619               var key = d.issueKey;
66620               var url = "".concat(_impOsmUrls[key], "/comment");
66621               var payload = {
66622                 username: user.display_name,
66623                 targetIds: [d.identifier]
66624               };
66625
66626               if (d.newStatus) {
66627                 payload.status = d.newStatus;
66628                 payload.text = 'status changed';
66629               } // Comment take place of default text
66630
66631
66632               if (d.newComment) {
66633                 payload.text = d.newComment;
66634               }
66635
66636               var controller = new AbortController();
66637               _cache$1.inflightPost[d.id] = controller;
66638               var options = {
66639                 method: 'POST',
66640                 signal: controller.signal,
66641                 body: JSON.stringify(payload)
66642               };
66643               d3_json(url, options).then(function () {
66644                 delete _cache$1.inflightPost[d.id]; // Just a comment, update error in cache
66645
66646                 if (!d.newStatus) {
66647                   var now = new Date();
66648                   var comments = d.comments ? d.comments : [];
66649                   comments.push({
66650                     username: payload.username,
66651                     text: payload.text,
66652                     timestamp: now.getTime() / 1000
66653                   });
66654
66655                   _this3.replaceItem(d.update({
66656                     comments: comments,
66657                     newComment: undefined
66658                   }));
66659                 } else {
66660                   _this3.removeItem(d);
66661
66662                   if (d.newStatus === 'SOLVED') {
66663                     // Keep track of the number of issues closed per type to tag the changeset
66664                     if (!(d.issueKey in _cache$1.closed)) {
66665                       _cache$1.closed[d.issueKey] = 0;
66666                     }
66667
66668                     _cache$1.closed[d.issueKey] += 1;
66669                   }
66670                 }
66671
66672                 if (callback) callback(null, d);
66673               })["catch"](function (err) {
66674                 delete _cache$1.inflightPost[d.id];
66675                 if (callback) callback(err.message);
66676               });
66677             }
66678           },
66679           // Get all cached QAItems covering the viewport
66680           getItems: function getItems(projection) {
66681             var viewport = projection.clipExtent();
66682             var min = [viewport[0][0], viewport[1][1]];
66683             var max = [viewport[1][0], viewport[0][1]];
66684             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
66685             return _cache$1.rtree.search(bbox).map(function (d) {
66686               return d.data;
66687             });
66688           },
66689           // Get a QAItem from cache
66690           // NOTE: Don't change method name until UI v3 is merged
66691           getError: function getError(id) {
66692             return _cache$1.data[id];
66693           },
66694           // get the name of the icon to display for this item
66695           getIcon: function getIcon(itemType) {
66696             return _impOsmData.icons[itemType];
66697           },
66698           // Replace a single QAItem in the cache
66699           replaceItem: function replaceItem(issue) {
66700             if (!(issue instanceof QAItem) || !issue.id) return;
66701             _cache$1.data[issue.id] = issue;
66702             updateRtree$2(encodeIssueRtree$1(issue), true); // true = replace
66703
66704             return issue;
66705           },
66706           // Remove a single QAItem from the cache
66707           removeItem: function removeItem(issue) {
66708             if (!(issue instanceof QAItem) || !issue.id) return;
66709             delete _cache$1.data[issue.id];
66710             updateRtree$2(encodeIssueRtree$1(issue), false); // false = remove
66711           },
66712           // Used to populate `closed:improveosm:*` changeset tags
66713           getClosedCounts: function getClosedCounts() {
66714             return _cache$1.closed;
66715           }
66716         };
66717
66718         var defaults$5 = {exports: {}};
66719
66720         function getDefaults$1() {
66721           return {
66722             baseUrl: null,
66723             breaks: false,
66724             gfm: true,
66725             headerIds: true,
66726             headerPrefix: '',
66727             highlight: null,
66728             langPrefix: 'language-',
66729             mangle: true,
66730             pedantic: false,
66731             renderer: null,
66732             sanitize: false,
66733             sanitizer: null,
66734             silent: false,
66735             smartLists: false,
66736             smartypants: false,
66737             tokenizer: null,
66738             walkTokens: null,
66739             xhtml: false
66740           };
66741         }
66742
66743         function changeDefaults$1(newDefaults) {
66744           defaults$5.exports.defaults = newDefaults;
66745         }
66746
66747         defaults$5.exports = {
66748           defaults: getDefaults$1(),
66749           getDefaults: getDefaults$1,
66750           changeDefaults: changeDefaults$1
66751         };
66752
66753         var escapeTest = /[&<>"']/;
66754         var escapeReplace = /[&<>"']/g;
66755         var escapeTestNoEncode = /[<>"']|&(?!#?\w+;)/;
66756         var escapeReplaceNoEncode = /[<>"']|&(?!#?\w+;)/g;
66757         var escapeReplacements = {
66758           '&': '&amp;',
66759           '<': '&lt;',
66760           '>': '&gt;',
66761           '"': '&quot;',
66762           "'": '&#39;'
66763         };
66764
66765         var getEscapeReplacement = function getEscapeReplacement(ch) {
66766           return escapeReplacements[ch];
66767         };
66768
66769         function escape$3(html, encode) {
66770           if (encode) {
66771             if (escapeTest.test(html)) {
66772               return html.replace(escapeReplace, getEscapeReplacement);
66773             }
66774           } else {
66775             if (escapeTestNoEncode.test(html)) {
66776               return html.replace(escapeReplaceNoEncode, getEscapeReplacement);
66777             }
66778           }
66779
66780           return html;
66781         }
66782
66783         var unescapeTest = /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig;
66784
66785         function unescape$2(html) {
66786           // explicitly match decimal, hex, and named HTML entities
66787           return html.replace(unescapeTest, function (_, n) {
66788             n = n.toLowerCase();
66789             if (n === 'colon') return ':';
66790
66791             if (n.charAt(0) === '#') {
66792               return n.charAt(1) === 'x' ? String.fromCharCode(parseInt(n.substring(2), 16)) : String.fromCharCode(+n.substring(1));
66793             }
66794
66795             return '';
66796           });
66797         }
66798
66799         var caret = /(^|[^\[])\^/g;
66800
66801         function edit$1(regex, opt) {
66802           regex = regex.source || regex;
66803           opt = opt || '';
66804           var obj = {
66805             replace: function replace(name, val) {
66806               val = val.source || val;
66807               val = val.replace(caret, '$1');
66808               regex = regex.replace(name, val);
66809               return obj;
66810             },
66811             getRegex: function getRegex() {
66812               return new RegExp(regex, opt);
66813             }
66814           };
66815           return obj;
66816         }
66817
66818         var nonWordAndColonTest = /[^\w:]/g;
66819         var originIndependentUrl = /^$|^[a-z][a-z0-9+.-]*:|^[?#]/i;
66820
66821         function cleanUrl$1(sanitize, base, href) {
66822           if (sanitize) {
66823             var prot;
66824
66825             try {
66826               prot = decodeURIComponent(unescape$2(href)).replace(nonWordAndColonTest, '').toLowerCase();
66827             } catch (e) {
66828               return null;
66829             }
66830
66831             if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0 || prot.indexOf('data:') === 0) {
66832               return null;
66833             }
66834           }
66835
66836           if (base && !originIndependentUrl.test(href)) {
66837             href = resolveUrl$2(base, href);
66838           }
66839
66840           try {
66841             href = encodeURI(href).replace(/%25/g, '%');
66842           } catch (e) {
66843             return null;
66844           }
66845
66846           return href;
66847         }
66848
66849         var baseUrls = {};
66850         var justDomain = /^[^:]+:\/*[^/]*$/;
66851         var protocol = /^([^:]+:)[\s\S]*$/;
66852         var domain = /^([^:]+:\/*[^/]*)[\s\S]*$/;
66853
66854         function resolveUrl$2(base, href) {
66855           if (!baseUrls[' ' + base]) {
66856             // we can ignore everything in base after the last slash of its path component,
66857             // but we might need to add _that_
66858             // https://tools.ietf.org/html/rfc3986#section-3
66859             if (justDomain.test(base)) {
66860               baseUrls[' ' + base] = base + '/';
66861             } else {
66862               baseUrls[' ' + base] = rtrim$1(base, '/', true);
66863             }
66864           }
66865
66866           base = baseUrls[' ' + base];
66867           var relativeBase = base.indexOf(':') === -1;
66868
66869           if (href.substring(0, 2) === '//') {
66870             if (relativeBase) {
66871               return href;
66872             }
66873
66874             return base.replace(protocol, '$1') + href;
66875           } else if (href.charAt(0) === '/') {
66876             if (relativeBase) {
66877               return href;
66878             }
66879
66880             return base.replace(domain, '$1') + href;
66881           } else {
66882             return base + href;
66883           }
66884         }
66885
66886         var noopTest$1 = {
66887           exec: function noopTest() {}
66888         };
66889
66890         function merge$2(obj) {
66891           var i = 1,
66892               target,
66893               key;
66894
66895           for (; i < arguments.length; i++) {
66896             target = arguments[i];
66897
66898             for (key in target) {
66899               if (Object.prototype.hasOwnProperty.call(target, key)) {
66900                 obj[key] = target[key];
66901               }
66902             }
66903           }
66904
66905           return obj;
66906         }
66907
66908         function splitCells$1(tableRow, count) {
66909           // ensure that every cell-delimiting pipe has a space
66910           // before it to distinguish it from an escaped pipe
66911           var row = tableRow.replace(/\|/g, function (match, offset, str) {
66912             var escaped = false,
66913                 curr = offset;
66914
66915             while (--curr >= 0 && str[curr] === '\\') {
66916               escaped = !escaped;
66917             }
66918
66919             if (escaped) {
66920               // odd number of slashes means | is escaped
66921               // so we leave it alone
66922               return '|';
66923             } else {
66924               // add space before unescaped |
66925               return ' |';
66926             }
66927           }),
66928               cells = row.split(/ \|/);
66929           var i = 0;
66930
66931           if (cells.length > count) {
66932             cells.splice(count);
66933           } else {
66934             while (cells.length < count) {
66935               cells.push('');
66936             }
66937           }
66938
66939           for (; i < cells.length; i++) {
66940             // leading or trailing whitespace is ignored per the gfm spec
66941             cells[i] = cells[i].trim().replace(/\\\|/g, '|');
66942           }
66943
66944           return cells;
66945         } // Remove trailing 'c's. Equivalent to str.replace(/c*$/, '').
66946         // /c*$/ is vulnerable to REDOS.
66947         // invert: Remove suffix of non-c chars instead. Default falsey.
66948
66949
66950         function rtrim$1(str, c, invert) {
66951           var l = str.length;
66952
66953           if (l === 0) {
66954             return '';
66955           } // Length of suffix matching the invert condition.
66956
66957
66958           var suffLen = 0; // Step left until we fail to match the invert condition.
66959
66960           while (suffLen < l) {
66961             var currChar = str.charAt(l - suffLen - 1);
66962
66963             if (currChar === c && !invert) {
66964               suffLen++;
66965             } else if (currChar !== c && invert) {
66966               suffLen++;
66967             } else {
66968               break;
66969             }
66970           }
66971
66972           return str.substr(0, l - suffLen);
66973         }
66974
66975         function findClosingBracket$1(str, b) {
66976           if (str.indexOf(b[1]) === -1) {
66977             return -1;
66978           }
66979
66980           var l = str.length;
66981           var level = 0,
66982               i = 0;
66983
66984           for (; i < l; i++) {
66985             if (str[i] === '\\') {
66986               i++;
66987             } else if (str[i] === b[0]) {
66988               level++;
66989             } else if (str[i] === b[1]) {
66990               level--;
66991
66992               if (level < 0) {
66993                 return i;
66994               }
66995             }
66996           }
66997
66998           return -1;
66999         }
67000
67001         function checkSanitizeDeprecation$1(opt) {
67002           if (opt && opt.sanitize && !opt.silent) {
67003             console.warn('marked(): sanitize and sanitizer parameters are deprecated since version 0.7.0, should not be used and will be removed in the future. Read more here: https://marked.js.org/#/USING_ADVANCED.md#options');
67004           }
67005         } // copied from https://stackoverflow.com/a/5450113/806777
67006
67007
67008         function repeatString$1(pattern, count) {
67009           if (count < 1) {
67010             return '';
67011           }
67012
67013           var result = '';
67014
67015           while (count > 1) {
67016             if (count & 1) {
67017               result += pattern;
67018             }
67019
67020             count >>= 1;
67021             pattern += pattern;
67022           }
67023
67024           return result + pattern;
67025         }
67026
67027         var helpers = {
67028           escape: escape$3,
67029           unescape: unescape$2,
67030           edit: edit$1,
67031           cleanUrl: cleanUrl$1,
67032           resolveUrl: resolveUrl$2,
67033           noopTest: noopTest$1,
67034           merge: merge$2,
67035           splitCells: splitCells$1,
67036           rtrim: rtrim$1,
67037           findClosingBracket: findClosingBracket$1,
67038           checkSanitizeDeprecation: checkSanitizeDeprecation$1,
67039           repeatString: repeatString$1
67040         };
67041
67042         var defaults$4 = defaults$5.exports.defaults;
67043         var rtrim = helpers.rtrim,
67044             splitCells = helpers.splitCells,
67045             _escape = helpers.escape,
67046             findClosingBracket = helpers.findClosingBracket;
67047
67048         function outputLink(cap, link, raw) {
67049           var href = link.href;
67050           var title = link.title ? _escape(link.title) : null;
67051           var text = cap[1].replace(/\\([\[\]])/g, '$1');
67052
67053           if (cap[0].charAt(0) !== '!') {
67054             return {
67055               type: 'link',
67056               raw: raw,
67057               href: href,
67058               title: title,
67059               text: text
67060             };
67061           } else {
67062             return {
67063               type: 'image',
67064               raw: raw,
67065               href: href,
67066               title: title,
67067               text: _escape(text)
67068             };
67069           }
67070         }
67071
67072         function indentCodeCompensation(raw, text) {
67073           var matchIndentToCode = raw.match(/^(\s+)(?:```)/);
67074
67075           if (matchIndentToCode === null) {
67076             return text;
67077           }
67078
67079           var indentToCode = matchIndentToCode[1];
67080           return text.split('\n').map(function (node) {
67081             var matchIndentInNode = node.match(/^\s+/);
67082
67083             if (matchIndentInNode === null) {
67084               return node;
67085             }
67086
67087             var _matchIndentInNode = _slicedToArray(matchIndentInNode, 1),
67088                 indentInNode = _matchIndentInNode[0];
67089
67090             if (indentInNode.length >= indentToCode.length) {
67091               return node.slice(indentToCode.length);
67092             }
67093
67094             return node;
67095           }).join('\n');
67096         }
67097         /**
67098          * Tokenizer
67099          */
67100
67101
67102         var Tokenizer_1 = /*#__PURE__*/function () {
67103           function Tokenizer(options) {
67104             _classCallCheck$1(this, Tokenizer);
67105
67106             this.options = options || defaults$4;
67107           }
67108
67109           _createClass$1(Tokenizer, [{
67110             key: "space",
67111             value: function space(src) {
67112               var cap = this.rules.block.newline.exec(src);
67113
67114               if (cap) {
67115                 if (cap[0].length > 1) {
67116                   return {
67117                     type: 'space',
67118                     raw: cap[0]
67119                   };
67120                 }
67121
67122                 return {
67123                   raw: '\n'
67124                 };
67125               }
67126             }
67127           }, {
67128             key: "code",
67129             value: function code(src) {
67130               var cap = this.rules.block.code.exec(src);
67131
67132               if (cap) {
67133                 var text = cap[0].replace(/^ {1,4}/gm, '');
67134                 return {
67135                   type: 'code',
67136                   raw: cap[0],
67137                   codeBlockStyle: 'indented',
67138                   text: !this.options.pedantic ? rtrim(text, '\n') : text
67139                 };
67140               }
67141             }
67142           }, {
67143             key: "fences",
67144             value: function fences(src) {
67145               var cap = this.rules.block.fences.exec(src);
67146
67147               if (cap) {
67148                 var raw = cap[0];
67149                 var text = indentCodeCompensation(raw, cap[3] || '');
67150                 return {
67151                   type: 'code',
67152                   raw: raw,
67153                   lang: cap[2] ? cap[2].trim() : cap[2],
67154                   text: text
67155                 };
67156               }
67157             }
67158           }, {
67159             key: "heading",
67160             value: function heading(src) {
67161               var cap = this.rules.block.heading.exec(src);
67162
67163               if (cap) {
67164                 var text = cap[2].trim(); // remove trailing #s
67165
67166                 if (/#$/.test(text)) {
67167                   var trimmed = rtrim(text, '#');
67168
67169                   if (this.options.pedantic) {
67170                     text = trimmed.trim();
67171                   } else if (!trimmed || / $/.test(trimmed)) {
67172                     // CommonMark requires space before trailing #s
67173                     text = trimmed.trim();
67174                   }
67175                 }
67176
67177                 return {
67178                   type: 'heading',
67179                   raw: cap[0],
67180                   depth: cap[1].length,
67181                   text: text
67182                 };
67183               }
67184             }
67185           }, {
67186             key: "nptable",
67187             value: function nptable(src) {
67188               var cap = this.rules.block.nptable.exec(src);
67189
67190               if (cap) {
67191                 var item = {
67192                   type: 'table',
67193                   header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
67194                   align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
67195                   cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : [],
67196                   raw: cap[0]
67197                 };
67198
67199                 if (item.header.length === item.align.length) {
67200                   var l = item.align.length;
67201                   var i;
67202
67203                   for (i = 0; i < l; i++) {
67204                     if (/^ *-+: *$/.test(item.align[i])) {
67205                       item.align[i] = 'right';
67206                     } else if (/^ *:-+: *$/.test(item.align[i])) {
67207                       item.align[i] = 'center';
67208                     } else if (/^ *:-+ *$/.test(item.align[i])) {
67209                       item.align[i] = 'left';
67210                     } else {
67211                       item.align[i] = null;
67212                     }
67213                   }
67214
67215                   l = item.cells.length;
67216
67217                   for (i = 0; i < l; i++) {
67218                     item.cells[i] = splitCells(item.cells[i], item.header.length);
67219                   }
67220
67221                   return item;
67222                 }
67223               }
67224             }
67225           }, {
67226             key: "hr",
67227             value: function hr(src) {
67228               var cap = this.rules.block.hr.exec(src);
67229
67230               if (cap) {
67231                 return {
67232                   type: 'hr',
67233                   raw: cap[0]
67234                 };
67235               }
67236             }
67237           }, {
67238             key: "blockquote",
67239             value: function blockquote(src) {
67240               var cap = this.rules.block.blockquote.exec(src);
67241
67242               if (cap) {
67243                 var text = cap[0].replace(/^ *> ?/gm, '');
67244                 return {
67245                   type: 'blockquote',
67246                   raw: cap[0],
67247                   text: text
67248                 };
67249               }
67250             }
67251           }, {
67252             key: "list",
67253             value: function list(src) {
67254               var cap = this.rules.block.list.exec(src);
67255
67256               if (cap) {
67257                 var raw = cap[0];
67258                 var bull = cap[2];
67259                 var isordered = bull.length > 1;
67260                 var list = {
67261                   type: 'list',
67262                   raw: raw,
67263                   ordered: isordered,
67264                   start: isordered ? +bull.slice(0, -1) : '',
67265                   loose: false,
67266                   items: []
67267                 }; // Get each top-level item.
67268
67269                 var itemMatch = cap[0].match(this.rules.block.item);
67270                 var next = false,
67271                     item,
67272                     space,
67273                     bcurr,
67274                     bnext,
67275                     addBack,
67276                     loose,
67277                     istask,
67278                     ischecked,
67279                     endMatch;
67280                 var l = itemMatch.length;
67281                 bcurr = this.rules.block.listItemStart.exec(itemMatch[0]);
67282
67283                 for (var i = 0; i < l; i++) {
67284                   item = itemMatch[i];
67285                   raw = item;
67286
67287                   if (!this.options.pedantic) {
67288                     // Determine if current item contains the end of the list
67289                     endMatch = item.match(new RegExp('\\n\\s*\\n {0,' + (bcurr[0].length - 1) + '}\\S'));
67290
67291                     if (endMatch) {
67292                       addBack = item.length - endMatch.index + itemMatch.slice(i + 1).join('\n').length;
67293                       list.raw = list.raw.substring(0, list.raw.length - addBack);
67294                       item = item.substring(0, endMatch.index);
67295                       raw = item;
67296                       l = i + 1;
67297                     }
67298                   } // Determine whether the next list item belongs here.
67299                   // Backpedal if it does not belong in this list.
67300
67301
67302                   if (i !== l - 1) {
67303                     bnext = this.rules.block.listItemStart.exec(itemMatch[i + 1]);
67304
67305                     if (!this.options.pedantic ? bnext[1].length >= bcurr[0].length || bnext[1].length > 3 : bnext[1].length > bcurr[1].length) {
67306                       // nested list or continuation
67307                       itemMatch.splice(i, 2, itemMatch[i] + (!this.options.pedantic && bnext[1].length < bcurr[0].length && !itemMatch[i].match(/\n$/) ? '' : '\n') + itemMatch[i + 1]);
67308                       i--;
67309                       l--;
67310                       continue;
67311                     } else if ( // different bullet style
67312                     !this.options.pedantic || this.options.smartLists ? bnext[2][bnext[2].length - 1] !== bull[bull.length - 1] : isordered === (bnext[2].length === 1)) {
67313                       addBack = itemMatch.slice(i + 1).join('\n').length;
67314                       list.raw = list.raw.substring(0, list.raw.length - addBack);
67315                       i = l - 1;
67316                     }
67317
67318                     bcurr = bnext;
67319                   } // Remove the list item's bullet
67320                   // so it is seen as the next token.
67321
67322
67323                   space = item.length;
67324                   item = item.replace(/^ *([*+-]|\d+[.)]) ?/, ''); // Outdent whatever the
67325                   // list item contains. Hacky.
67326
67327                   if (~item.indexOf('\n ')) {
67328                     space -= item.length;
67329                     item = !this.options.pedantic ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') : item.replace(/^ {1,4}/gm, '');
67330                   } // trim item newlines at end
67331
67332
67333                   item = rtrim(item, '\n');
67334
67335                   if (i !== l - 1) {
67336                     raw = raw + '\n';
67337                   } // Determine whether item is loose or not.
67338                   // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
67339                   // for discount behavior.
67340
67341
67342                   loose = next || /\n\n(?!\s*$)/.test(raw);
67343
67344                   if (i !== l - 1) {
67345                     next = raw.slice(-2) === '\n\n';
67346                     if (!loose) loose = next;
67347                   }
67348
67349                   if (loose) {
67350                     list.loose = true;
67351                   } // Check for task list items
67352
67353
67354                   if (this.options.gfm) {
67355                     istask = /^\[[ xX]\] /.test(item);
67356                     ischecked = undefined;
67357
67358                     if (istask) {
67359                       ischecked = item[1] !== ' ';
67360                       item = item.replace(/^\[[ xX]\] +/, '');
67361                     }
67362                   }
67363
67364                   list.items.push({
67365                     type: 'list_item',
67366                     raw: raw,
67367                     task: istask,
67368                     checked: ischecked,
67369                     loose: loose,
67370                     text: item
67371                   });
67372                 }
67373
67374                 return list;
67375               }
67376             }
67377           }, {
67378             key: "html",
67379             value: function html(src) {
67380               var cap = this.rules.block.html.exec(src);
67381
67382               if (cap) {
67383                 return {
67384                   type: this.options.sanitize ? 'paragraph' : 'html',
67385                   raw: cap[0],
67386                   pre: !this.options.sanitizer && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
67387                   text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : _escape(cap[0]) : cap[0]
67388                 };
67389               }
67390             }
67391           }, {
67392             key: "def",
67393             value: function def(src) {
67394               var cap = this.rules.block.def.exec(src);
67395
67396               if (cap) {
67397                 if (cap[3]) cap[3] = cap[3].substring(1, cap[3].length - 1);
67398                 var tag = cap[1].toLowerCase().replace(/\s+/g, ' ');
67399                 return {
67400                   type: 'def',
67401                   tag: tag,
67402                   raw: cap[0],
67403                   href: cap[2],
67404                   title: cap[3]
67405                 };
67406               }
67407             }
67408           }, {
67409             key: "table",
67410             value: function table(src) {
67411               var cap = this.rules.block.table.exec(src);
67412
67413               if (cap) {
67414                 var item = {
67415                   type: 'table',
67416                   header: splitCells(cap[1].replace(/^ *| *\| *$/g, '')),
67417                   align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
67418                   cells: cap[3] ? cap[3].replace(/\n$/, '').split('\n') : []
67419                 };
67420
67421                 if (item.header.length === item.align.length) {
67422                   item.raw = cap[0];
67423                   var l = item.align.length;
67424                   var i;
67425
67426                   for (i = 0; i < l; i++) {
67427                     if (/^ *-+: *$/.test(item.align[i])) {
67428                       item.align[i] = 'right';
67429                     } else if (/^ *:-+: *$/.test(item.align[i])) {
67430                       item.align[i] = 'center';
67431                     } else if (/^ *:-+ *$/.test(item.align[i])) {
67432                       item.align[i] = 'left';
67433                     } else {
67434                       item.align[i] = null;
67435                     }
67436                   }
67437
67438                   l = item.cells.length;
67439
67440                   for (i = 0; i < l; i++) {
67441                     item.cells[i] = splitCells(item.cells[i].replace(/^ *\| *| *\| *$/g, ''), item.header.length);
67442                   }
67443
67444                   return item;
67445                 }
67446               }
67447             }
67448           }, {
67449             key: "lheading",
67450             value: function lheading(src) {
67451               var cap = this.rules.block.lheading.exec(src);
67452
67453               if (cap) {
67454                 return {
67455                   type: 'heading',
67456                   raw: cap[0],
67457                   depth: cap[2].charAt(0) === '=' ? 1 : 2,
67458                   text: cap[1]
67459                 };
67460               }
67461             }
67462           }, {
67463             key: "paragraph",
67464             value: function paragraph(src) {
67465               var cap = this.rules.block.paragraph.exec(src);
67466
67467               if (cap) {
67468                 return {
67469                   type: 'paragraph',
67470                   raw: cap[0],
67471                   text: cap[1].charAt(cap[1].length - 1) === '\n' ? cap[1].slice(0, -1) : cap[1]
67472                 };
67473               }
67474             }
67475           }, {
67476             key: "text",
67477             value: function text(src) {
67478               var cap = this.rules.block.text.exec(src);
67479
67480               if (cap) {
67481                 return {
67482                   type: 'text',
67483                   raw: cap[0],
67484                   text: cap[0]
67485                 };
67486               }
67487             }
67488           }, {
67489             key: "escape",
67490             value: function escape(src) {
67491               var cap = this.rules.inline.escape.exec(src);
67492
67493               if (cap) {
67494                 return {
67495                   type: 'escape',
67496                   raw: cap[0],
67497                   text: _escape(cap[1])
67498                 };
67499               }
67500             }
67501           }, {
67502             key: "tag",
67503             value: function tag(src, inLink, inRawBlock) {
67504               var cap = this.rules.inline.tag.exec(src);
67505
67506               if (cap) {
67507                 if (!inLink && /^<a /i.test(cap[0])) {
67508                   inLink = true;
67509                 } else if (inLink && /^<\/a>/i.test(cap[0])) {
67510                   inLink = false;
67511                 }
67512
67513                 if (!inRawBlock && /^<(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
67514                   inRawBlock = true;
67515                 } else if (inRawBlock && /^<\/(pre|code|kbd|script)(\s|>)/i.test(cap[0])) {
67516                   inRawBlock = false;
67517                 }
67518
67519                 return {
67520                   type: this.options.sanitize ? 'text' : 'html',
67521                   raw: cap[0],
67522                   inLink: inLink,
67523                   inRawBlock: inRawBlock,
67524                   text: this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : _escape(cap[0]) : cap[0]
67525                 };
67526               }
67527             }
67528           }, {
67529             key: "link",
67530             value: function link(src) {
67531               var cap = this.rules.inline.link.exec(src);
67532
67533               if (cap) {
67534                 var trimmedUrl = cap[2].trim();
67535
67536                 if (!this.options.pedantic && /^</.test(trimmedUrl)) {
67537                   // commonmark requires matching angle brackets
67538                   if (!/>$/.test(trimmedUrl)) {
67539                     return;
67540                   } // ending angle bracket cannot be escaped
67541
67542
67543                   var rtrimSlash = rtrim(trimmedUrl.slice(0, -1), '\\');
67544
67545                   if ((trimmedUrl.length - rtrimSlash.length) % 2 === 0) {
67546                     return;
67547                   }
67548                 } else {
67549                   // find closing parenthesis
67550                   var lastParenIndex = findClosingBracket(cap[2], '()');
67551
67552                   if (lastParenIndex > -1) {
67553                     var start = cap[0].indexOf('!') === 0 ? 5 : 4;
67554                     var linkLen = start + cap[1].length + lastParenIndex;
67555                     cap[2] = cap[2].substring(0, lastParenIndex);
67556                     cap[0] = cap[0].substring(0, linkLen).trim();
67557                     cap[3] = '';
67558                   }
67559                 }
67560
67561                 var href = cap[2];
67562                 var title = '';
67563
67564                 if (this.options.pedantic) {
67565                   // split pedantic href and title
67566                   var link = /^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(href);
67567
67568                   if (link) {
67569                     href = link[1];
67570                     title = link[3];
67571                   }
67572                 } else {
67573                   title = cap[3] ? cap[3].slice(1, -1) : '';
67574                 }
67575
67576                 href = href.trim();
67577
67578                 if (/^</.test(href)) {
67579                   if (this.options.pedantic && !/>$/.test(trimmedUrl)) {
67580                     // pedantic allows starting angle bracket without ending angle bracket
67581                     href = href.slice(1);
67582                   } else {
67583                     href = href.slice(1, -1);
67584                   }
67585                 }
67586
67587                 return outputLink(cap, {
67588                   href: href ? href.replace(this.rules.inline._escapes, '$1') : href,
67589                   title: title ? title.replace(this.rules.inline._escapes, '$1') : title
67590                 }, cap[0]);
67591               }
67592             }
67593           }, {
67594             key: "reflink",
67595             value: function reflink(src, links) {
67596               var cap;
67597
67598               if ((cap = this.rules.inline.reflink.exec(src)) || (cap = this.rules.inline.nolink.exec(src))) {
67599                 var link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
67600                 link = links[link.toLowerCase()];
67601
67602                 if (!link || !link.href) {
67603                   var text = cap[0].charAt(0);
67604                   return {
67605                     type: 'text',
67606                     raw: text,
67607                     text: text
67608                   };
67609                 }
67610
67611                 return outputLink(cap, link, cap[0]);
67612               }
67613             }
67614           }, {
67615             key: "emStrong",
67616             value: function emStrong(src, maskedSrc) {
67617               var prevChar = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
67618               var match = this.rules.inline.emStrong.lDelim.exec(src);
67619               if (!match) return; // _ can't be between two alphanumerics. \p{L}\p{N} includes non-english alphabet/numbers as well
67620
67621               if (match[3] && prevChar.match(/(?:[0-9A-Za-z\xAA\xB2\xB3\xB5\xB9\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088E\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71-\u0B77\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5D\u0C60\u0C61\u0C66-\u0C6F\u0C78-\u0C7E\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDD\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D58-\u0D61\u0D66-\u0D78\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1369-\u137C\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C88\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070\u2071\u2074-\u2079\u207F-\u2089\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2CFD\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u3192-\u3195\u31A0-\u31BF\u31F0-\u31FF\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7CA\uA7D0\uA7D1\uA7D3\uA7D5-\uA7D9\uA7F2-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA830-\uA835\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDE80-\uDE9C\uDEA0-\uDED0\uDEE1-\uDEFB\uDF00-\uDF23\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC58-\uDC76\uDC79-\uDC9E\uDCA7-\uDCAF\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDD1B\uDD20-\uDD39\uDD80-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE40-\uDE48\uDE60-\uDE7E\uDE80-\uDE9F\uDEC0-\uDEC7\uDEC9-\uDEE4\uDEEB-\uDEEF\uDF00-\uDF35\uDF40-\uDF55\uDF58-\uDF72\uDF78-\uDF91\uDFA9-\uDFAF]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDD23\uDD30-\uDD39\uDE60-\uDE7E\uDE80-\uDEA9\uDEB0\uDEB1\uDF00-\uDF27\uDF30-\uDF45\uDF51-\uDF54\uDF70-\uDF81\uDFB0-\uDFCB\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC52-\uDC6F\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDDE1-\uDDF4\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDF00-\uDF1A\uDF30-\uDF3B\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCF2\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC6C\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDEE0-\uDEF2\uDFB0\uDFC0-\uDFD4]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD81C-\uD820\uD822\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879\uD880-\uD883][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDE70-\uDEBE\uDEC0-\uDEC9\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDE40-\uDE96\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3]|\uD821[\uDC00-\uDFF7]|\uD823[\uDC00-\uDCD5\uDD00-\uDD08]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD50-\uDD52\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD834[\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD837[\uDF00-\uDF1E]|\uD838[\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD839[\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDCC7-\uDCCF\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDD01-\uDD2D\uDD2F-\uDD3D\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD00-\uDD0C]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF38\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A])/)) return;
67622               var nextChar = match[1] || match[2] || '';
67623
67624               if (!nextChar || nextChar && (prevChar === '' || this.rules.inline.punctuation.exec(prevChar))) {
67625                 var lLength = match[0].length - 1;
67626                 var rDelim,
67627                     rLength,
67628                     delimTotal = lLength,
67629                     midDelimTotal = 0;
67630                 var endReg = match[0][0] === '*' ? this.rules.inline.emStrong.rDelimAst : this.rules.inline.emStrong.rDelimUnd;
67631                 endReg.lastIndex = 0; // Clip maskedSrc to same section of string as src (move to lexer?)
67632
67633                 maskedSrc = maskedSrc.slice(-1 * src.length + lLength);
67634
67635                 while ((match = endReg.exec(maskedSrc)) != null) {
67636                   rDelim = match[1] || match[2] || match[3] || match[4] || match[5] || match[6];
67637                   if (!rDelim) continue; // skip single * in __abc*abc__
67638
67639                   rLength = rDelim.length;
67640
67641                   if (match[3] || match[4]) {
67642                     // found another Left Delim
67643                     delimTotal += rLength;
67644                     continue;
67645                   } else if (match[5] || match[6]) {
67646                     // either Left or Right Delim
67647                     if (lLength % 3 && !((lLength + rLength) % 3)) {
67648                       midDelimTotal += rLength;
67649                       continue; // CommonMark Emphasis Rules 9-10
67650                     }
67651                   }
67652
67653                   delimTotal -= rLength;
67654                   if (delimTotal > 0) continue; // Haven't found enough closing delimiters
67655                   // Remove extra characters. *a*** -> *a*
67656
67657                   rLength = Math.min(rLength, rLength + delimTotal + midDelimTotal); // Create `em` if smallest delimiter has odd char count. *a***
67658
67659                   if (Math.min(lLength, rLength) % 2) {
67660                     return {
67661                       type: 'em',
67662                       raw: src.slice(0, lLength + match.index + rLength + 1),
67663                       text: src.slice(1, lLength + match.index + rLength)
67664                     };
67665                   } // Create 'strong' if smallest delimiter has even char count. **a***
67666
67667
67668                   return {
67669                     type: 'strong',
67670                     raw: src.slice(0, lLength + match.index + rLength + 1),
67671                     text: src.slice(2, lLength + match.index + rLength - 1)
67672                   };
67673                 }
67674               }
67675             }
67676           }, {
67677             key: "codespan",
67678             value: function codespan(src) {
67679               var cap = this.rules.inline.code.exec(src);
67680
67681               if (cap) {
67682                 var text = cap[2].replace(/\n/g, ' ');
67683                 var hasNonSpaceChars = /[^ ]/.test(text);
67684                 var hasSpaceCharsOnBothEnds = /^ /.test(text) && / $/.test(text);
67685
67686                 if (hasNonSpaceChars && hasSpaceCharsOnBothEnds) {
67687                   text = text.substring(1, text.length - 1);
67688                 }
67689
67690                 text = _escape(text, true);
67691                 return {
67692                   type: 'codespan',
67693                   raw: cap[0],
67694                   text: text
67695                 };
67696               }
67697             }
67698           }, {
67699             key: "br",
67700             value: function br(src) {
67701               var cap = this.rules.inline.br.exec(src);
67702
67703               if (cap) {
67704                 return {
67705                   type: 'br',
67706                   raw: cap[0]
67707                 };
67708               }
67709             }
67710           }, {
67711             key: "del",
67712             value: function del(src) {
67713               var cap = this.rules.inline.del.exec(src);
67714
67715               if (cap) {
67716                 return {
67717                   type: 'del',
67718                   raw: cap[0],
67719                   text: cap[2]
67720                 };
67721               }
67722             }
67723           }, {
67724             key: "autolink",
67725             value: function autolink(src, mangle) {
67726               var cap = this.rules.inline.autolink.exec(src);
67727
67728               if (cap) {
67729                 var text, href;
67730
67731                 if (cap[2] === '@') {
67732                   text = _escape(this.options.mangle ? mangle(cap[1]) : cap[1]);
67733                   href = 'mailto:' + text;
67734                 } else {
67735                   text = _escape(cap[1]);
67736                   href = text;
67737                 }
67738
67739                 return {
67740                   type: 'link',
67741                   raw: cap[0],
67742                   text: text,
67743                   href: href,
67744                   tokens: [{
67745                     type: 'text',
67746                     raw: text,
67747                     text: text
67748                   }]
67749                 };
67750               }
67751             }
67752           }, {
67753             key: "url",
67754             value: function url(src, mangle) {
67755               var cap;
67756
67757               if (cap = this.rules.inline.url.exec(src)) {
67758                 var text, href;
67759
67760                 if (cap[2] === '@') {
67761                   text = _escape(this.options.mangle ? mangle(cap[0]) : cap[0]);
67762                   href = 'mailto:' + text;
67763                 } else {
67764                   // do extended autolink path validation
67765                   var prevCapZero;
67766
67767                   do {
67768                     prevCapZero = cap[0];
67769                     cap[0] = this.rules.inline._backpedal.exec(cap[0])[0];
67770                   } while (prevCapZero !== cap[0]);
67771
67772                   text = _escape(cap[0]);
67773
67774                   if (cap[1] === 'www.') {
67775                     href = 'http://' + text;
67776                   } else {
67777                     href = text;
67778                   }
67779                 }
67780
67781                 return {
67782                   type: 'link',
67783                   raw: cap[0],
67784                   text: text,
67785                   href: href,
67786                   tokens: [{
67787                     type: 'text',
67788                     raw: text,
67789                     text: text
67790                   }]
67791                 };
67792               }
67793             }
67794           }, {
67795             key: "inlineText",
67796             value: function inlineText(src, inRawBlock, smartypants) {
67797               var cap = this.rules.inline.text.exec(src);
67798
67799               if (cap) {
67800                 var text;
67801
67802                 if (inRawBlock) {
67803                   text = this.options.sanitize ? this.options.sanitizer ? this.options.sanitizer(cap[0]) : _escape(cap[0]) : cap[0];
67804                 } else {
67805                   text = _escape(this.options.smartypants ? smartypants(cap[0]) : cap[0]);
67806                 }
67807
67808                 return {
67809                   type: 'text',
67810                   raw: cap[0],
67811                   text: text
67812                 };
67813               }
67814             }
67815           }]);
67816
67817           return Tokenizer;
67818         }();
67819
67820         var noopTest = helpers.noopTest,
67821             edit = helpers.edit,
67822             merge$1 = helpers.merge;
67823         /**
67824          * Block-Level Grammar
67825          */
67826
67827         var block$1 = {
67828           newline: /^(?: *(?:\n|$))+/,
67829           code: /^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,
67830           fences: /^ {0,3}(`{3,}(?=[^`\n]*\n)|~{3,})([^\n]*)\n(?:|([\s\S]*?)\n)(?: {0,3}\1[~`]* *(?:\n+|$)|$)/,
67831           hr: /^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,
67832           heading: /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,
67833           blockquote: /^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,
67834           list: /^( {0,3})(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?! {0,3}bull )\n*|\s*$)/,
67835           html: '^ {0,3}(?:' // optional indentation
67836           + '<(script|pre|style)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)' // (1)
67837           + '|comment[^\\n]*(\\n+|$)' // (2)
67838           + '|<\\?[\\s\\S]*?(?:\\?>\\n*|$)' // (3)
67839           + '|<![A-Z][\\s\\S]*?(?:>\\n*|$)' // (4)
67840           + '|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)' // (5)
67841           + '|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (6)
67842           + '|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) open tag
67843           + '|</(?!script|pre|style)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)' // (7) closing tag
67844           + ')',
67845           def: /^ {0,3}\[(label)\]: *\n? *<?([^\s>]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,
67846           nptable: noopTest,
67847           table: noopTest,
67848           lheading: /^([^\n]+)\n {0,3}(=+|-+) *(?:\n+|$)/,
67849           // regex template, placeholders will be replaced according to different paragraph
67850           // interruption rules of commonmark and the original markdown spec:
67851           _paragraph: /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html| +\n)[^\n]+)*)/,
67852           text: /^[^\n]+/
67853         };
67854         block$1._label = /(?!\s*\])(?:\\[\[\]]|[^\[\]])+/;
67855         block$1._title = /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/;
67856         block$1.def = edit(block$1.def).replace('label', block$1._label).replace('title', block$1._title).getRegex();
67857         block$1.bullet = /(?:[*+-]|\d{1,9}[.)])/;
67858         block$1.item = /^( *)(bull) ?[^\n]*(?:\n(?! *bull ?)[^\n]*)*/;
67859         block$1.item = edit(block$1.item, 'gm').replace(/bull/g, block$1.bullet).getRegex();
67860         block$1.listItemStart = edit(/^( *)(bull) */).replace('bull', block$1.bullet).getRegex();
67861         block$1.list = edit(block$1.list).replace(/bull/g, block$1.bullet).replace('hr', '\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))').replace('def', '\\n+(?=' + block$1.def.source + ')').getRegex();
67862         block$1._tag = 'address|article|aside|base|basefont|blockquote|body|caption' + '|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption' + '|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe' + '|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option' + '|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr' + '|track|ul';
67863         block$1._comment = /<!--(?!-?>)[\s\S]*?(?:-->|$)/;
67864         block$1.html = edit(block$1.html, 'i').replace('comment', block$1._comment).replace('tag', block$1._tag).replace('attribute', / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
67865         block$1.paragraph = edit(block$1._paragraph).replace('hr', block$1.hr).replace('heading', ' {0,3}#{1,6} ').replace('|lheading', '') // setex headings don't interrupt commonmark paragraphs
67866         .replace('blockquote', ' {0,3}>').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
67867         .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)').replace('tag', block$1._tag) // pars can be interrupted by type (6) html blocks
67868         .getRegex();
67869         block$1.blockquote = edit(block$1.blockquote).replace('paragraph', block$1.paragraph).getRegex();
67870         /**
67871          * Normal Block Grammar
67872          */
67873
67874         block$1.normal = merge$1({}, block$1);
67875         /**
67876          * GFM Block Grammar
67877          */
67878
67879         block$1.gfm = merge$1({}, block$1.normal, {
67880           nptable: '^ *([^|\\n ].*\\|.*)\\n' // Header
67881           + ' {0,3}([-:]+ *\\|[-| :]*)' // Align
67882           + '(?:\\n((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)',
67883           // Cells
67884           table: '^ *\\|(.+)\\n' // Header
67885           + ' {0,3}\\|?( *[-:]+[-| :]*)' // Align
67886           + '(?:\\n *((?:(?!\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)' // Cells
67887
67888         });
67889         block$1.gfm.nptable = edit(block$1.gfm.nptable).replace('hr', block$1.hr).replace('heading', ' {0,3}#{1,6} ').replace('blockquote', ' {0,3}>').replace('code', ' {4}[^\\n]').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
67890         .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)').replace('tag', block$1._tag) // tables can be interrupted by type (6) html blocks
67891         .getRegex();
67892         block$1.gfm.table = edit(block$1.gfm.table).replace('hr', block$1.hr).replace('heading', ' {0,3}#{1,6} ').replace('blockquote', ' {0,3}>').replace('code', ' {4}[^\\n]').replace('fences', ' {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n').replace('list', ' {0,3}(?:[*+-]|1[.)]) ') // only lists starting from 1 can interrupt
67893         .replace('html', '</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|!--)').replace('tag', block$1._tag) // tables can be interrupted by type (6) html blocks
67894         .getRegex();
67895         /**
67896          * Pedantic grammar (original John Gruber's loose markdown specification)
67897          */
67898
67899         block$1.pedantic = merge$1({}, block$1.normal, {
67900           html: edit('^ *(?:comment *(?:\\n|\\s*$)' + '|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)' // closed tag
67901           + '|<tag(?:"[^"]*"|\'[^\']*\'|\\s[^\'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))').replace('comment', block$1._comment).replace(/tag/g, '(?!(?:' + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub' + '|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)' + '\\b)\\w+(?!:|[^\\w\\s@]*@)\\b').getRegex(),
67902           def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,
67903           heading: /^(#{1,6})(.*)(?:\n+|$)/,
67904           fences: noopTest,
67905           // fences not supported
67906           paragraph: edit(block$1.normal._paragraph).replace('hr', block$1.hr).replace('heading', ' *#{1,6} *[^\n]').replace('lheading', block$1.lheading).replace('blockquote', ' {0,3}>').replace('|fences', '').replace('|list', '').replace('|html', '').getRegex()
67907         });
67908         /**
67909          * Inline-Level Grammar
67910          */
67911
67912         var inline$1 = {
67913           escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,
67914           autolink: /^<(scheme:[^\s\x00-\x1f<>]*|email)>/,
67915           url: noopTest,
67916           tag: '^comment' + '|^</[a-zA-Z][\\w:-]*\\s*>' // self-closing tag
67917           + '|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>' // open tag
67918           + '|^<\\?[\\s\\S]*?\\?>' // processing instruction, e.g. <?php ?>
67919           + '|^<![a-zA-Z]+\\s[\\s\\S]*?>' // declaration, e.g. <!DOCTYPE html>
67920           + '|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>',
67921           // CDATA section
67922           link: /^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/,
67923           reflink: /^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,
67924           nolink: /^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,
67925           reflinkSearch: 'reflink|nolink(?!\\()',
67926           emStrong: {
67927             lDelim: /^(?:\*+(?:([punct_])|[^\s*]))|^_+(?:([punct*])|([^\s_]))/,
67928             //        (1) and (2) can only be a Right Delimiter. (3) and (4) can only be Left.  (5) and (6) can be either Left or Right.
67929             //        () Skip other delimiter (1) #***                   (2) a***#, a***                   (3) #***a, ***a                 (4) ***#              (5) #***#                 (6) a***a
67930             rDelimAst: /\_\_[^_*]*?\*[^_*]*?\_\_|[punct_](\*+)(?=[\s]|$)|[^punct*_\s](\*+)(?=[punct_\s]|$)|[punct_\s](\*+)(?=[^punct*_\s])|[\s](\*+)(?=[punct_])|[punct_](\*+)(?=[punct_])|[^punct*_\s](\*+)(?=[^punct*_\s])/,
67931             rDelimUnd: /\*\*[^_*]*?\_[^_*]*?\*\*|[punct*](\_+)(?=[\s]|$)|[^punct*_\s](\_+)(?=[punct*\s]|$)|[punct*\s](\_+)(?=[^punct*_\s])|[\s](\_+)(?=[punct*])|[punct*](\_+)(?=[punct*])/ // ^- Not allowed for _
67932
67933           },
67934           code: /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,
67935           br: /^( {2,}|\\)\n(?!\s*$)/,
67936           del: noopTest,
67937           text: /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/,
67938           punctuation: /^([\spunctuation])/
67939         }; // list of punctuation marks from CommonMark spec
67940         // without * and _ to handle the different emphasis markers * and _
67941
67942         inline$1._punctuation = '!"#$%&\'()+\\-.,/:;<=>?@\\[\\]`^{|}~';
67943         inline$1.punctuation = edit(inline$1.punctuation).replace(/punctuation/g, inline$1._punctuation).getRegex(); // sequences em should skip over [title](link), `code`, <html>
67944
67945         inline$1.blockSkip = /\[[^\]]*?\]\([^\)]*?\)|`[^`]*?`|<[^>]*?>/g;
67946         inline$1.escapedEmSt = /\\\*|\\_/g;
67947         inline$1._comment = edit(block$1._comment).replace('(?:-->|$)', '-->').getRegex();
67948         inline$1.emStrong.lDelim = edit(inline$1.emStrong.lDelim).replace(/punct/g, inline$1._punctuation).getRegex();
67949         inline$1.emStrong.rDelimAst = edit(inline$1.emStrong.rDelimAst, 'g').replace(/punct/g, inline$1._punctuation).getRegex();
67950         inline$1.emStrong.rDelimUnd = edit(inline$1.emStrong.rDelimUnd, 'g').replace(/punct/g, inline$1._punctuation).getRegex();
67951         inline$1._escapes = /\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g;
67952         inline$1._scheme = /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/;
67953         inline$1._email = /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/;
67954         inline$1.autolink = edit(inline$1.autolink).replace('scheme', inline$1._scheme).replace('email', inline$1._email).getRegex();
67955         inline$1._attribute = /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/;
67956         inline$1.tag = edit(inline$1.tag).replace('comment', inline$1._comment).replace('attribute', inline$1._attribute).getRegex();
67957         inline$1._label = /(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/;
67958         inline$1._href = /<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/;
67959         inline$1._title = /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/;
67960         inline$1.link = edit(inline$1.link).replace('label', inline$1._label).replace('href', inline$1._href).replace('title', inline$1._title).getRegex();
67961         inline$1.reflink = edit(inline$1.reflink).replace('label', inline$1._label).getRegex();
67962         inline$1.reflinkSearch = edit(inline$1.reflinkSearch, 'g').replace('reflink', inline$1.reflink).replace('nolink', inline$1.nolink).getRegex();
67963         /**
67964          * Normal Inline Grammar
67965          */
67966
67967         inline$1.normal = merge$1({}, inline$1);
67968         /**
67969          * Pedantic Inline Grammar
67970          */
67971
67972         inline$1.pedantic = merge$1({}, inline$1.normal, {
67973           strong: {
67974             start: /^__|\*\*/,
67975             middle: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
67976             endAst: /\*\*(?!\*)/g,
67977             endUnd: /__(?!_)/g
67978           },
67979           em: {
67980             start: /^_|\*/,
67981             middle: /^()\*(?=\S)([\s\S]*?\S)\*(?!\*)|^_(?=\S)([\s\S]*?\S)_(?!_)/,
67982             endAst: /\*(?!\*)/g,
67983             endUnd: /_(?!_)/g
67984           },
67985           link: edit(/^!?\[(label)\]\((.*?)\)/).replace('label', inline$1._label).getRegex(),
67986           reflink: edit(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace('label', inline$1._label).getRegex()
67987         });
67988         /**
67989          * GFM Inline Grammar
67990          */
67991
67992         inline$1.gfm = merge$1({}, inline$1.normal, {
67993           escape: edit(inline$1.escape).replace('])', '~|])').getRegex(),
67994           _extended_email: /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/,
67995           url: /^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/,
67996           _backpedal: /(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,
67997           del: /^(~~?)(?=[^\s~])([\s\S]*?[^\s~])\1(?=[^~]|$)/,
67998           text: /^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|https?:\/\/|ftp:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/
67999         });
68000         inline$1.gfm.url = edit(inline$1.gfm.url, 'i').replace('email', inline$1.gfm._extended_email).getRegex();
68001         /**
68002          * GFM + Line Breaks Inline Grammar
68003          */
68004
68005         inline$1.breaks = merge$1({}, inline$1.gfm, {
68006           br: edit(inline$1.br).replace('{2,}', '*').getRegex(),
68007           text: edit(inline$1.gfm.text).replace('\\b_', '\\b_| {2,}\\n').replace(/\{2,\}/g, '*').getRegex()
68008         });
68009         var rules = {
68010           block: block$1,
68011           inline: inline$1
68012         };
68013
68014         var Tokenizer$1 = Tokenizer_1;
68015         var defaults$3 = defaults$5.exports.defaults;
68016         var block = rules.block,
68017             inline = rules.inline;
68018         var repeatString = helpers.repeatString;
68019         /**
68020          * smartypants text replacement
68021          */
68022
68023         function smartypants(text) {
68024           return text // em-dashes
68025           .replace(/---/g, "\u2014") // en-dashes
68026           .replace(/--/g, "\u2013") // opening singles
68027           .replace(/(^|[-\u2014/(\[{"\s])'/g, "$1\u2018") // closing singles & apostrophes
68028           .replace(/'/g, "\u2019") // opening doubles
68029           .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, "$1\u201C") // closing doubles
68030           .replace(/"/g, "\u201D") // ellipses
68031           .replace(/\.{3}/g, "\u2026");
68032         }
68033         /**
68034          * mangle email addresses
68035          */
68036
68037
68038         function mangle(text) {
68039           var out = '',
68040               i,
68041               ch;
68042           var l = text.length;
68043
68044           for (i = 0; i < l; i++) {
68045             ch = text.charCodeAt(i);
68046
68047             if (Math.random() > 0.5) {
68048               ch = 'x' + ch.toString(16);
68049             }
68050
68051             out += '&#' + ch + ';';
68052           }
68053
68054           return out;
68055         }
68056         /**
68057          * Block Lexer
68058          */
68059
68060
68061         var Lexer_1 = /*#__PURE__*/function () {
68062           function Lexer(options) {
68063             _classCallCheck$1(this, Lexer);
68064
68065             this.tokens = [];
68066             this.tokens.links = Object.create(null);
68067             this.options = options || defaults$3;
68068             this.options.tokenizer = this.options.tokenizer || new Tokenizer$1();
68069             this.tokenizer = this.options.tokenizer;
68070             this.tokenizer.options = this.options;
68071             var rules = {
68072               block: block.normal,
68073               inline: inline.normal
68074             };
68075
68076             if (this.options.pedantic) {
68077               rules.block = block.pedantic;
68078               rules.inline = inline.pedantic;
68079             } else if (this.options.gfm) {
68080               rules.block = block.gfm;
68081
68082               if (this.options.breaks) {
68083                 rules.inline = inline.breaks;
68084               } else {
68085                 rules.inline = inline.gfm;
68086               }
68087             }
68088
68089             this.tokenizer.rules = rules;
68090           }
68091           /**
68092            * Expose Rules
68093            */
68094
68095
68096           _createClass$1(Lexer, [{
68097             key: "lex",
68098             value:
68099             /**
68100              * Preprocessing
68101              */
68102             function lex(src) {
68103               src = src.replace(/\r\n|\r/g, '\n').replace(/\t/g, '    ');
68104               this.blockTokens(src, this.tokens, true);
68105               this.inline(this.tokens);
68106               return this.tokens;
68107             }
68108             /**
68109              * Lexing
68110              */
68111
68112           }, {
68113             key: "blockTokens",
68114             value: function blockTokens(src) {
68115               var tokens = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
68116               var top = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
68117
68118               if (this.options.pedantic) {
68119                 src = src.replace(/^ +$/gm, '');
68120               }
68121
68122               var token, i, l, lastToken;
68123
68124               while (src) {
68125                 // newline
68126                 if (token = this.tokenizer.space(src)) {
68127                   src = src.substring(token.raw.length);
68128
68129                   if (token.type) {
68130                     tokens.push(token);
68131                   }
68132
68133                   continue;
68134                 } // code
68135
68136
68137                 if (token = this.tokenizer.code(src)) {
68138                   src = src.substring(token.raw.length);
68139                   lastToken = tokens[tokens.length - 1]; // An indented code block cannot interrupt a paragraph.
68140
68141                   if (lastToken && lastToken.type === 'paragraph') {
68142                     lastToken.raw += '\n' + token.raw;
68143                     lastToken.text += '\n' + token.text;
68144                   } else {
68145                     tokens.push(token);
68146                   }
68147
68148                   continue;
68149                 } // fences
68150
68151
68152                 if (token = this.tokenizer.fences(src)) {
68153                   src = src.substring(token.raw.length);
68154                   tokens.push(token);
68155                   continue;
68156                 } // heading
68157
68158
68159                 if (token = this.tokenizer.heading(src)) {
68160                   src = src.substring(token.raw.length);
68161                   tokens.push(token);
68162                   continue;
68163                 } // table no leading pipe (gfm)
68164
68165
68166                 if (token = this.tokenizer.nptable(src)) {
68167                   src = src.substring(token.raw.length);
68168                   tokens.push(token);
68169                   continue;
68170                 } // hr
68171
68172
68173                 if (token = this.tokenizer.hr(src)) {
68174                   src = src.substring(token.raw.length);
68175                   tokens.push(token);
68176                   continue;
68177                 } // blockquote
68178
68179
68180                 if (token = this.tokenizer.blockquote(src)) {
68181                   src = src.substring(token.raw.length);
68182                   token.tokens = this.blockTokens(token.text, [], top);
68183                   tokens.push(token);
68184                   continue;
68185                 } // list
68186
68187
68188                 if (token = this.tokenizer.list(src)) {
68189                   src = src.substring(token.raw.length);
68190                   l = token.items.length;
68191
68192                   for (i = 0; i < l; i++) {
68193                     token.items[i].tokens = this.blockTokens(token.items[i].text, [], false);
68194                   }
68195
68196                   tokens.push(token);
68197                   continue;
68198                 } // html
68199
68200
68201                 if (token = this.tokenizer.html(src)) {
68202                   src = src.substring(token.raw.length);
68203                   tokens.push(token);
68204                   continue;
68205                 } // def
68206
68207
68208                 if (top && (token = this.tokenizer.def(src))) {
68209                   src = src.substring(token.raw.length);
68210
68211                   if (!this.tokens.links[token.tag]) {
68212                     this.tokens.links[token.tag] = {
68213                       href: token.href,
68214                       title: token.title
68215                     };
68216                   }
68217
68218                   continue;
68219                 } // table (gfm)
68220
68221
68222                 if (token = this.tokenizer.table(src)) {
68223                   src = src.substring(token.raw.length);
68224                   tokens.push(token);
68225                   continue;
68226                 } // lheading
68227
68228
68229                 if (token = this.tokenizer.lheading(src)) {
68230                   src = src.substring(token.raw.length);
68231                   tokens.push(token);
68232                   continue;
68233                 } // top-level paragraph
68234
68235
68236                 if (top && (token = this.tokenizer.paragraph(src))) {
68237                   src = src.substring(token.raw.length);
68238                   tokens.push(token);
68239                   continue;
68240                 } // text
68241
68242
68243                 if (token = this.tokenizer.text(src)) {
68244                   src = src.substring(token.raw.length);
68245                   lastToken = tokens[tokens.length - 1];
68246
68247                   if (lastToken && lastToken.type === 'text') {
68248                     lastToken.raw += '\n' + token.raw;
68249                     lastToken.text += '\n' + token.text;
68250                   } else {
68251                     tokens.push(token);
68252                   }
68253
68254                   continue;
68255                 }
68256
68257                 if (src) {
68258                   var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
68259
68260                   if (this.options.silent) {
68261                     console.error(errMsg);
68262                     break;
68263                   } else {
68264                     throw new Error(errMsg);
68265                   }
68266                 }
68267               }
68268
68269               return tokens;
68270             }
68271           }, {
68272             key: "inline",
68273             value: function inline(tokens) {
68274               var i, j, k, l2, row, token;
68275               var l = tokens.length;
68276
68277               for (i = 0; i < l; i++) {
68278                 token = tokens[i];
68279
68280                 switch (token.type) {
68281                   case 'paragraph':
68282                   case 'text':
68283                   case 'heading':
68284                     {
68285                       token.tokens = [];
68286                       this.inlineTokens(token.text, token.tokens);
68287                       break;
68288                     }
68289
68290                   case 'table':
68291                     {
68292                       token.tokens = {
68293                         header: [],
68294                         cells: []
68295                       }; // header
68296
68297                       l2 = token.header.length;
68298
68299                       for (j = 0; j < l2; j++) {
68300                         token.tokens.header[j] = [];
68301                         this.inlineTokens(token.header[j], token.tokens.header[j]);
68302                       } // cells
68303
68304
68305                       l2 = token.cells.length;
68306
68307                       for (j = 0; j < l2; j++) {
68308                         row = token.cells[j];
68309                         token.tokens.cells[j] = [];
68310
68311                         for (k = 0; k < row.length; k++) {
68312                           token.tokens.cells[j][k] = [];
68313                           this.inlineTokens(row[k], token.tokens.cells[j][k]);
68314                         }
68315                       }
68316
68317                       break;
68318                     }
68319
68320                   case 'blockquote':
68321                     {
68322                       this.inline(token.tokens);
68323                       break;
68324                     }
68325
68326                   case 'list':
68327                     {
68328                       l2 = token.items.length;
68329
68330                       for (j = 0; j < l2; j++) {
68331                         this.inline(token.items[j].tokens);
68332                       }
68333
68334                       break;
68335                     }
68336                 }
68337               }
68338
68339               return tokens;
68340             }
68341             /**
68342              * Lexing/Compiling
68343              */
68344
68345           }, {
68346             key: "inlineTokens",
68347             value: function inlineTokens(src) {
68348               var tokens = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
68349               var inLink = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
68350               var inRawBlock = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
68351               var token, lastToken; // String with links masked to avoid interference with em and strong
68352
68353               var maskedSrc = src;
68354               var match;
68355               var keepPrevChar, prevChar; // Mask out reflinks
68356
68357               if (this.tokens.links) {
68358                 var links = Object.keys(this.tokens.links);
68359
68360                 if (links.length > 0) {
68361                   while ((match = this.tokenizer.rules.inline.reflinkSearch.exec(maskedSrc)) != null) {
68362                     if (links.includes(match[0].slice(match[0].lastIndexOf('[') + 1, -1))) {
68363                       maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex);
68364                     }
68365                   }
68366                 }
68367               } // Mask out other blocks
68368
68369
68370               while ((match = this.tokenizer.rules.inline.blockSkip.exec(maskedSrc)) != null) {
68371                 maskedSrc = maskedSrc.slice(0, match.index) + '[' + repeatString('a', match[0].length - 2) + ']' + maskedSrc.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
68372               } // Mask out escaped em & strong delimiters
68373
68374
68375               while ((match = this.tokenizer.rules.inline.escapedEmSt.exec(maskedSrc)) != null) {
68376                 maskedSrc = maskedSrc.slice(0, match.index) + '++' + maskedSrc.slice(this.tokenizer.rules.inline.escapedEmSt.lastIndex);
68377               }
68378
68379               while (src) {
68380                 if (!keepPrevChar) {
68381                   prevChar = '';
68382                 }
68383
68384                 keepPrevChar = false; // escape
68385
68386                 if (token = this.tokenizer.escape(src)) {
68387                   src = src.substring(token.raw.length);
68388                   tokens.push(token);
68389                   continue;
68390                 } // tag
68391
68392
68393                 if (token = this.tokenizer.tag(src, inLink, inRawBlock)) {
68394                   src = src.substring(token.raw.length);
68395                   inLink = token.inLink;
68396                   inRawBlock = token.inRawBlock;
68397                   var _lastToken = tokens[tokens.length - 1];
68398
68399                   if (_lastToken && token.type === 'text' && _lastToken.type === 'text') {
68400                     _lastToken.raw += token.raw;
68401                     _lastToken.text += token.text;
68402                   } else {
68403                     tokens.push(token);
68404                   }
68405
68406                   continue;
68407                 } // link
68408
68409
68410                 if (token = this.tokenizer.link(src)) {
68411                   src = src.substring(token.raw.length);
68412
68413                   if (token.type === 'link') {
68414                     token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
68415                   }
68416
68417                   tokens.push(token);
68418                   continue;
68419                 } // reflink, nolink
68420
68421
68422                 if (token = this.tokenizer.reflink(src, this.tokens.links)) {
68423                   src = src.substring(token.raw.length);
68424                   var _lastToken2 = tokens[tokens.length - 1];
68425
68426                   if (token.type === 'link') {
68427                     token.tokens = this.inlineTokens(token.text, [], true, inRawBlock);
68428                     tokens.push(token);
68429                   } else if (_lastToken2 && token.type === 'text' && _lastToken2.type === 'text') {
68430                     _lastToken2.raw += token.raw;
68431                     _lastToken2.text += token.text;
68432                   } else {
68433                     tokens.push(token);
68434                   }
68435
68436                   continue;
68437                 } // em & strong
68438
68439
68440                 if (token = this.tokenizer.emStrong(src, maskedSrc, prevChar)) {
68441                   src = src.substring(token.raw.length);
68442                   token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
68443                   tokens.push(token);
68444                   continue;
68445                 } // code
68446
68447
68448                 if (token = this.tokenizer.codespan(src)) {
68449                   src = src.substring(token.raw.length);
68450                   tokens.push(token);
68451                   continue;
68452                 } // br
68453
68454
68455                 if (token = this.tokenizer.br(src)) {
68456                   src = src.substring(token.raw.length);
68457                   tokens.push(token);
68458                   continue;
68459                 } // del (gfm)
68460
68461
68462                 if (token = this.tokenizer.del(src)) {
68463                   src = src.substring(token.raw.length);
68464                   token.tokens = this.inlineTokens(token.text, [], inLink, inRawBlock);
68465                   tokens.push(token);
68466                   continue;
68467                 } // autolink
68468
68469
68470                 if (token = this.tokenizer.autolink(src, mangle)) {
68471                   src = src.substring(token.raw.length);
68472                   tokens.push(token);
68473                   continue;
68474                 } // url (gfm)
68475
68476
68477                 if (!inLink && (token = this.tokenizer.url(src, mangle))) {
68478                   src = src.substring(token.raw.length);
68479                   tokens.push(token);
68480                   continue;
68481                 } // text
68482
68483
68484                 if (token = this.tokenizer.inlineText(src, inRawBlock, smartypants)) {
68485                   src = src.substring(token.raw.length);
68486
68487                   if (token.raw.slice(-1) !== '_') {
68488                     // Track prevChar before string of ____ started
68489                     prevChar = token.raw.slice(-1);
68490                   }
68491
68492                   keepPrevChar = true;
68493                   lastToken = tokens[tokens.length - 1];
68494
68495                   if (lastToken && lastToken.type === 'text') {
68496                     lastToken.raw += token.raw;
68497                     lastToken.text += token.text;
68498                   } else {
68499                     tokens.push(token);
68500                   }
68501
68502                   continue;
68503                 }
68504
68505                 if (src) {
68506                   var errMsg = 'Infinite loop on byte: ' + src.charCodeAt(0);
68507
68508                   if (this.options.silent) {
68509                     console.error(errMsg);
68510                     break;
68511                   } else {
68512                     throw new Error(errMsg);
68513                   }
68514                 }
68515               }
68516
68517               return tokens;
68518             }
68519           }], [{
68520             key: "rules",
68521             get: function get() {
68522               return {
68523                 block: block,
68524                 inline: inline
68525               };
68526             }
68527             /**
68528              * Static Lex Method
68529              */
68530
68531           }, {
68532             key: "lex",
68533             value: function lex(src, options) {
68534               var lexer = new Lexer(options);
68535               return lexer.lex(src);
68536             }
68537             /**
68538              * Static Lex Inline Method
68539              */
68540
68541           }, {
68542             key: "lexInline",
68543             value: function lexInline(src, options) {
68544               var lexer = new Lexer(options);
68545               return lexer.inlineTokens(src);
68546             }
68547           }]);
68548
68549           return Lexer;
68550         }();
68551
68552         var defaults$2 = defaults$5.exports.defaults;
68553         var cleanUrl = helpers.cleanUrl,
68554             escape$2 = helpers.escape;
68555         /**
68556          * Renderer
68557          */
68558
68559         var Renderer_1 = /*#__PURE__*/function () {
68560           function Renderer(options) {
68561             _classCallCheck$1(this, Renderer);
68562
68563             this.options = options || defaults$2;
68564           }
68565
68566           _createClass$1(Renderer, [{
68567             key: "code",
68568             value: function code(_code, infostring, escaped) {
68569               var lang = (infostring || '').match(/\S*/)[0];
68570
68571               if (this.options.highlight) {
68572                 var out = this.options.highlight(_code, lang);
68573
68574                 if (out != null && out !== _code) {
68575                   escaped = true;
68576                   _code = out;
68577                 }
68578               }
68579
68580               _code = _code.replace(/\n$/, '') + '\n';
68581
68582               if (!lang) {
68583                 return '<pre><code>' + (escaped ? _code : escape$2(_code, true)) + '</code></pre>\n';
68584               }
68585
68586               return '<pre><code class="' + this.options.langPrefix + escape$2(lang, true) + '">' + (escaped ? _code : escape$2(_code, true)) + '</code></pre>\n';
68587             }
68588           }, {
68589             key: "blockquote",
68590             value: function blockquote(quote) {
68591               return '<blockquote>\n' + quote + '</blockquote>\n';
68592             }
68593           }, {
68594             key: "html",
68595             value: function html(_html) {
68596               return _html;
68597             }
68598           }, {
68599             key: "heading",
68600             value: function heading(text, level, raw, slugger) {
68601               if (this.options.headerIds) {
68602                 return '<h' + level + ' id="' + this.options.headerPrefix + slugger.slug(raw) + '">' + text + '</h' + level + '>\n';
68603               } // ignore IDs
68604
68605
68606               return '<h' + level + '>' + text + '</h' + level + '>\n';
68607             }
68608           }, {
68609             key: "hr",
68610             value: function hr() {
68611               return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
68612             }
68613           }, {
68614             key: "list",
68615             value: function list(body, ordered, start) {
68616               var type = ordered ? 'ol' : 'ul',
68617                   startatt = ordered && start !== 1 ? ' start="' + start + '"' : '';
68618               return '<' + type + startatt + '>\n' + body + '</' + type + '>\n';
68619             }
68620           }, {
68621             key: "listitem",
68622             value: function listitem(text) {
68623               return '<li>' + text + '</li>\n';
68624             }
68625           }, {
68626             key: "checkbox",
68627             value: function checkbox(checked) {
68628               return '<input ' + (checked ? 'checked="" ' : '') + 'disabled="" type="checkbox"' + (this.options.xhtml ? ' /' : '') + '> ';
68629             }
68630           }, {
68631             key: "paragraph",
68632             value: function paragraph(text) {
68633               return '<p>' + text + '</p>\n';
68634             }
68635           }, {
68636             key: "table",
68637             value: function table(header, body) {
68638               if (body) body = '<tbody>' + body + '</tbody>';
68639               return '<table>\n' + '<thead>\n' + header + '</thead>\n' + body + '</table>\n';
68640             }
68641           }, {
68642             key: "tablerow",
68643             value: function tablerow(content) {
68644               return '<tr>\n' + content + '</tr>\n';
68645             }
68646           }, {
68647             key: "tablecell",
68648             value: function tablecell(content, flags) {
68649               var type = flags.header ? 'th' : 'td';
68650               var tag = flags.align ? '<' + type + ' align="' + flags.align + '">' : '<' + type + '>';
68651               return tag + content + '</' + type + '>\n';
68652             } // span level renderer
68653
68654           }, {
68655             key: "strong",
68656             value: function strong(text) {
68657               return '<strong>' + text + '</strong>';
68658             }
68659           }, {
68660             key: "em",
68661             value: function em(text) {
68662               return '<em>' + text + '</em>';
68663             }
68664           }, {
68665             key: "codespan",
68666             value: function codespan(text) {
68667               return '<code>' + text + '</code>';
68668             }
68669           }, {
68670             key: "br",
68671             value: function br() {
68672               return this.options.xhtml ? '<br/>' : '<br>';
68673             }
68674           }, {
68675             key: "del",
68676             value: function del(text) {
68677               return '<del>' + text + '</del>';
68678             }
68679           }, {
68680             key: "link",
68681             value: function link(href, title, text) {
68682               href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
68683
68684               if (href === null) {
68685                 return text;
68686               }
68687
68688               var out = '<a href="' + escape$2(href) + '"';
68689
68690               if (title) {
68691                 out += ' title="' + title + '"';
68692               }
68693
68694               out += '>' + text + '</a>';
68695               return out;
68696             }
68697           }, {
68698             key: "image",
68699             value: function image(href, title, text) {
68700               href = cleanUrl(this.options.sanitize, this.options.baseUrl, href);
68701
68702               if (href === null) {
68703                 return text;
68704               }
68705
68706               var out = '<img src="' + href + '" alt="' + text + '"';
68707
68708               if (title) {
68709                 out += ' title="' + title + '"';
68710               }
68711
68712               out += this.options.xhtml ? '/>' : '>';
68713               return out;
68714             }
68715           }, {
68716             key: "text",
68717             value: function text(_text) {
68718               return _text;
68719             }
68720           }]);
68721
68722           return Renderer;
68723         }();
68724
68725         var TextRenderer_1 = /*#__PURE__*/function () {
68726           function TextRenderer() {
68727             _classCallCheck$1(this, TextRenderer);
68728           }
68729
68730           _createClass$1(TextRenderer, [{
68731             key: "strong",
68732             value: // no need for block level renderers
68733             function strong(text) {
68734               return text;
68735             }
68736           }, {
68737             key: "em",
68738             value: function em(text) {
68739               return text;
68740             }
68741           }, {
68742             key: "codespan",
68743             value: function codespan(text) {
68744               return text;
68745             }
68746           }, {
68747             key: "del",
68748             value: function del(text) {
68749               return text;
68750             }
68751           }, {
68752             key: "html",
68753             value: function html(text) {
68754               return text;
68755             }
68756           }, {
68757             key: "text",
68758             value: function text(_text) {
68759               return _text;
68760             }
68761           }, {
68762             key: "link",
68763             value: function link(href, title, text) {
68764               return '' + text;
68765             }
68766           }, {
68767             key: "image",
68768             value: function image(href, title, text) {
68769               return '' + text;
68770             }
68771           }, {
68772             key: "br",
68773             value: function br() {
68774               return '';
68775             }
68776           }]);
68777
68778           return TextRenderer;
68779         }();
68780
68781         var Slugger_1 = /*#__PURE__*/function () {
68782           function Slugger() {
68783             _classCallCheck$1(this, Slugger);
68784
68785             this.seen = {};
68786           }
68787
68788           _createClass$1(Slugger, [{
68789             key: "serialize",
68790             value: function serialize(value) {
68791               return value.toLowerCase().trim() // remove html tags
68792               .replace(/<[!\/a-z].*?>/ig, '') // remove unwanted chars
68793               .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '').replace(/\s/g, '-');
68794             }
68795             /**
68796              * Finds the next safe (unique) slug to use
68797              */
68798
68799           }, {
68800             key: "getNextSafeSlug",
68801             value: function getNextSafeSlug(originalSlug, isDryRun) {
68802               var slug = originalSlug;
68803               var occurenceAccumulator = 0;
68804
68805               if (this.seen.hasOwnProperty(slug)) {
68806                 occurenceAccumulator = this.seen[originalSlug];
68807
68808                 do {
68809                   occurenceAccumulator++;
68810                   slug = originalSlug + '-' + occurenceAccumulator;
68811                 } while (this.seen.hasOwnProperty(slug));
68812               }
68813
68814               if (!isDryRun) {
68815                 this.seen[originalSlug] = occurenceAccumulator;
68816                 this.seen[slug] = 0;
68817               }
68818
68819               return slug;
68820             }
68821             /**
68822              * Convert string to unique id
68823              * @param {object} options
68824              * @param {boolean} options.dryrun Generates the next unique slug without updating the internal accumulator.
68825              */
68826
68827           }, {
68828             key: "slug",
68829             value: function slug(value) {
68830               var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
68831               var slug = this.serialize(value);
68832               return this.getNextSafeSlug(slug, options.dryrun);
68833             }
68834           }]);
68835
68836           return Slugger;
68837         }();
68838
68839         var Renderer$1 = Renderer_1;
68840         var TextRenderer$1 = TextRenderer_1;
68841         var Slugger$1 = Slugger_1;
68842         var defaults$1 = defaults$5.exports.defaults;
68843         var unescape$1 = helpers.unescape;
68844         /**
68845          * Parsing & Compiling
68846          */
68847
68848         var Parser_1 = /*#__PURE__*/function () {
68849           function Parser(options) {
68850             _classCallCheck$1(this, Parser);
68851
68852             this.options = options || defaults$1;
68853             this.options.renderer = this.options.renderer || new Renderer$1();
68854             this.renderer = this.options.renderer;
68855             this.renderer.options = this.options;
68856             this.textRenderer = new TextRenderer$1();
68857             this.slugger = new Slugger$1();
68858           }
68859           /**
68860            * Static Parse Method
68861            */
68862
68863
68864           _createClass$1(Parser, [{
68865             key: "parse",
68866             value:
68867             /**
68868              * Parse Loop
68869              */
68870             function parse(tokens) {
68871               var top = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
68872               var out = '',
68873                   i,
68874                   j,
68875                   k,
68876                   l2,
68877                   l3,
68878                   row,
68879                   cell,
68880                   header,
68881                   body,
68882                   token,
68883                   ordered,
68884                   start,
68885                   loose,
68886                   itemBody,
68887                   item,
68888                   checked,
68889                   task,
68890                   checkbox;
68891               var l = tokens.length;
68892
68893               for (i = 0; i < l; i++) {
68894                 token = tokens[i];
68895
68896                 switch (token.type) {
68897                   case 'space':
68898                     {
68899                       continue;
68900                     }
68901
68902                   case 'hr':
68903                     {
68904                       out += this.renderer.hr();
68905                       continue;
68906                     }
68907
68908                   case 'heading':
68909                     {
68910                       out += this.renderer.heading(this.parseInline(token.tokens), token.depth, unescape$1(this.parseInline(token.tokens, this.textRenderer)), this.slugger);
68911                       continue;
68912                     }
68913
68914                   case 'code':
68915                     {
68916                       out += this.renderer.code(token.text, token.lang, token.escaped);
68917                       continue;
68918                     }
68919
68920                   case 'table':
68921                     {
68922                       header = ''; // header
68923
68924                       cell = '';
68925                       l2 = token.header.length;
68926
68927                       for (j = 0; j < l2; j++) {
68928                         cell += this.renderer.tablecell(this.parseInline(token.tokens.header[j]), {
68929                           header: true,
68930                           align: token.align[j]
68931                         });
68932                       }
68933
68934                       header += this.renderer.tablerow(cell);
68935                       body = '';
68936                       l2 = token.cells.length;
68937
68938                       for (j = 0; j < l2; j++) {
68939                         row = token.tokens.cells[j];
68940                         cell = '';
68941                         l3 = row.length;
68942
68943                         for (k = 0; k < l3; k++) {
68944                           cell += this.renderer.tablecell(this.parseInline(row[k]), {
68945                             header: false,
68946                             align: token.align[k]
68947                           });
68948                         }
68949
68950                         body += this.renderer.tablerow(cell);
68951                       }
68952
68953                       out += this.renderer.table(header, body);
68954                       continue;
68955                     }
68956
68957                   case 'blockquote':
68958                     {
68959                       body = this.parse(token.tokens);
68960                       out += this.renderer.blockquote(body);
68961                       continue;
68962                     }
68963
68964                   case 'list':
68965                     {
68966                       ordered = token.ordered;
68967                       start = token.start;
68968                       loose = token.loose;
68969                       l2 = token.items.length;
68970                       body = '';
68971
68972                       for (j = 0; j < l2; j++) {
68973                         item = token.items[j];
68974                         checked = item.checked;
68975                         task = item.task;
68976                         itemBody = '';
68977
68978                         if (item.task) {
68979                           checkbox = this.renderer.checkbox(checked);
68980
68981                           if (loose) {
68982                             if (item.tokens.length > 0 && item.tokens[0].type === 'text') {
68983                               item.tokens[0].text = checkbox + ' ' + item.tokens[0].text;
68984
68985                               if (item.tokens[0].tokens && item.tokens[0].tokens.length > 0 && item.tokens[0].tokens[0].type === 'text') {
68986                                 item.tokens[0].tokens[0].text = checkbox + ' ' + item.tokens[0].tokens[0].text;
68987                               }
68988                             } else {
68989                               item.tokens.unshift({
68990                                 type: 'text',
68991                                 text: checkbox
68992                               });
68993                             }
68994                           } else {
68995                             itemBody += checkbox;
68996                           }
68997                         }
68998
68999                         itemBody += this.parse(item.tokens, loose);
69000                         body += this.renderer.listitem(itemBody, task, checked);
69001                       }
69002
69003                       out += this.renderer.list(body, ordered, start);
69004                       continue;
69005                     }
69006
69007                   case 'html':
69008                     {
69009                       // TODO parse inline content if parameter markdown=1
69010                       out += this.renderer.html(token.text);
69011                       continue;
69012                     }
69013
69014                   case 'paragraph':
69015                     {
69016                       out += this.renderer.paragraph(this.parseInline(token.tokens));
69017                       continue;
69018                     }
69019
69020                   case 'text':
69021                     {
69022                       body = token.tokens ? this.parseInline(token.tokens) : token.text;
69023
69024                       while (i + 1 < l && tokens[i + 1].type === 'text') {
69025                         token = tokens[++i];
69026                         body += '\n' + (token.tokens ? this.parseInline(token.tokens) : token.text);
69027                       }
69028
69029                       out += top ? this.renderer.paragraph(body) : body;
69030                       continue;
69031                     }
69032
69033                   default:
69034                     {
69035                       var errMsg = 'Token with "' + token.type + '" type was not found.';
69036
69037                       if (this.options.silent) {
69038                         console.error(errMsg);
69039                         return;
69040                       } else {
69041                         throw new Error(errMsg);
69042                       }
69043                     }
69044                 }
69045               }
69046
69047               return out;
69048             }
69049             /**
69050              * Parse Inline Tokens
69051              */
69052
69053           }, {
69054             key: "parseInline",
69055             value: function parseInline(tokens, renderer) {
69056               renderer = renderer || this.renderer;
69057               var out = '',
69058                   i,
69059                   token;
69060               var l = tokens.length;
69061
69062               for (i = 0; i < l; i++) {
69063                 token = tokens[i];
69064
69065                 switch (token.type) {
69066                   case 'escape':
69067                     {
69068                       out += renderer.text(token.text);
69069                       break;
69070                     }
69071
69072                   case 'html':
69073                     {
69074                       out += renderer.html(token.text);
69075                       break;
69076                     }
69077
69078                   case 'link':
69079                     {
69080                       out += renderer.link(token.href, token.title, this.parseInline(token.tokens, renderer));
69081                       break;
69082                     }
69083
69084                   case 'image':
69085                     {
69086                       out += renderer.image(token.href, token.title, token.text);
69087                       break;
69088                     }
69089
69090                   case 'strong':
69091                     {
69092                       out += renderer.strong(this.parseInline(token.tokens, renderer));
69093                       break;
69094                     }
69095
69096                   case 'em':
69097                     {
69098                       out += renderer.em(this.parseInline(token.tokens, renderer));
69099                       break;
69100                     }
69101
69102                   case 'codespan':
69103                     {
69104                       out += renderer.codespan(token.text);
69105                       break;
69106                     }
69107
69108                   case 'br':
69109                     {
69110                       out += renderer.br();
69111                       break;
69112                     }
69113
69114                   case 'del':
69115                     {
69116                       out += renderer.del(this.parseInline(token.tokens, renderer));
69117                       break;
69118                     }
69119
69120                   case 'text':
69121                     {
69122                       out += renderer.text(token.text);
69123                       break;
69124                     }
69125
69126                   default:
69127                     {
69128                       var errMsg = 'Token with "' + token.type + '" type was not found.';
69129
69130                       if (this.options.silent) {
69131                         console.error(errMsg);
69132                         return;
69133                       } else {
69134                         throw new Error(errMsg);
69135                       }
69136                     }
69137                 }
69138               }
69139
69140               return out;
69141             }
69142           }], [{
69143             key: "parse",
69144             value: function parse(tokens, options) {
69145               var parser = new Parser(options);
69146               return parser.parse(tokens);
69147             }
69148             /**
69149              * Static Parse Inline Method
69150              */
69151
69152           }, {
69153             key: "parseInline",
69154             value: function parseInline(tokens, options) {
69155               var parser = new Parser(options);
69156               return parser.parseInline(tokens);
69157             }
69158           }]);
69159
69160           return Parser;
69161         }();
69162
69163         var Lexer = Lexer_1;
69164         var Parser = Parser_1;
69165         var Tokenizer = Tokenizer_1;
69166         var Renderer = Renderer_1;
69167         var TextRenderer = TextRenderer_1;
69168         var Slugger = Slugger_1;
69169         var merge = helpers.merge,
69170             checkSanitizeDeprecation = helpers.checkSanitizeDeprecation,
69171             escape$1 = helpers.escape;
69172         var getDefaults = defaults$5.exports.getDefaults,
69173             changeDefaults = defaults$5.exports.changeDefaults,
69174             defaults = defaults$5.exports.defaults;
69175         /**
69176          * Marked
69177          */
69178
69179         function marked(src, opt, callback) {
69180           // throw error in case of non string input
69181           if (typeof src === 'undefined' || src === null) {
69182             throw new Error('marked(): input parameter is undefined or null');
69183           }
69184
69185           if (typeof src !== 'string') {
69186             throw new Error('marked(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected');
69187           }
69188
69189           if (typeof opt === 'function') {
69190             callback = opt;
69191             opt = null;
69192           }
69193
69194           opt = merge({}, marked.defaults, opt || {});
69195           checkSanitizeDeprecation(opt);
69196
69197           if (callback) {
69198             var highlight = opt.highlight;
69199             var tokens;
69200
69201             try {
69202               tokens = Lexer.lex(src, opt);
69203             } catch (e) {
69204               return callback(e);
69205             }
69206
69207             var done = function done(err) {
69208               var out;
69209
69210               if (!err) {
69211                 try {
69212                   if (opt.walkTokens) {
69213                     marked.walkTokens(tokens, opt.walkTokens);
69214                   }
69215
69216                   out = Parser.parse(tokens, opt);
69217                 } catch (e) {
69218                   err = e;
69219                 }
69220               }
69221
69222               opt.highlight = highlight;
69223               return err ? callback(err) : callback(null, out);
69224             };
69225
69226             if (!highlight || highlight.length < 3) {
69227               return done();
69228             }
69229
69230             delete opt.highlight;
69231             if (!tokens.length) return done();
69232             var pending = 0;
69233             marked.walkTokens(tokens, function (token) {
69234               if (token.type === 'code') {
69235                 pending++;
69236                 setTimeout(function () {
69237                   highlight(token.text, token.lang, function (err, code) {
69238                     if (err) {
69239                       return done(err);
69240                     }
69241
69242                     if (code != null && code !== token.text) {
69243                       token.text = code;
69244                       token.escaped = true;
69245                     }
69246
69247                     pending--;
69248
69249                     if (pending === 0) {
69250                       done();
69251                     }
69252                   });
69253                 }, 0);
69254               }
69255             });
69256
69257             if (pending === 0) {
69258               done();
69259             }
69260
69261             return;
69262           }
69263
69264           try {
69265             var _tokens = Lexer.lex(src, opt);
69266
69267             if (opt.walkTokens) {
69268               marked.walkTokens(_tokens, opt.walkTokens);
69269             }
69270
69271             return Parser.parse(_tokens, opt);
69272           } catch (e) {
69273             e.message += '\nPlease report this to https://github.com/markedjs/marked.';
69274
69275             if (opt.silent) {
69276               return '<p>An error occurred:</p><pre>' + escape$1(e.message + '', true) + '</pre>';
69277             }
69278
69279             throw e;
69280           }
69281         }
69282         /**
69283          * Options
69284          */
69285
69286
69287         marked.options = marked.setOptions = function (opt) {
69288           merge(marked.defaults, opt);
69289           changeDefaults(marked.defaults);
69290           return marked;
69291         };
69292
69293         marked.getDefaults = getDefaults;
69294         marked.defaults = defaults;
69295         /**
69296          * Use Extension
69297          */
69298
69299         marked.use = function (extension) {
69300           var opts = merge({}, extension);
69301
69302           if (extension.renderer) {
69303             (function () {
69304               var renderer = marked.defaults.renderer || new Renderer();
69305
69306               var _loop = function _loop(prop) {
69307                 var prevRenderer = renderer[prop];
69308
69309                 renderer[prop] = function () {
69310                   for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
69311                     args[_key] = arguments[_key];
69312                   }
69313
69314                   var ret = extension.renderer[prop].apply(renderer, args);
69315
69316                   if (ret === false) {
69317                     ret = prevRenderer.apply(renderer, args);
69318                   }
69319
69320                   return ret;
69321                 };
69322               };
69323
69324               for (var prop in extension.renderer) {
69325                 _loop(prop);
69326               }
69327
69328               opts.renderer = renderer;
69329             })();
69330           }
69331
69332           if (extension.tokenizer) {
69333             (function () {
69334               var tokenizer = marked.defaults.tokenizer || new Tokenizer();
69335
69336               var _loop2 = function _loop2(prop) {
69337                 var prevTokenizer = tokenizer[prop];
69338
69339                 tokenizer[prop] = function () {
69340                   for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
69341                     args[_key2] = arguments[_key2];
69342                   }
69343
69344                   var ret = extension.tokenizer[prop].apply(tokenizer, args);
69345
69346                   if (ret === false) {
69347                     ret = prevTokenizer.apply(tokenizer, args);
69348                   }
69349
69350                   return ret;
69351                 };
69352               };
69353
69354               for (var prop in extension.tokenizer) {
69355                 _loop2(prop);
69356               }
69357
69358               opts.tokenizer = tokenizer;
69359             })();
69360           }
69361
69362           if (extension.walkTokens) {
69363             var walkTokens = marked.defaults.walkTokens;
69364
69365             opts.walkTokens = function (token) {
69366               extension.walkTokens(token);
69367
69368               if (walkTokens) {
69369                 walkTokens(token);
69370               }
69371             };
69372           }
69373
69374           marked.setOptions(opts);
69375         };
69376         /**
69377          * Run callback for every token
69378          */
69379
69380
69381         marked.walkTokens = function (tokens, callback) {
69382           var _iterator = _createForOfIteratorHelper(tokens),
69383               _step;
69384
69385           try {
69386             for (_iterator.s(); !(_step = _iterator.n()).done;) {
69387               var token = _step.value;
69388               callback(token);
69389
69390               switch (token.type) {
69391                 case 'table':
69392                   {
69393                     var _iterator2 = _createForOfIteratorHelper(token.tokens.header),
69394                         _step2;
69395
69396                     try {
69397                       for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
69398                         var cell = _step2.value;
69399                         marked.walkTokens(cell, callback);
69400                       }
69401                     } catch (err) {
69402                       _iterator2.e(err);
69403                     } finally {
69404                       _iterator2.f();
69405                     }
69406
69407                     var _iterator3 = _createForOfIteratorHelper(token.tokens.cells),
69408                         _step3;
69409
69410                     try {
69411                       for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
69412                         var row = _step3.value;
69413
69414                         var _iterator4 = _createForOfIteratorHelper(row),
69415                             _step4;
69416
69417                         try {
69418                           for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
69419                             var _cell = _step4.value;
69420                             marked.walkTokens(_cell, callback);
69421                           }
69422                         } catch (err) {
69423                           _iterator4.e(err);
69424                         } finally {
69425                           _iterator4.f();
69426                         }
69427                       }
69428                     } catch (err) {
69429                       _iterator3.e(err);
69430                     } finally {
69431                       _iterator3.f();
69432                     }
69433
69434                     break;
69435                   }
69436
69437                 case 'list':
69438                   {
69439                     marked.walkTokens(token.items, callback);
69440                     break;
69441                   }
69442
69443                 default:
69444                   {
69445                     if (token.tokens) {
69446                       marked.walkTokens(token.tokens, callback);
69447                     }
69448                   }
69449               }
69450             }
69451           } catch (err) {
69452             _iterator.e(err);
69453           } finally {
69454             _iterator.f();
69455           }
69456         };
69457         /**
69458          * Parse Inline
69459          */
69460
69461
69462         marked.parseInline = function (src, opt) {
69463           // throw error in case of non string input
69464           if (typeof src === 'undefined' || src === null) {
69465             throw new Error('marked.parseInline(): input parameter is undefined or null');
69466           }
69467
69468           if (typeof src !== 'string') {
69469             throw new Error('marked.parseInline(): input parameter is of type ' + Object.prototype.toString.call(src) + ', string expected');
69470           }
69471
69472           opt = merge({}, marked.defaults, opt || {});
69473           checkSanitizeDeprecation(opt);
69474
69475           try {
69476             var tokens = Lexer.lexInline(src, opt);
69477
69478             if (opt.walkTokens) {
69479               marked.walkTokens(tokens, opt.walkTokens);
69480             }
69481
69482             return Parser.parseInline(tokens, opt);
69483           } catch (e) {
69484             e.message += '\nPlease report this to https://github.com/markedjs/marked.';
69485
69486             if (opt.silent) {
69487               return '<p>An error occurred:</p><pre>' + escape$1(e.message + '', true) + '</pre>';
69488             }
69489
69490             throw e;
69491           }
69492         };
69493         /**
69494          * Expose
69495          */
69496
69497
69498         marked.Parser = Parser;
69499         marked.parser = Parser.parse;
69500         marked.Renderer = Renderer;
69501         marked.TextRenderer = TextRenderer;
69502         marked.Lexer = Lexer;
69503         marked.lexer = Lexer.lex;
69504         marked.Tokenizer = Tokenizer;
69505         marked.Slugger = Slugger;
69506         marked.parse = marked;
69507         var marked_1 = marked;
69508
69509         var tiler$4 = utilTiler();
69510         var dispatch$5 = dispatch$8('loaded');
69511         var _tileZoom$1 = 14;
69512         var _osmoseUrlRoot = 'https://osmose.openstreetmap.fr/api/0.3';
69513         var _osmoseData = {
69514           icons: {},
69515           items: []
69516         }; // This gets reassigned if reset
69517
69518         var _cache;
69519
69520         function abortRequest$4(controller) {
69521           if (controller) {
69522             controller.abort();
69523           }
69524         }
69525
69526         function abortUnwantedRequests$1(cache, tiles) {
69527           Object.keys(cache.inflightTile).forEach(function (k) {
69528             var wanted = tiles.find(function (tile) {
69529               return k === tile.id;
69530             });
69531
69532             if (!wanted) {
69533               abortRequest$4(cache.inflightTile[k]);
69534               delete cache.inflightTile[k];
69535             }
69536           });
69537         }
69538
69539         function encodeIssueRtree(d) {
69540           return {
69541             minX: d.loc[0],
69542             minY: d.loc[1],
69543             maxX: d.loc[0],
69544             maxY: d.loc[1],
69545             data: d
69546           };
69547         } // Replace or remove QAItem from rtree
69548
69549
69550         function updateRtree$1(item, replace) {
69551           _cache.rtree.remove(item, function (a, b) {
69552             return a.data.id === b.data.id;
69553           });
69554
69555           if (replace) {
69556             _cache.rtree.insert(item);
69557           }
69558         } // Issues shouldn't obscure each other
69559
69560
69561         function preventCoincident(loc) {
69562           var coincident = false;
69563
69564           do {
69565             // first time, move marker up. after that, move marker right.
69566             var delta = coincident ? [0.00001, 0] : [0, 0.00001];
69567             loc = geoVecAdd(loc, delta);
69568             var bbox = geoExtent(loc).bbox();
69569             coincident = _cache.rtree.search(bbox).length;
69570           } while (coincident);
69571
69572           return loc;
69573         }
69574
69575         var serviceOsmose = {
69576           title: 'osmose',
69577           init: function init() {
69578             _mainFileFetcher.get('qa_data').then(function (d) {
69579               _osmoseData = d.osmose;
69580               _osmoseData.items = Object.keys(d.osmose.icons).map(function (s) {
69581                 return s.split('-')[0];
69582               }).reduce(function (unique, item) {
69583                 return unique.indexOf(item) !== -1 ? unique : [].concat(_toConsumableArray(unique), [item]);
69584               }, []);
69585             });
69586
69587             if (!_cache) {
69588               this.reset();
69589             }
69590
69591             this.event = utilRebind(this, dispatch$5, 'on');
69592           },
69593           reset: function reset() {
69594             var _strings = {};
69595             var _colors = {};
69596
69597             if (_cache) {
69598               Object.values(_cache.inflightTile).forEach(abortRequest$4); // Strings and colors are static and should not be re-populated
69599
69600               _strings = _cache.strings;
69601               _colors = _cache.colors;
69602             }
69603
69604             _cache = {
69605               data: {},
69606               loadedTile: {},
69607               inflightTile: {},
69608               inflightPost: {},
69609               closed: {},
69610               rtree: new RBush(),
69611               strings: _strings,
69612               colors: _colors
69613             };
69614           },
69615           loadIssues: function loadIssues(projection) {
69616             var _this = this;
69617
69618             var params = {
69619               // Tiles return a maximum # of issues
69620               // So we want to filter our request for only types iD supports
69621               item: _osmoseData.items
69622             }; // determine the needed tiles to cover the view
69623
69624             var tiles = tiler$4.zoomExtent([_tileZoom$1, _tileZoom$1]).getTiles(projection); // abort inflight requests that are no longer needed
69625
69626             abortUnwantedRequests$1(_cache, tiles); // issue new requests..
69627
69628             tiles.forEach(function (tile) {
69629               if (_cache.loadedTile[tile.id] || _cache.inflightTile[tile.id]) return;
69630
69631               var _tile$xyz = _slicedToArray(tile.xyz, 3),
69632                   x = _tile$xyz[0],
69633                   y = _tile$xyz[1],
69634                   z = _tile$xyz[2];
69635
69636               var url = "".concat(_osmoseUrlRoot, "/issues/").concat(z, "/").concat(x, "/").concat(y, ".json?") + utilQsString(params);
69637               var controller = new AbortController();
69638               _cache.inflightTile[tile.id] = controller;
69639               d3_json(url, {
69640                 signal: controller.signal
69641               }).then(function (data) {
69642                 delete _cache.inflightTile[tile.id];
69643                 _cache.loadedTile[tile.id] = true;
69644
69645                 if (data.features) {
69646                   data.features.forEach(function (issue) {
69647                     var _issue$properties = issue.properties,
69648                         item = _issue$properties.item,
69649                         cl = _issue$properties["class"],
69650                         id = _issue$properties.uuid;
69651                     /* Osmose issues are uniquely identified by a unique
69652                       `item` and `class` combination (both integer values) */
69653
69654                     var itemType = "".concat(item, "-").concat(cl); // Filter out unsupported issue types (some are too specific or advanced)
69655
69656                     if (itemType in _osmoseData.icons) {
69657                       var loc = issue.geometry.coordinates; // lon, lat
69658
69659                       loc = preventCoincident(loc);
69660                       var d = new QAItem(loc, _this, itemType, id, {
69661                         item: item
69662                       }); // Setting elems here prevents UI detail requests
69663
69664                       if (item === 8300 || item === 8360) {
69665                         d.elems = [];
69666                       }
69667
69668                       _cache.data[d.id] = d;
69669
69670                       _cache.rtree.insert(encodeIssueRtree(d));
69671                     }
69672                   });
69673                 }
69674
69675                 dispatch$5.call('loaded');
69676               })["catch"](function () {
69677                 delete _cache.inflightTile[tile.id];
69678                 _cache.loadedTile[tile.id] = true;
69679               });
69680             });
69681           },
69682           loadIssueDetail: function loadIssueDetail(issue) {
69683             var _this2 = this;
69684
69685             // Issue details only need to be fetched once
69686             if (issue.elems !== undefined) {
69687               return Promise.resolve(issue);
69688             }
69689
69690             var url = "".concat(_osmoseUrlRoot, "/issue/").concat(issue.id, "?langs=").concat(_mainLocalizer.localeCode());
69691
69692             var cacheDetails = function cacheDetails(data) {
69693               // Associated elements used for highlighting
69694               // Assign directly for immediate use in the callback
69695               issue.elems = data.elems.map(function (e) {
69696                 return e.type.substring(0, 1) + e.id;
69697               }); // Some issues have instance specific detail in a subtitle
69698
69699               issue.detail = data.subtitle ? marked_1(data.subtitle.auto) : '';
69700
69701               _this2.replaceItem(issue);
69702             };
69703
69704             return d3_json(url).then(cacheDetails).then(function () {
69705               return issue;
69706             });
69707           },
69708           loadStrings: function loadStrings() {
69709             var locale = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _mainLocalizer.localeCode();
69710             var items = Object.keys(_osmoseData.icons);
69711
69712             if (locale in _cache.strings && Object.keys(_cache.strings[locale]).length === items.length) {
69713               return Promise.resolve(_cache.strings[locale]);
69714             } // May be partially populated already if some requests were successful
69715
69716
69717             if (!(locale in _cache.strings)) {
69718               _cache.strings[locale] = {};
69719             } // Only need to cache strings for supported issue types
69720             // Using multiple individual item + class requests to reduce fetched data size
69721
69722
69723             var allRequests = items.map(function (itemType) {
69724               // No need to request data we already have
69725               if (itemType in _cache.strings[locale]) return null;
69726
69727               var cacheData = function cacheData(data) {
69728                 // Bunch of nested single value arrays of objects
69729                 var _data$categories = _slicedToArray(data.categories, 1),
69730                     _data$categories$ = _data$categories[0],
69731                     cat = _data$categories$ === void 0 ? {
69732                   items: []
69733                 } : _data$categories$;
69734
69735                 var _cat$items = _slicedToArray(cat.items, 1),
69736                     _cat$items$ = _cat$items[0],
69737                     item = _cat$items$ === void 0 ? {
69738                   "class": []
69739                 } : _cat$items$;
69740
69741                 var _item$class = _slicedToArray(item["class"], 1),
69742                     _item$class$ = _item$class[0],
69743                     cl = _item$class$ === void 0 ? null : _item$class$; // If null default value is reached, data wasn't as expected (or was empty)
69744
69745
69746                 if (!cl) {
69747                   /* eslint-disable no-console */
69748                   console.log("Osmose strings request (".concat(itemType, ") had unexpected data"));
69749                   /* eslint-enable no-console */
69750
69751                   return;
69752                 } // Cache served item colors to automatically style issue markers later
69753
69754
69755                 var itemInt = item.item,
69756                     color = item.color;
69757
69758                 if (/^#[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}/.test(color)) {
69759                   _cache.colors[itemInt] = color;
69760                 } // Value of root key will be null if no string exists
69761                 // If string exists, value is an object with key 'auto' for string
69762
69763
69764                 var title = cl.title,
69765                     detail = cl.detail,
69766                     fix = cl.fix,
69767                     trap = cl.trap; // Osmose titles shouldn't contain markdown
69768
69769                 var issueStrings = {};
69770                 if (title) issueStrings.title = title.auto;
69771                 if (detail) issueStrings.detail = marked_1(detail.auto);
69772                 if (trap) issueStrings.trap = marked_1(trap.auto);
69773                 if (fix) issueStrings.fix = marked_1(fix.auto);
69774                 _cache.strings[locale][itemType] = issueStrings;
69775               };
69776
69777               var _itemType$split = itemType.split('-'),
69778                   _itemType$split2 = _slicedToArray(_itemType$split, 2),
69779                   item = _itemType$split2[0],
69780                   cl = _itemType$split2[1]; // Osmose API falls back to English strings where untranslated or if locale doesn't exist
69781
69782
69783               var url = "".concat(_osmoseUrlRoot, "/items/").concat(item, "/class/").concat(cl, "?langs=").concat(locale);
69784               return d3_json(url).then(cacheData);
69785             }).filter(Boolean);
69786             return Promise.all(allRequests).then(function () {
69787               return _cache.strings[locale];
69788             });
69789           },
69790           getStrings: function getStrings(itemType) {
69791             var locale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _mainLocalizer.localeCode();
69792             // No need to fallback to English, Osmose API handles this for us
69793             return locale in _cache.strings ? _cache.strings[locale][itemType] : {};
69794           },
69795           getColor: function getColor(itemType) {
69796             return itemType in _cache.colors ? _cache.colors[itemType] : '#FFFFFF';
69797           },
69798           postUpdate: function postUpdate(issue, callback) {
69799             var _this3 = this;
69800
69801             if (_cache.inflightPost[issue.id]) {
69802               return callback({
69803                 message: 'Issue update already inflight',
69804                 status: -2
69805               }, issue);
69806             } // UI sets the status to either 'done' or 'false'
69807
69808
69809             var url = "".concat(_osmoseUrlRoot, "/issue/").concat(issue.id, "/").concat(issue.newStatus);
69810             var controller = new AbortController();
69811
69812             var after = function after() {
69813               delete _cache.inflightPost[issue.id];
69814
69815               _this3.removeItem(issue);
69816
69817               if (issue.newStatus === 'done') {
69818                 // Keep track of the number of issues closed per `item` to tag the changeset
69819                 if (!(issue.item in _cache.closed)) {
69820                   _cache.closed[issue.item] = 0;
69821                 }
69822
69823                 _cache.closed[issue.item] += 1;
69824               }
69825
69826               if (callback) callback(null, issue);
69827             };
69828
69829             _cache.inflightPost[issue.id] = controller;
69830             fetch(url, {
69831               signal: controller.signal
69832             }).then(after)["catch"](function (err) {
69833               delete _cache.inflightPost[issue.id];
69834               if (callback) callback(err.message);
69835             });
69836           },
69837           // Get all cached QAItems covering the viewport
69838           getItems: function getItems(projection) {
69839             var viewport = projection.clipExtent();
69840             var min = [viewport[0][0], viewport[1][1]];
69841             var max = [viewport[1][0], viewport[0][1]];
69842             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
69843             return _cache.rtree.search(bbox).map(function (d) {
69844               return d.data;
69845             });
69846           },
69847           // Get a QAItem from cache
69848           // NOTE: Don't change method name until UI v3 is merged
69849           getError: function getError(id) {
69850             return _cache.data[id];
69851           },
69852           // get the name of the icon to display for this item
69853           getIcon: function getIcon(itemType) {
69854             return _osmoseData.icons[itemType];
69855           },
69856           // Replace a single QAItem in the cache
69857           replaceItem: function replaceItem(item) {
69858             if (!(item instanceof QAItem) || !item.id) return;
69859             _cache.data[item.id] = item;
69860             updateRtree$1(encodeIssueRtree(item), true); // true = replace
69861
69862             return item;
69863           },
69864           // Remove a single QAItem from the cache
69865           removeItem: function removeItem(item) {
69866             if (!(item instanceof QAItem) || !item.id) return;
69867             delete _cache.data[item.id];
69868             updateRtree$1(encodeIssueRtree(item), false); // false = remove
69869           },
69870           // Used to populate `closed:osmose:*` changeset tags
69871           getClosedCounts: function getClosedCounts() {
69872             return _cache.closed;
69873           },
69874           itemURL: function itemURL(item) {
69875             return "https://osmose.openstreetmap.fr/en/error/".concat(item.id);
69876           }
69877         };
69878
69879         var ieee754$1 = {};
69880
69881         /*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
69882
69883         ieee754$1.read = function (buffer, offset, isLE, mLen, nBytes) {
69884           var e, m;
69885           var eLen = nBytes * 8 - mLen - 1;
69886           var eMax = (1 << eLen) - 1;
69887           var eBias = eMax >> 1;
69888           var nBits = -7;
69889           var i = isLE ? nBytes - 1 : 0;
69890           var d = isLE ? -1 : 1;
69891           var s = buffer[offset + i];
69892           i += d;
69893           e = s & (1 << -nBits) - 1;
69894           s >>= -nBits;
69895           nBits += eLen;
69896
69897           for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
69898
69899           m = e & (1 << -nBits) - 1;
69900           e >>= -nBits;
69901           nBits += mLen;
69902
69903           for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
69904
69905           if (e === 0) {
69906             e = 1 - eBias;
69907           } else if (e === eMax) {
69908             return m ? NaN : (s ? -1 : 1) * Infinity;
69909           } else {
69910             m = m + Math.pow(2, mLen);
69911             e = e - eBias;
69912           }
69913
69914           return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
69915         };
69916
69917         ieee754$1.write = function (buffer, value, offset, isLE, mLen, nBytes) {
69918           var e, m, c;
69919           var eLen = nBytes * 8 - mLen - 1;
69920           var eMax = (1 << eLen) - 1;
69921           var eBias = eMax >> 1;
69922           var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0;
69923           var i = isLE ? 0 : nBytes - 1;
69924           var d = isLE ? 1 : -1;
69925           var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0;
69926           value = Math.abs(value);
69927
69928           if (isNaN(value) || value === Infinity) {
69929             m = isNaN(value) ? 1 : 0;
69930             e = eMax;
69931           } else {
69932             e = Math.floor(Math.log(value) / Math.LN2);
69933
69934             if (value * (c = Math.pow(2, -e)) < 1) {
69935               e--;
69936               c *= 2;
69937             }
69938
69939             if (e + eBias >= 1) {
69940               value += rt / c;
69941             } else {
69942               value += rt * Math.pow(2, 1 - eBias);
69943             }
69944
69945             if (value * c >= 2) {
69946               e++;
69947               c /= 2;
69948             }
69949
69950             if (e + eBias >= eMax) {
69951               m = 0;
69952               e = eMax;
69953             } else if (e + eBias >= 1) {
69954               m = (value * c - 1) * Math.pow(2, mLen);
69955               e = e + eBias;
69956             } else {
69957               m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
69958               e = 0;
69959             }
69960           }
69961
69962           for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
69963
69964           e = e << mLen | m;
69965           eLen += mLen;
69966
69967           for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
69968
69969           buffer[offset + i - d] |= s * 128;
69970         };
69971
69972         var pbf = Pbf;
69973         var ieee754 = ieee754$1;
69974
69975         function Pbf(buf) {
69976           this.buf = ArrayBuffer.isView && ArrayBuffer.isView(buf) ? buf : new Uint8Array(buf || 0);
69977           this.pos = 0;
69978           this.type = 0;
69979           this.length = this.buf.length;
69980         }
69981
69982         Pbf.Varint = 0; // varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum
69983
69984         Pbf.Fixed64 = 1; // 64-bit: double, fixed64, sfixed64
69985
69986         Pbf.Bytes = 2; // length-delimited: string, bytes, embedded messages, packed repeated fields
69987
69988         Pbf.Fixed32 = 5; // 32-bit: float, fixed32, sfixed32
69989
69990         var SHIFT_LEFT_32 = (1 << 16) * (1 << 16),
69991             SHIFT_RIGHT_32 = 1 / SHIFT_LEFT_32; // Threshold chosen based on both benchmarking and knowledge about browser string
69992         // data structures (which currently switch structure types at 12 bytes or more)
69993
69994         var TEXT_DECODER_MIN_LENGTH = 12;
69995         var utf8TextDecoder = typeof TextDecoder === 'undefined' ? null : new TextDecoder('utf8');
69996         Pbf.prototype = {
69997           destroy: function destroy() {
69998             this.buf = null;
69999           },
70000           // === READING =================================================================
70001           readFields: function readFields(readField, result, end) {
70002             end = end || this.length;
70003
70004             while (this.pos < end) {
70005               var val = this.readVarint(),
70006                   tag = val >> 3,
70007                   startPos = this.pos;
70008               this.type = val & 0x7;
70009               readField(tag, result, this);
70010               if (this.pos === startPos) this.skip(val);
70011             }
70012
70013             return result;
70014           },
70015           readMessage: function readMessage(readField, result) {
70016             return this.readFields(readField, result, this.readVarint() + this.pos);
70017           },
70018           readFixed32: function readFixed32() {
70019             var val = readUInt32(this.buf, this.pos);
70020             this.pos += 4;
70021             return val;
70022           },
70023           readSFixed32: function readSFixed32() {
70024             var val = readInt32(this.buf, this.pos);
70025             this.pos += 4;
70026             return val;
70027           },
70028           // 64-bit int handling is based on github.com/dpw/node-buffer-more-ints (MIT-licensed)
70029           readFixed64: function readFixed64() {
70030             var val = readUInt32(this.buf, this.pos) + readUInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
70031             this.pos += 8;
70032             return val;
70033           },
70034           readSFixed64: function readSFixed64() {
70035             var val = readUInt32(this.buf, this.pos) + readInt32(this.buf, this.pos + 4) * SHIFT_LEFT_32;
70036             this.pos += 8;
70037             return val;
70038           },
70039           readFloat: function readFloat() {
70040             var val = ieee754.read(this.buf, this.pos, true, 23, 4);
70041             this.pos += 4;
70042             return val;
70043           },
70044           readDouble: function readDouble() {
70045             var val = ieee754.read(this.buf, this.pos, true, 52, 8);
70046             this.pos += 8;
70047             return val;
70048           },
70049           readVarint: function readVarint(isSigned) {
70050             var buf = this.buf,
70051                 val,
70052                 b;
70053             b = buf[this.pos++];
70054             val = b & 0x7f;
70055             if (b < 0x80) return val;
70056             b = buf[this.pos++];
70057             val |= (b & 0x7f) << 7;
70058             if (b < 0x80) return val;
70059             b = buf[this.pos++];
70060             val |= (b & 0x7f) << 14;
70061             if (b < 0x80) return val;
70062             b = buf[this.pos++];
70063             val |= (b & 0x7f) << 21;
70064             if (b < 0x80) return val;
70065             b = buf[this.pos];
70066             val |= (b & 0x0f) << 28;
70067             return readVarintRemainder(val, isSigned, this);
70068           },
70069           readVarint64: function readVarint64() {
70070             // for compatibility with v2.0.1
70071             return this.readVarint(true);
70072           },
70073           readSVarint: function readSVarint() {
70074             var num = this.readVarint();
70075             return num % 2 === 1 ? (num + 1) / -2 : num / 2; // zigzag encoding
70076           },
70077           readBoolean: function readBoolean() {
70078             return Boolean(this.readVarint());
70079           },
70080           readString: function readString() {
70081             var end = this.readVarint() + this.pos;
70082             var pos = this.pos;
70083             this.pos = end;
70084
70085             if (end - pos >= TEXT_DECODER_MIN_LENGTH && utf8TextDecoder) {
70086               // longer strings are fast with the built-in browser TextDecoder API
70087               return readUtf8TextDecoder(this.buf, pos, end);
70088             } // short strings are fast with our custom implementation
70089
70090
70091             return readUtf8(this.buf, pos, end);
70092           },
70093           readBytes: function readBytes() {
70094             var end = this.readVarint() + this.pos,
70095                 buffer = this.buf.subarray(this.pos, end);
70096             this.pos = end;
70097             return buffer;
70098           },
70099           // verbose for performance reasons; doesn't affect gzipped size
70100           readPackedVarint: function readPackedVarint(arr, isSigned) {
70101             if (this.type !== Pbf.Bytes) return arr.push(this.readVarint(isSigned));
70102             var end = readPackedEnd(this);
70103             arr = arr || [];
70104
70105             while (this.pos < end) {
70106               arr.push(this.readVarint(isSigned));
70107             }
70108
70109             return arr;
70110           },
70111           readPackedSVarint: function readPackedSVarint(arr) {
70112             if (this.type !== Pbf.Bytes) return arr.push(this.readSVarint());
70113             var end = readPackedEnd(this);
70114             arr = arr || [];
70115
70116             while (this.pos < end) {
70117               arr.push(this.readSVarint());
70118             }
70119
70120             return arr;
70121           },
70122           readPackedBoolean: function readPackedBoolean(arr) {
70123             if (this.type !== Pbf.Bytes) return arr.push(this.readBoolean());
70124             var end = readPackedEnd(this);
70125             arr = arr || [];
70126
70127             while (this.pos < end) {
70128               arr.push(this.readBoolean());
70129             }
70130
70131             return arr;
70132           },
70133           readPackedFloat: function readPackedFloat(arr) {
70134             if (this.type !== Pbf.Bytes) return arr.push(this.readFloat());
70135             var end = readPackedEnd(this);
70136             arr = arr || [];
70137
70138             while (this.pos < end) {
70139               arr.push(this.readFloat());
70140             }
70141
70142             return arr;
70143           },
70144           readPackedDouble: function readPackedDouble(arr) {
70145             if (this.type !== Pbf.Bytes) return arr.push(this.readDouble());
70146             var end = readPackedEnd(this);
70147             arr = arr || [];
70148
70149             while (this.pos < end) {
70150               arr.push(this.readDouble());
70151             }
70152
70153             return arr;
70154           },
70155           readPackedFixed32: function readPackedFixed32(arr) {
70156             if (this.type !== Pbf.Bytes) return arr.push(this.readFixed32());
70157             var end = readPackedEnd(this);
70158             arr = arr || [];
70159
70160             while (this.pos < end) {
70161               arr.push(this.readFixed32());
70162             }
70163
70164             return arr;
70165           },
70166           readPackedSFixed32: function readPackedSFixed32(arr) {
70167             if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed32());
70168             var end = readPackedEnd(this);
70169             arr = arr || [];
70170
70171             while (this.pos < end) {
70172               arr.push(this.readSFixed32());
70173             }
70174
70175             return arr;
70176           },
70177           readPackedFixed64: function readPackedFixed64(arr) {
70178             if (this.type !== Pbf.Bytes) return arr.push(this.readFixed64());
70179             var end = readPackedEnd(this);
70180             arr = arr || [];
70181
70182             while (this.pos < end) {
70183               arr.push(this.readFixed64());
70184             }
70185
70186             return arr;
70187           },
70188           readPackedSFixed64: function readPackedSFixed64(arr) {
70189             if (this.type !== Pbf.Bytes) return arr.push(this.readSFixed64());
70190             var end = readPackedEnd(this);
70191             arr = arr || [];
70192
70193             while (this.pos < end) {
70194               arr.push(this.readSFixed64());
70195             }
70196
70197             return arr;
70198           },
70199           skip: function skip(val) {
70200             var type = val & 0x7;
70201             if (type === Pbf.Varint) while (this.buf[this.pos++] > 0x7f) {} else if (type === Pbf.Bytes) this.pos = this.readVarint() + this.pos;else if (type === Pbf.Fixed32) this.pos += 4;else if (type === Pbf.Fixed64) this.pos += 8;else throw new Error('Unimplemented type: ' + type);
70202           },
70203           // === WRITING =================================================================
70204           writeTag: function writeTag(tag, type) {
70205             this.writeVarint(tag << 3 | type);
70206           },
70207           realloc: function realloc(min) {
70208             var length = this.length || 16;
70209
70210             while (length < this.pos + min) {
70211               length *= 2;
70212             }
70213
70214             if (length !== this.length) {
70215               var buf = new Uint8Array(length);
70216               buf.set(this.buf);
70217               this.buf = buf;
70218               this.length = length;
70219             }
70220           },
70221           finish: function finish() {
70222             this.length = this.pos;
70223             this.pos = 0;
70224             return this.buf.subarray(0, this.length);
70225           },
70226           writeFixed32: function writeFixed32(val) {
70227             this.realloc(4);
70228             writeInt32(this.buf, val, this.pos);
70229             this.pos += 4;
70230           },
70231           writeSFixed32: function writeSFixed32(val) {
70232             this.realloc(4);
70233             writeInt32(this.buf, val, this.pos);
70234             this.pos += 4;
70235           },
70236           writeFixed64: function writeFixed64(val) {
70237             this.realloc(8);
70238             writeInt32(this.buf, val & -1, this.pos);
70239             writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
70240             this.pos += 8;
70241           },
70242           writeSFixed64: function writeSFixed64(val) {
70243             this.realloc(8);
70244             writeInt32(this.buf, val & -1, this.pos);
70245             writeInt32(this.buf, Math.floor(val * SHIFT_RIGHT_32), this.pos + 4);
70246             this.pos += 8;
70247           },
70248           writeVarint: function writeVarint(val) {
70249             val = +val || 0;
70250
70251             if (val > 0xfffffff || val < 0) {
70252               writeBigVarint(val, this);
70253               return;
70254             }
70255
70256             this.realloc(4);
70257             this.buf[this.pos++] = val & 0x7f | (val > 0x7f ? 0x80 : 0);
70258             if (val <= 0x7f) return;
70259             this.buf[this.pos++] = (val >>>= 7) & 0x7f | (val > 0x7f ? 0x80 : 0);
70260             if (val <= 0x7f) return;
70261             this.buf[this.pos++] = (val >>>= 7) & 0x7f | (val > 0x7f ? 0x80 : 0);
70262             if (val <= 0x7f) return;
70263             this.buf[this.pos++] = val >>> 7 & 0x7f;
70264           },
70265           writeSVarint: function writeSVarint(val) {
70266             this.writeVarint(val < 0 ? -val * 2 - 1 : val * 2);
70267           },
70268           writeBoolean: function writeBoolean(val) {
70269             this.writeVarint(Boolean(val));
70270           },
70271           writeString: function writeString(str) {
70272             str = String(str);
70273             this.realloc(str.length * 4);
70274             this.pos++; // reserve 1 byte for short string length
70275
70276             var startPos = this.pos; // write the string directly to the buffer and see how much was written
70277
70278             this.pos = writeUtf8(this.buf, str, this.pos);
70279             var len = this.pos - startPos;
70280             if (len >= 0x80) makeRoomForExtraLength(startPos, len, this); // finally, write the message length in the reserved place and restore the position
70281
70282             this.pos = startPos - 1;
70283             this.writeVarint(len);
70284             this.pos += len;
70285           },
70286           writeFloat: function writeFloat(val) {
70287             this.realloc(4);
70288             ieee754.write(this.buf, val, this.pos, true, 23, 4);
70289             this.pos += 4;
70290           },
70291           writeDouble: function writeDouble(val) {
70292             this.realloc(8);
70293             ieee754.write(this.buf, val, this.pos, true, 52, 8);
70294             this.pos += 8;
70295           },
70296           writeBytes: function writeBytes(buffer) {
70297             var len = buffer.length;
70298             this.writeVarint(len);
70299             this.realloc(len);
70300
70301             for (var i = 0; i < len; i++) {
70302               this.buf[this.pos++] = buffer[i];
70303             }
70304           },
70305           writeRawMessage: function writeRawMessage(fn, obj) {
70306             this.pos++; // reserve 1 byte for short message length
70307             // write the message directly to the buffer and see how much was written
70308
70309             var startPos = this.pos;
70310             fn(obj, this);
70311             var len = this.pos - startPos;
70312             if (len >= 0x80) makeRoomForExtraLength(startPos, len, this); // finally, write the message length in the reserved place and restore the position
70313
70314             this.pos = startPos - 1;
70315             this.writeVarint(len);
70316             this.pos += len;
70317           },
70318           writeMessage: function writeMessage(tag, fn, obj) {
70319             this.writeTag(tag, Pbf.Bytes);
70320             this.writeRawMessage(fn, obj);
70321           },
70322           writePackedVarint: function writePackedVarint(tag, arr) {
70323             if (arr.length) this.writeMessage(tag, _writePackedVarint, arr);
70324           },
70325           writePackedSVarint: function writePackedSVarint(tag, arr) {
70326             if (arr.length) this.writeMessage(tag, _writePackedSVarint, arr);
70327           },
70328           writePackedBoolean: function writePackedBoolean(tag, arr) {
70329             if (arr.length) this.writeMessage(tag, _writePackedBoolean, arr);
70330           },
70331           writePackedFloat: function writePackedFloat(tag, arr) {
70332             if (arr.length) this.writeMessage(tag, _writePackedFloat, arr);
70333           },
70334           writePackedDouble: function writePackedDouble(tag, arr) {
70335             if (arr.length) this.writeMessage(tag, _writePackedDouble, arr);
70336           },
70337           writePackedFixed32: function writePackedFixed32(tag, arr) {
70338             if (arr.length) this.writeMessage(tag, _writePackedFixed, arr);
70339           },
70340           writePackedSFixed32: function writePackedSFixed32(tag, arr) {
70341             if (arr.length) this.writeMessage(tag, _writePackedSFixed, arr);
70342           },
70343           writePackedFixed64: function writePackedFixed64(tag, arr) {
70344             if (arr.length) this.writeMessage(tag, _writePackedFixed2, arr);
70345           },
70346           writePackedSFixed64: function writePackedSFixed64(tag, arr) {
70347             if (arr.length) this.writeMessage(tag, _writePackedSFixed2, arr);
70348           },
70349           writeBytesField: function writeBytesField(tag, buffer) {
70350             this.writeTag(tag, Pbf.Bytes);
70351             this.writeBytes(buffer);
70352           },
70353           writeFixed32Field: function writeFixed32Field(tag, val) {
70354             this.writeTag(tag, Pbf.Fixed32);
70355             this.writeFixed32(val);
70356           },
70357           writeSFixed32Field: function writeSFixed32Field(tag, val) {
70358             this.writeTag(tag, Pbf.Fixed32);
70359             this.writeSFixed32(val);
70360           },
70361           writeFixed64Field: function writeFixed64Field(tag, val) {
70362             this.writeTag(tag, Pbf.Fixed64);
70363             this.writeFixed64(val);
70364           },
70365           writeSFixed64Field: function writeSFixed64Field(tag, val) {
70366             this.writeTag(tag, Pbf.Fixed64);
70367             this.writeSFixed64(val);
70368           },
70369           writeVarintField: function writeVarintField(tag, val) {
70370             this.writeTag(tag, Pbf.Varint);
70371             this.writeVarint(val);
70372           },
70373           writeSVarintField: function writeSVarintField(tag, val) {
70374             this.writeTag(tag, Pbf.Varint);
70375             this.writeSVarint(val);
70376           },
70377           writeStringField: function writeStringField(tag, str) {
70378             this.writeTag(tag, Pbf.Bytes);
70379             this.writeString(str);
70380           },
70381           writeFloatField: function writeFloatField(tag, val) {
70382             this.writeTag(tag, Pbf.Fixed32);
70383             this.writeFloat(val);
70384           },
70385           writeDoubleField: function writeDoubleField(tag, val) {
70386             this.writeTag(tag, Pbf.Fixed64);
70387             this.writeDouble(val);
70388           },
70389           writeBooleanField: function writeBooleanField(tag, val) {
70390             this.writeVarintField(tag, Boolean(val));
70391           }
70392         };
70393
70394         function readVarintRemainder(l, s, p) {
70395           var buf = p.buf,
70396               h,
70397               b;
70398           b = buf[p.pos++];
70399           h = (b & 0x70) >> 4;
70400           if (b < 0x80) return toNum(l, h, s);
70401           b = buf[p.pos++];
70402           h |= (b & 0x7f) << 3;
70403           if (b < 0x80) return toNum(l, h, s);
70404           b = buf[p.pos++];
70405           h |= (b & 0x7f) << 10;
70406           if (b < 0x80) return toNum(l, h, s);
70407           b = buf[p.pos++];
70408           h |= (b & 0x7f) << 17;
70409           if (b < 0x80) return toNum(l, h, s);
70410           b = buf[p.pos++];
70411           h |= (b & 0x7f) << 24;
70412           if (b < 0x80) return toNum(l, h, s);
70413           b = buf[p.pos++];
70414           h |= (b & 0x01) << 31;
70415           if (b < 0x80) return toNum(l, h, s);
70416           throw new Error('Expected varint not more than 10 bytes');
70417         }
70418
70419         function readPackedEnd(pbf) {
70420           return pbf.type === Pbf.Bytes ? pbf.readVarint() + pbf.pos : pbf.pos + 1;
70421         }
70422
70423         function toNum(low, high, isSigned) {
70424           if (isSigned) {
70425             return high * 0x100000000 + (low >>> 0);
70426           }
70427
70428           return (high >>> 0) * 0x100000000 + (low >>> 0);
70429         }
70430
70431         function writeBigVarint(val, pbf) {
70432           var low, high;
70433
70434           if (val >= 0) {
70435             low = val % 0x100000000 | 0;
70436             high = val / 0x100000000 | 0;
70437           } else {
70438             low = ~(-val % 0x100000000);
70439             high = ~(-val / 0x100000000);
70440
70441             if (low ^ 0xffffffff) {
70442               low = low + 1 | 0;
70443             } else {
70444               low = 0;
70445               high = high + 1 | 0;
70446             }
70447           }
70448
70449           if (val >= 0x10000000000000000 || val < -0x10000000000000000) {
70450             throw new Error('Given varint doesn\'t fit into 10 bytes');
70451           }
70452
70453           pbf.realloc(10);
70454           writeBigVarintLow(low, high, pbf);
70455           writeBigVarintHigh(high, pbf);
70456         }
70457
70458         function writeBigVarintLow(low, high, pbf) {
70459           pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70460           low >>>= 7;
70461           pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70462           low >>>= 7;
70463           pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70464           low >>>= 7;
70465           pbf.buf[pbf.pos++] = low & 0x7f | 0x80;
70466           low >>>= 7;
70467           pbf.buf[pbf.pos] = low & 0x7f;
70468         }
70469
70470         function writeBigVarintHigh(high, pbf) {
70471           var lsb = (high & 0x07) << 4;
70472           pbf.buf[pbf.pos++] |= lsb | ((high >>>= 3) ? 0x80 : 0);
70473           if (!high) return;
70474           pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70475           if (!high) return;
70476           pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70477           if (!high) return;
70478           pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70479           if (!high) return;
70480           pbf.buf[pbf.pos++] = high & 0x7f | ((high >>>= 7) ? 0x80 : 0);
70481           if (!high) return;
70482           pbf.buf[pbf.pos++] = high & 0x7f;
70483         }
70484
70485         function makeRoomForExtraLength(startPos, len, pbf) {
70486           var extraLen = len <= 0x3fff ? 1 : len <= 0x1fffff ? 2 : len <= 0xfffffff ? 3 : Math.floor(Math.log(len) / (Math.LN2 * 7)); // if 1 byte isn't enough for encoding message length, shift the data to the right
70487
70488           pbf.realloc(extraLen);
70489
70490           for (var i = pbf.pos - 1; i >= startPos; i--) {
70491             pbf.buf[i + extraLen] = pbf.buf[i];
70492           }
70493         }
70494
70495         function _writePackedVarint(arr, pbf) {
70496           for (var i = 0; i < arr.length; i++) {
70497             pbf.writeVarint(arr[i]);
70498           }
70499         }
70500
70501         function _writePackedSVarint(arr, pbf) {
70502           for (var i = 0; i < arr.length; i++) {
70503             pbf.writeSVarint(arr[i]);
70504           }
70505         }
70506
70507         function _writePackedFloat(arr, pbf) {
70508           for (var i = 0; i < arr.length; i++) {
70509             pbf.writeFloat(arr[i]);
70510           }
70511         }
70512
70513         function _writePackedDouble(arr, pbf) {
70514           for (var i = 0; i < arr.length; i++) {
70515             pbf.writeDouble(arr[i]);
70516           }
70517         }
70518
70519         function _writePackedBoolean(arr, pbf) {
70520           for (var i = 0; i < arr.length; i++) {
70521             pbf.writeBoolean(arr[i]);
70522           }
70523         }
70524
70525         function _writePackedFixed(arr, pbf) {
70526           for (var i = 0; i < arr.length; i++) {
70527             pbf.writeFixed32(arr[i]);
70528           }
70529         }
70530
70531         function _writePackedSFixed(arr, pbf) {
70532           for (var i = 0; i < arr.length; i++) {
70533             pbf.writeSFixed32(arr[i]);
70534           }
70535         }
70536
70537         function _writePackedFixed2(arr, pbf) {
70538           for (var i = 0; i < arr.length; i++) {
70539             pbf.writeFixed64(arr[i]);
70540           }
70541         }
70542
70543         function _writePackedSFixed2(arr, pbf) {
70544           for (var i = 0; i < arr.length; i++) {
70545             pbf.writeSFixed64(arr[i]);
70546           }
70547         } // Buffer code below from https://github.com/feross/buffer, MIT-licensed
70548
70549
70550         function readUInt32(buf, pos) {
70551           return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16) + buf[pos + 3] * 0x1000000;
70552         }
70553
70554         function writeInt32(buf, val, pos) {
70555           buf[pos] = val;
70556           buf[pos + 1] = val >>> 8;
70557           buf[pos + 2] = val >>> 16;
70558           buf[pos + 3] = val >>> 24;
70559         }
70560
70561         function readInt32(buf, pos) {
70562           return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16) + (buf[pos + 3] << 24);
70563         }
70564
70565         function readUtf8(buf, pos, end) {
70566           var str = '';
70567           var i = pos;
70568
70569           while (i < end) {
70570             var b0 = buf[i];
70571             var c = null; // codepoint
70572
70573             var bytesPerSequence = b0 > 0xEF ? 4 : b0 > 0xDF ? 3 : b0 > 0xBF ? 2 : 1;
70574             if (i + bytesPerSequence > end) break;
70575             var b1, b2, b3;
70576
70577             if (bytesPerSequence === 1) {
70578               if (b0 < 0x80) {
70579                 c = b0;
70580               }
70581             } else if (bytesPerSequence === 2) {
70582               b1 = buf[i + 1];
70583
70584               if ((b1 & 0xC0) === 0x80) {
70585                 c = (b0 & 0x1F) << 0x6 | b1 & 0x3F;
70586
70587                 if (c <= 0x7F) {
70588                   c = null;
70589                 }
70590               }
70591             } else if (bytesPerSequence === 3) {
70592               b1 = buf[i + 1];
70593               b2 = buf[i + 2];
70594
70595               if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80) {
70596                 c = (b0 & 0xF) << 0xC | (b1 & 0x3F) << 0x6 | b2 & 0x3F;
70597
70598                 if (c <= 0x7FF || c >= 0xD800 && c <= 0xDFFF) {
70599                   c = null;
70600                 }
70601               }
70602             } else if (bytesPerSequence === 4) {
70603               b1 = buf[i + 1];
70604               b2 = buf[i + 2];
70605               b3 = buf[i + 3];
70606
70607               if ((b1 & 0xC0) === 0x80 && (b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {
70608                 c = (b0 & 0xF) << 0x12 | (b1 & 0x3F) << 0xC | (b2 & 0x3F) << 0x6 | b3 & 0x3F;
70609
70610                 if (c <= 0xFFFF || c >= 0x110000) {
70611                   c = null;
70612                 }
70613               }
70614             }
70615
70616             if (c === null) {
70617               c = 0xFFFD;
70618               bytesPerSequence = 1;
70619             } else if (c > 0xFFFF) {
70620               c -= 0x10000;
70621               str += String.fromCharCode(c >>> 10 & 0x3FF | 0xD800);
70622               c = 0xDC00 | c & 0x3FF;
70623             }
70624
70625             str += String.fromCharCode(c);
70626             i += bytesPerSequence;
70627           }
70628
70629           return str;
70630         }
70631
70632         function readUtf8TextDecoder(buf, pos, end) {
70633           return utf8TextDecoder.decode(buf.subarray(pos, end));
70634         }
70635
70636         function writeUtf8(buf, str, pos) {
70637           for (var i = 0, c, lead; i < str.length; i++) {
70638             c = str.charCodeAt(i); // code point
70639
70640             if (c > 0xD7FF && c < 0xE000) {
70641               if (lead) {
70642                 if (c < 0xDC00) {
70643                   buf[pos++] = 0xEF;
70644                   buf[pos++] = 0xBF;
70645                   buf[pos++] = 0xBD;
70646                   lead = c;
70647                   continue;
70648                 } else {
70649                   c = lead - 0xD800 << 10 | c - 0xDC00 | 0x10000;
70650                   lead = null;
70651                 }
70652               } else {
70653                 if (c > 0xDBFF || i + 1 === str.length) {
70654                   buf[pos++] = 0xEF;
70655                   buf[pos++] = 0xBF;
70656                   buf[pos++] = 0xBD;
70657                 } else {
70658                   lead = c;
70659                 }
70660
70661                 continue;
70662               }
70663             } else if (lead) {
70664               buf[pos++] = 0xEF;
70665               buf[pos++] = 0xBF;
70666               buf[pos++] = 0xBD;
70667               lead = null;
70668             }
70669
70670             if (c < 0x80) {
70671               buf[pos++] = c;
70672             } else {
70673               if (c < 0x800) {
70674                 buf[pos++] = c >> 0x6 | 0xC0;
70675               } else {
70676                 if (c < 0x10000) {
70677                   buf[pos++] = c >> 0xC | 0xE0;
70678                 } else {
70679                   buf[pos++] = c >> 0x12 | 0xF0;
70680                   buf[pos++] = c >> 0xC & 0x3F | 0x80;
70681                 }
70682
70683                 buf[pos++] = c >> 0x6 & 0x3F | 0x80;
70684               }
70685
70686               buf[pos++] = c & 0x3F | 0x80;
70687             }
70688           }
70689
70690           return pos;
70691         }
70692
70693         var vectorTile = {};
70694
70695         var pointGeometry = Point$1;
70696         /**
70697          * A standalone point geometry with useful accessor, comparison, and
70698          * modification methods.
70699          *
70700          * @class Point
70701          * @param {Number} x the x-coordinate. this could be longitude or screen
70702          * pixels, or any other sort of unit.
70703          * @param {Number} y the y-coordinate. this could be latitude or screen
70704          * pixels, or any other sort of unit.
70705          * @example
70706          * var point = new Point(-77, 38);
70707          */
70708
70709         function Point$1(x, y) {
70710           this.x = x;
70711           this.y = y;
70712         }
70713
70714         Point$1.prototype = {
70715           /**
70716            * Clone this point, returning a new point that can be modified
70717            * without affecting the old one.
70718            * @return {Point} the clone
70719            */
70720           clone: function clone() {
70721             return new Point$1(this.x, this.y);
70722           },
70723
70724           /**
70725            * Add this point's x & y coordinates to another point,
70726            * yielding a new point.
70727            * @param {Point} p the other point
70728            * @return {Point} output point
70729            */
70730           add: function add(p) {
70731             return this.clone()._add(p);
70732           },
70733
70734           /**
70735            * Subtract this point's x & y coordinates to from point,
70736            * yielding a new point.
70737            * @param {Point} p the other point
70738            * @return {Point} output point
70739            */
70740           sub: function sub(p) {
70741             return this.clone()._sub(p);
70742           },
70743
70744           /**
70745            * Multiply this point's x & y coordinates by point,
70746            * yielding a new point.
70747            * @param {Point} p the other point
70748            * @return {Point} output point
70749            */
70750           multByPoint: function multByPoint(p) {
70751             return this.clone()._multByPoint(p);
70752           },
70753
70754           /**
70755            * Divide this point's x & y coordinates by point,
70756            * yielding a new point.
70757            * @param {Point} p the other point
70758            * @return {Point} output point
70759            */
70760           divByPoint: function divByPoint(p) {
70761             return this.clone()._divByPoint(p);
70762           },
70763
70764           /**
70765            * Multiply this point's x & y coordinates by a factor,
70766            * yielding a new point.
70767            * @param {Point} k factor
70768            * @return {Point} output point
70769            */
70770           mult: function mult(k) {
70771             return this.clone()._mult(k);
70772           },
70773
70774           /**
70775            * Divide this point's x & y coordinates by a factor,
70776            * yielding a new point.
70777            * @param {Point} k factor
70778            * @return {Point} output point
70779            */
70780           div: function div(k) {
70781             return this.clone()._div(k);
70782           },
70783
70784           /**
70785            * Rotate this point around the 0, 0 origin by an angle a,
70786            * given in radians
70787            * @param {Number} a angle to rotate around, in radians
70788            * @return {Point} output point
70789            */
70790           rotate: function rotate(a) {
70791             return this.clone()._rotate(a);
70792           },
70793
70794           /**
70795            * Rotate this point around p point by an angle a,
70796            * given in radians
70797            * @param {Number} a angle to rotate around, in radians
70798            * @param {Point} p Point to rotate around
70799            * @return {Point} output point
70800            */
70801           rotateAround: function rotateAround(a, p) {
70802             return this.clone()._rotateAround(a, p);
70803           },
70804
70805           /**
70806            * Multiply this point by a 4x1 transformation matrix
70807            * @param {Array<Number>} m transformation matrix
70808            * @return {Point} output point
70809            */
70810           matMult: function matMult(m) {
70811             return this.clone()._matMult(m);
70812           },
70813
70814           /**
70815            * Calculate this point but as a unit vector from 0, 0, meaning
70816            * that the distance from the resulting point to the 0, 0
70817            * coordinate will be equal to 1 and the angle from the resulting
70818            * point to the 0, 0 coordinate will be the same as before.
70819            * @return {Point} unit vector point
70820            */
70821           unit: function unit() {
70822             return this.clone()._unit();
70823           },
70824
70825           /**
70826            * Compute a perpendicular point, where the new y coordinate
70827            * is the old x coordinate and the new x coordinate is the old y
70828            * coordinate multiplied by -1
70829            * @return {Point} perpendicular point
70830            */
70831           perp: function perp() {
70832             return this.clone()._perp();
70833           },
70834
70835           /**
70836            * Return a version of this point with the x & y coordinates
70837            * rounded to integers.
70838            * @return {Point} rounded point
70839            */
70840           round: function round() {
70841             return this.clone()._round();
70842           },
70843
70844           /**
70845            * Return the magitude of this point: this is the Euclidean
70846            * distance from the 0, 0 coordinate to this point's x and y
70847            * coordinates.
70848            * @return {Number} magnitude
70849            */
70850           mag: function mag() {
70851             return Math.sqrt(this.x * this.x + this.y * this.y);
70852           },
70853
70854           /**
70855            * Judge whether this point is equal to another point, returning
70856            * true or false.
70857            * @param {Point} other the other point
70858            * @return {boolean} whether the points are equal
70859            */
70860           equals: function equals(other) {
70861             return this.x === other.x && this.y === other.y;
70862           },
70863
70864           /**
70865            * Calculate the distance from this point to another point
70866            * @param {Point} p the other point
70867            * @return {Number} distance
70868            */
70869           dist: function dist(p) {
70870             return Math.sqrt(this.distSqr(p));
70871           },
70872
70873           /**
70874            * Calculate the distance from this point to another point,
70875            * without the square root step. Useful if you're comparing
70876            * relative distances.
70877            * @param {Point} p the other point
70878            * @return {Number} distance
70879            */
70880           distSqr: function distSqr(p) {
70881             var dx = p.x - this.x,
70882                 dy = p.y - this.y;
70883             return dx * dx + dy * dy;
70884           },
70885
70886           /**
70887            * Get the angle from the 0, 0 coordinate to this point, in radians
70888            * coordinates.
70889            * @return {Number} angle
70890            */
70891           angle: function angle() {
70892             return Math.atan2(this.y, this.x);
70893           },
70894
70895           /**
70896            * Get the angle from this point to another point, in radians
70897            * @param {Point} b the other point
70898            * @return {Number} angle
70899            */
70900           angleTo: function angleTo(b) {
70901             return Math.atan2(this.y - b.y, this.x - b.x);
70902           },
70903
70904           /**
70905            * Get the angle between this point and another point, in radians
70906            * @param {Point} b the other point
70907            * @return {Number} angle
70908            */
70909           angleWith: function angleWith(b) {
70910             return this.angleWithSep(b.x, b.y);
70911           },
70912
70913           /*
70914            * Find the angle of the two vectors, solving the formula for
70915            * the cross product a x b = |a||b|sin(θ) for θ.
70916            * @param {Number} x the x-coordinate
70917            * @param {Number} y the y-coordinate
70918            * @return {Number} the angle in radians
70919            */
70920           angleWithSep: function angleWithSep(x, y) {
70921             return Math.atan2(this.x * y - this.y * x, this.x * x + this.y * y);
70922           },
70923           _matMult: function _matMult(m) {
70924             var x = m[0] * this.x + m[1] * this.y,
70925                 y = m[2] * this.x + m[3] * this.y;
70926             this.x = x;
70927             this.y = y;
70928             return this;
70929           },
70930           _add: function _add(p) {
70931             this.x += p.x;
70932             this.y += p.y;
70933             return this;
70934           },
70935           _sub: function _sub(p) {
70936             this.x -= p.x;
70937             this.y -= p.y;
70938             return this;
70939           },
70940           _mult: function _mult(k) {
70941             this.x *= k;
70942             this.y *= k;
70943             return this;
70944           },
70945           _div: function _div(k) {
70946             this.x /= k;
70947             this.y /= k;
70948             return this;
70949           },
70950           _multByPoint: function _multByPoint(p) {
70951             this.x *= p.x;
70952             this.y *= p.y;
70953             return this;
70954           },
70955           _divByPoint: function _divByPoint(p) {
70956             this.x /= p.x;
70957             this.y /= p.y;
70958             return this;
70959           },
70960           _unit: function _unit() {
70961             this._div(this.mag());
70962
70963             return this;
70964           },
70965           _perp: function _perp() {
70966             var y = this.y;
70967             this.y = this.x;
70968             this.x = -y;
70969             return this;
70970           },
70971           _rotate: function _rotate(angle) {
70972             var cos = Math.cos(angle),
70973                 sin = Math.sin(angle),
70974                 x = cos * this.x - sin * this.y,
70975                 y = sin * this.x + cos * this.y;
70976             this.x = x;
70977             this.y = y;
70978             return this;
70979           },
70980           _rotateAround: function _rotateAround(angle, p) {
70981             var cos = Math.cos(angle),
70982                 sin = Math.sin(angle),
70983                 x = p.x + cos * (this.x - p.x) - sin * (this.y - p.y),
70984                 y = p.y + sin * (this.x - p.x) + cos * (this.y - p.y);
70985             this.x = x;
70986             this.y = y;
70987             return this;
70988           },
70989           _round: function _round() {
70990             this.x = Math.round(this.x);
70991             this.y = Math.round(this.y);
70992             return this;
70993           }
70994         };
70995         /**
70996          * Construct a point from an array if necessary, otherwise if the input
70997          * is already a Point, or an unknown type, return it unchanged
70998          * @param {Array<Number>|Point|*} a any kind of input value
70999          * @return {Point} constructed point, or passed-through value.
71000          * @example
71001          * // this
71002          * var point = Point.convert([0, 1]);
71003          * // is equivalent to
71004          * var point = new Point(0, 1);
71005          */
71006
71007         Point$1.convert = function (a) {
71008           if (a instanceof Point$1) {
71009             return a;
71010           }
71011
71012           if (Array.isArray(a)) {
71013             return new Point$1(a[0], a[1]);
71014           }
71015
71016           return a;
71017         };
71018
71019         var Point = pointGeometry;
71020         var vectortilefeature = VectorTileFeature$1;
71021
71022         function VectorTileFeature$1(pbf, end, extent, keys, values) {
71023           // Public
71024           this.properties = {};
71025           this.extent = extent;
71026           this.type = 0; // Private
71027
71028           this._pbf = pbf;
71029           this._geometry = -1;
71030           this._keys = keys;
71031           this._values = values;
71032           pbf.readFields(readFeature, this, end);
71033         }
71034
71035         function readFeature(tag, feature, pbf) {
71036           if (tag == 1) feature.id = pbf.readVarint();else if (tag == 2) readTag(pbf, feature);else if (tag == 3) feature.type = pbf.readVarint();else if (tag == 4) feature._geometry = pbf.pos;
71037         }
71038
71039         function readTag(pbf, feature) {
71040           var end = pbf.readVarint() + pbf.pos;
71041
71042           while (pbf.pos < end) {
71043             var key = feature._keys[pbf.readVarint()],
71044                 value = feature._values[pbf.readVarint()];
71045
71046             feature.properties[key] = value;
71047           }
71048         }
71049
71050         VectorTileFeature$1.types = ['Unknown', 'Point', 'LineString', 'Polygon'];
71051
71052         VectorTileFeature$1.prototype.loadGeometry = function () {
71053           var pbf = this._pbf;
71054           pbf.pos = this._geometry;
71055           var end = pbf.readVarint() + pbf.pos,
71056               cmd = 1,
71057               length = 0,
71058               x = 0,
71059               y = 0,
71060               lines = [],
71061               line;
71062
71063           while (pbf.pos < end) {
71064             if (length <= 0) {
71065               var cmdLen = pbf.readVarint();
71066               cmd = cmdLen & 0x7;
71067               length = cmdLen >> 3;
71068             }
71069
71070             length--;
71071
71072             if (cmd === 1 || cmd === 2) {
71073               x += pbf.readSVarint();
71074               y += pbf.readSVarint();
71075
71076               if (cmd === 1) {
71077                 // moveTo
71078                 if (line) lines.push(line);
71079                 line = [];
71080               }
71081
71082               line.push(new Point(x, y));
71083             } else if (cmd === 7) {
71084               // Workaround for https://github.com/mapbox/mapnik-vector-tile/issues/90
71085               if (line) {
71086                 line.push(line[0].clone()); // closePolygon
71087               }
71088             } else {
71089               throw new Error('unknown command ' + cmd);
71090             }
71091           }
71092
71093           if (line) lines.push(line);
71094           return lines;
71095         };
71096
71097         VectorTileFeature$1.prototype.bbox = function () {
71098           var pbf = this._pbf;
71099           pbf.pos = this._geometry;
71100           var end = pbf.readVarint() + pbf.pos,
71101               cmd = 1,
71102               length = 0,
71103               x = 0,
71104               y = 0,
71105               x1 = Infinity,
71106               x2 = -Infinity,
71107               y1 = Infinity,
71108               y2 = -Infinity;
71109
71110           while (pbf.pos < end) {
71111             if (length <= 0) {
71112               var cmdLen = pbf.readVarint();
71113               cmd = cmdLen & 0x7;
71114               length = cmdLen >> 3;
71115             }
71116
71117             length--;
71118
71119             if (cmd === 1 || cmd === 2) {
71120               x += pbf.readSVarint();
71121               y += pbf.readSVarint();
71122               if (x < x1) x1 = x;
71123               if (x > x2) x2 = x;
71124               if (y < y1) y1 = y;
71125               if (y > y2) y2 = y;
71126             } else if (cmd !== 7) {
71127               throw new Error('unknown command ' + cmd);
71128             }
71129           }
71130
71131           return [x1, y1, x2, y2];
71132         };
71133
71134         VectorTileFeature$1.prototype.toGeoJSON = function (x, y, z) {
71135           var size = this.extent * Math.pow(2, z),
71136               x0 = this.extent * x,
71137               y0 = this.extent * y,
71138               coords = this.loadGeometry(),
71139               type = VectorTileFeature$1.types[this.type],
71140               i,
71141               j;
71142
71143           function project(line) {
71144             for (var j = 0; j < line.length; j++) {
71145               var p = line[j],
71146                   y2 = 180 - (p.y + y0) * 360 / size;
71147               line[j] = [(p.x + x0) * 360 / size - 180, 360 / Math.PI * Math.atan(Math.exp(y2 * Math.PI / 180)) - 90];
71148             }
71149           }
71150
71151           switch (this.type) {
71152             case 1:
71153               var points = [];
71154
71155               for (i = 0; i < coords.length; i++) {
71156                 points[i] = coords[i][0];
71157               }
71158
71159               coords = points;
71160               project(coords);
71161               break;
71162
71163             case 2:
71164               for (i = 0; i < coords.length; i++) {
71165                 project(coords[i]);
71166               }
71167
71168               break;
71169
71170             case 3:
71171               coords = classifyRings(coords);
71172
71173               for (i = 0; i < coords.length; i++) {
71174                 for (j = 0; j < coords[i].length; j++) {
71175                   project(coords[i][j]);
71176                 }
71177               }
71178
71179               break;
71180           }
71181
71182           if (coords.length === 1) {
71183             coords = coords[0];
71184           } else {
71185             type = 'Multi' + type;
71186           }
71187
71188           var result = {
71189             type: "Feature",
71190             geometry: {
71191               type: type,
71192               coordinates: coords
71193             },
71194             properties: this.properties
71195           };
71196
71197           if ('id' in this) {
71198             result.id = this.id;
71199           }
71200
71201           return result;
71202         }; // classifies an array of rings into polygons with outer rings and holes
71203
71204
71205         function classifyRings(rings) {
71206           var len = rings.length;
71207           if (len <= 1) return [rings];
71208           var polygons = [],
71209               polygon,
71210               ccw;
71211
71212           for (var i = 0; i < len; i++) {
71213             var area = signedArea(rings[i]);
71214             if (area === 0) continue;
71215             if (ccw === undefined) ccw = area < 0;
71216
71217             if (ccw === area < 0) {
71218               if (polygon) polygons.push(polygon);
71219               polygon = [rings[i]];
71220             } else {
71221               polygon.push(rings[i]);
71222             }
71223           }
71224
71225           if (polygon) polygons.push(polygon);
71226           return polygons;
71227         }
71228
71229         function signedArea(ring) {
71230           var sum = 0;
71231
71232           for (var i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) {
71233             p1 = ring[i];
71234             p2 = ring[j];
71235             sum += (p2.x - p1.x) * (p1.y + p2.y);
71236           }
71237
71238           return sum;
71239         }
71240
71241         var VectorTileFeature = vectortilefeature;
71242         var vectortilelayer = VectorTileLayer$1;
71243
71244         function VectorTileLayer$1(pbf, end) {
71245           // Public
71246           this.version = 1;
71247           this.name = null;
71248           this.extent = 4096;
71249           this.length = 0; // Private
71250
71251           this._pbf = pbf;
71252           this._keys = [];
71253           this._values = [];
71254           this._features = [];
71255           pbf.readFields(readLayer, this, end);
71256           this.length = this._features.length;
71257         }
71258
71259         function readLayer(tag, layer, pbf) {
71260           if (tag === 15) layer.version = pbf.readVarint();else if (tag === 1) layer.name = pbf.readString();else if (tag === 5) layer.extent = pbf.readVarint();else if (tag === 2) layer._features.push(pbf.pos);else if (tag === 3) layer._keys.push(pbf.readString());else if (tag === 4) layer._values.push(readValueMessage(pbf));
71261         }
71262
71263         function readValueMessage(pbf) {
71264           var value = null,
71265               end = pbf.readVarint() + pbf.pos;
71266
71267           while (pbf.pos < end) {
71268             var tag = pbf.readVarint() >> 3;
71269             value = tag === 1 ? pbf.readString() : tag === 2 ? pbf.readFloat() : tag === 3 ? pbf.readDouble() : tag === 4 ? pbf.readVarint64() : tag === 5 ? pbf.readVarint() : tag === 6 ? pbf.readSVarint() : tag === 7 ? pbf.readBoolean() : null;
71270           }
71271
71272           return value;
71273         } // return feature `i` from this layer as a `VectorTileFeature`
71274
71275
71276         VectorTileLayer$1.prototype.feature = function (i) {
71277           if (i < 0 || i >= this._features.length) throw new Error('feature index out of bounds');
71278           this._pbf.pos = this._features[i];
71279
71280           var end = this._pbf.readVarint() + this._pbf.pos;
71281
71282           return new VectorTileFeature(this._pbf, end, this.extent, this._keys, this._values);
71283         };
71284
71285         var VectorTileLayer = vectortilelayer;
71286         var vectortile = VectorTile$1;
71287
71288         function VectorTile$1(pbf, end) {
71289           this.layers = pbf.readFields(readTile, {}, end);
71290         }
71291
71292         function readTile(tag, layers, pbf) {
71293           if (tag === 3) {
71294             var layer = new VectorTileLayer(pbf, pbf.readVarint() + pbf.pos);
71295             if (layer.length) layers[layer.name] = layer;
71296           }
71297         }
71298
71299         var VectorTile = vectorTile.VectorTile = vectortile;
71300         vectorTile.VectorTileFeature = vectortilefeature;
71301         vectorTile.VectorTileLayer = vectortilelayer;
71302
71303         var accessToken = 'MLY|4100327730013843|5bb78b81720791946a9a7b956c57b7cf';
71304         var apiUrl = 'https://graph.mapillary.com/';
71305         var baseTileUrl = 'https://tiles.mapillary.com/maps/vtp';
71306         var mapFeatureTileUrl = "".concat(baseTileUrl, "/mly_map_feature_point/2/{z}/{x}/{y}?access_token=").concat(accessToken);
71307         var tileUrl = "".concat(baseTileUrl, "/mly1_public/2/{z}/{x}/{y}?access_token=").concat(accessToken);
71308         var trafficSignTileUrl = "".concat(baseTileUrl, "/mly_map_feature_traffic_sign/2/{z}/{x}/{y}?access_token=").concat(accessToken);
71309         var viewercss = 'mapillary-js/mapillary.css';
71310         var viewerjs = 'mapillary-js/mapillary.js';
71311         var minZoom$1 = 14;
71312         var dispatch$4 = dispatch$8('change', 'loadedImages', 'loadedSigns', 'loadedMapFeatures', 'bearingChanged', 'imageChanged');
71313
71314         var _loadViewerPromise$2;
71315
71316         var _mlyActiveImage;
71317
71318         var _mlyCache;
71319
71320         var _mlyFallback = false;
71321
71322         var _mlyHighlightedDetection;
71323
71324         var _mlyShowFeatureDetections = false;
71325         var _mlyShowSignDetections = false;
71326
71327         var _mlyViewer;
71328
71329         var _mlyViewerFilter = ['all']; // Load all data for the specified type from Mapillary vector tiles
71330
71331         function loadTiles$2(which, url, maxZoom, projection) {
71332           var tiler = utilTiler().zoomExtent([minZoom$1, maxZoom]).skipNullIsland(true);
71333           var tiles = tiler.getTiles(projection);
71334           tiles.forEach(function (tile) {
71335             loadTile$1(which, url, tile);
71336           });
71337         } // Load all data for the specified type from one vector tile
71338
71339
71340         function loadTile$1(which, url, tile) {
71341           var cache = _mlyCache.requests;
71342           var tileId = "".concat(tile.id, "-").concat(which);
71343           if (cache.loaded[tileId] || cache.inflight[tileId]) return;
71344           var controller = new AbortController();
71345           cache.inflight[tileId] = controller;
71346           var requestUrl = url.replace('{x}', tile.xyz[0]).replace('{y}', tile.xyz[1]).replace('{z}', tile.xyz[2]);
71347           fetch(requestUrl, {
71348             signal: controller.signal
71349           }).then(function (response) {
71350             if (!response.ok) {
71351               throw new Error(response.status + ' ' + response.statusText);
71352             }
71353
71354             cache.loaded[tileId] = true;
71355             delete cache.inflight[tileId];
71356             return response.arrayBuffer();
71357           }).then(function (data) {
71358             if (!data) {
71359               throw new Error('No Data');
71360             }
71361
71362             loadTileDataToCache(data, tile, which);
71363
71364             if (which === 'images') {
71365               dispatch$4.call('loadedImages');
71366             } else if (which === 'signs') {
71367               dispatch$4.call('loadedSigns');
71368             } else if (which === 'points') {
71369               dispatch$4.call('loadedMapFeatures');
71370             }
71371           })["catch"](function () {
71372             cache.loaded[tileId] = true;
71373             delete cache.inflight[tileId];
71374           });
71375         } // Load the data from the vector tile into cache
71376
71377
71378         function loadTileDataToCache(data, tile, which) {
71379           var vectorTile = new VectorTile(new pbf(data));
71380           var features, cache, layer, i, feature, loc, d;
71381
71382           if (vectorTile.layers.hasOwnProperty('image')) {
71383             features = [];
71384             cache = _mlyCache.images;
71385             layer = vectorTile.layers.image;
71386
71387             for (i = 0; i < layer.length; i++) {
71388               feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71389               loc = feature.geometry.coordinates;
71390               d = {
71391                 loc: loc,
71392                 captured_at: feature.properties.captured_at,
71393                 ca: feature.properties.compass_angle,
71394                 id: feature.properties.id,
71395                 is_pano: feature.properties.is_pano,
71396                 sequence_id: feature.properties.sequence_id
71397               };
71398               cache.forImageId[d.id] = d;
71399               features.push({
71400                 minX: loc[0],
71401                 minY: loc[1],
71402                 maxX: loc[0],
71403                 maxY: loc[1],
71404                 data: d
71405               });
71406             }
71407
71408             if (cache.rtree) {
71409               cache.rtree.load(features);
71410             }
71411           }
71412
71413           if (vectorTile.layers.hasOwnProperty('sequence')) {
71414             features = [];
71415             cache = _mlyCache.sequences;
71416             layer = vectorTile.layers.sequence;
71417
71418             for (i = 0; i < layer.length; i++) {
71419               feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71420
71421               if (cache.lineString[feature.properties.id]) {
71422                 cache.lineString[feature.properties.id].push(feature);
71423               } else {
71424                 cache.lineString[feature.properties.id] = [feature];
71425               }
71426             }
71427           }
71428
71429           if (vectorTile.layers.hasOwnProperty('point')) {
71430             features = [];
71431             cache = _mlyCache[which];
71432             layer = vectorTile.layers.point;
71433
71434             for (i = 0; i < layer.length; i++) {
71435               feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71436               loc = feature.geometry.coordinates;
71437               d = {
71438                 loc: loc,
71439                 id: feature.properties.id,
71440                 first_seen_at: feature.properties.first_seen_at,
71441                 last_seen_at: feature.properties.last_seen_at,
71442                 value: feature.properties.value
71443               };
71444               features.push({
71445                 minX: loc[0],
71446                 minY: loc[1],
71447                 maxX: loc[0],
71448                 maxY: loc[1],
71449                 data: d
71450               });
71451             }
71452
71453             if (cache.rtree) {
71454               cache.rtree.load(features);
71455             }
71456           }
71457
71458           if (vectorTile.layers.hasOwnProperty('traffic_sign')) {
71459             features = [];
71460             cache = _mlyCache[which];
71461             layer = vectorTile.layers.traffic_sign;
71462
71463             for (i = 0; i < layer.length; i++) {
71464               feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
71465               loc = feature.geometry.coordinates;
71466               d = {
71467                 loc: loc,
71468                 id: feature.properties.id,
71469                 first_seen_at: feature.properties.first_seen_at,
71470                 last_seen_at: feature.properties.last_seen_at,
71471                 value: feature.properties.value
71472               };
71473               features.push({
71474                 minX: loc[0],
71475                 minY: loc[1],
71476                 maxX: loc[0],
71477                 maxY: loc[1],
71478                 data: d
71479               });
71480             }
71481
71482             if (cache.rtree) {
71483               cache.rtree.load(features);
71484             }
71485           }
71486         } // Get data from the API
71487
71488
71489         function loadData(url) {
71490           return fetch(url).then(function (response) {
71491             if (!response.ok) {
71492               throw new Error(response.status + ' ' + response.statusText);
71493             }
71494
71495             return response.json();
71496           }).then(function (result) {
71497             if (!result) {
71498               return [];
71499             }
71500
71501             return result.data || [];
71502           });
71503         } // Partition viewport into higher zoom tiles
71504
71505
71506         function partitionViewport$2(projection) {
71507           var z = geoScaleToZoom(projection.scale());
71508           var z2 = Math.ceil(z * 2) / 2 + 2.5; // round to next 0.5 and add 2.5
71509
71510           var tiler = utilTiler().zoomExtent([z2, z2]);
71511           return tiler.getTiles(projection).map(function (tile) {
71512             return tile.extent;
71513           });
71514         } // Return no more than `limit` results per partition.
71515
71516
71517         function searchLimited$2(limit, projection, rtree) {
71518           limit = limit || 5;
71519           return partitionViewport$2(projection).reduce(function (result, extent) {
71520             var found = rtree.search(extent.bbox()).slice(0, limit).map(function (d) {
71521               return d.data;
71522             });
71523             return found.length ? result.concat(found) : result;
71524           }, []);
71525         }
71526
71527         var serviceMapillary = {
71528           // Initialize Mapillary
71529           init: function init() {
71530             if (!_mlyCache) {
71531               this.reset();
71532             }
71533
71534             this.event = utilRebind(this, dispatch$4, 'on');
71535           },
71536           // Reset cache and state
71537           reset: function reset() {
71538             if (_mlyCache) {
71539               Object.values(_mlyCache.requests.inflight).forEach(function (request) {
71540                 request.abort();
71541               });
71542             }
71543
71544             _mlyCache = {
71545               images: {
71546                 rtree: new RBush(),
71547                 forImageId: {}
71548               },
71549               image_detections: {
71550                 forImageId: {}
71551               },
71552               signs: {
71553                 rtree: new RBush()
71554               },
71555               points: {
71556                 rtree: new RBush()
71557               },
71558               sequences: {
71559                 rtree: new RBush(),
71560                 lineString: {}
71561               },
71562               requests: {
71563                 loaded: {},
71564                 inflight: {}
71565               }
71566             };
71567             _mlyActiveImage = null;
71568           },
71569           // Get visible images
71570           images: function images(projection) {
71571             var limit = 5;
71572             return searchLimited$2(limit, projection, _mlyCache.images.rtree);
71573           },
71574           // Get visible traffic signs
71575           signs: function signs(projection) {
71576             var limit = 5;
71577             return searchLimited$2(limit, projection, _mlyCache.signs.rtree);
71578           },
71579           // Get visible map (point) features
71580           mapFeatures: function mapFeatures(projection) {
71581             var limit = 5;
71582             return searchLimited$2(limit, projection, _mlyCache.points.rtree);
71583           },
71584           // Get cached image by id
71585           cachedImage: function cachedImage(imageId) {
71586             return _mlyCache.images.forImageId[imageId];
71587           },
71588           // Get visible sequences
71589           sequences: function sequences(projection) {
71590             var viewport = projection.clipExtent();
71591             var min = [viewport[0][0], viewport[1][1]];
71592             var max = [viewport[1][0], viewport[0][1]];
71593             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
71594             var sequenceIds = {};
71595             var lineStrings = [];
71596
71597             _mlyCache.images.rtree.search(bbox).forEach(function (d) {
71598               if (d.data.sequence_id) {
71599                 sequenceIds[d.data.sequence_id] = true;
71600               }
71601             });
71602
71603             Object.keys(sequenceIds).forEach(function (sequenceId) {
71604               if (_mlyCache.sequences.lineString[sequenceId]) {
71605                 lineStrings = lineStrings.concat(_mlyCache.sequences.lineString[sequenceId]);
71606               }
71607             });
71608             return lineStrings;
71609           },
71610           // Load images in the visible area
71611           loadImages: function loadImages(projection) {
71612             loadTiles$2('images', tileUrl, 14, projection);
71613           },
71614           // Load traffic signs in the visible area
71615           loadSigns: function loadSigns(projection) {
71616             loadTiles$2('signs', trafficSignTileUrl, 14, projection);
71617           },
71618           // Load map (point) features in the visible area
71619           loadMapFeatures: function loadMapFeatures(projection) {
71620             loadTiles$2('points', mapFeatureTileUrl, 14, projection);
71621           },
71622           // Return a promise that resolves when the image viewer (Mapillary JS) library has finished loading
71623           ensureViewerLoaded: function ensureViewerLoaded(context) {
71624             if (_loadViewerPromise$2) return _loadViewerPromise$2; // add mly-wrapper
71625
71626             var wrap = context.container().select('.photoviewer').selectAll('.mly-wrapper').data([0]);
71627             wrap.enter().append('div').attr('id', 'ideditor-mly').attr('class', 'photo-wrapper mly-wrapper').classed('hide', true);
71628             var that = this;
71629             _loadViewerPromise$2 = new Promise(function (resolve, reject) {
71630               var loadedCount = 0;
71631
71632               function loaded() {
71633                 loadedCount += 1; // wait until both files are loaded
71634
71635                 if (loadedCount === 2) resolve();
71636               }
71637
71638               var head = select('head'); // load mapillary-viewercss
71639
71640               head.selectAll('#ideditor-mapillary-viewercss').data([0]).enter().append('link').attr('id', 'ideditor-mapillary-viewercss').attr('rel', 'stylesheet').attr('crossorigin', 'anonymous').attr('href', context.asset(viewercss)).on('load.serviceMapillary', loaded).on('error.serviceMapillary', function () {
71641                 reject();
71642               }); // load mapillary-viewerjs
71643
71644               head.selectAll('#ideditor-mapillary-viewerjs').data([0]).enter().append('script').attr('id', 'ideditor-mapillary-viewerjs').attr('crossorigin', 'anonymous').attr('src', context.asset(viewerjs)).on('load.serviceMapillary', loaded).on('error.serviceMapillary', function () {
71645                 reject();
71646               });
71647             })["catch"](function () {
71648               _loadViewerPromise$2 = null;
71649             }).then(function () {
71650               that.initViewer(context);
71651             });
71652             return _loadViewerPromise$2;
71653           },
71654           // Load traffic sign image sprites
71655           loadSignResources: function loadSignResources(context) {
71656             context.ui().svgDefs.addSprites(['mapillary-sprite'], false
71657             /* don't override colors */
71658             );
71659             return this;
71660           },
71661           // Load map (point) feature image sprites
71662           loadObjectResources: function loadObjectResources(context) {
71663             context.ui().svgDefs.addSprites(['mapillary-object-sprite'], false
71664             /* don't override colors */
71665             );
71666             return this;
71667           },
71668           // Remove previous detections in image viewer
71669           resetTags: function resetTags() {
71670             if (_mlyViewer && !_mlyFallback) {
71671               _mlyViewer.getComponent('tag').removeAll();
71672             }
71673           },
71674           // Show map feature detections in image viewer
71675           showFeatureDetections: function showFeatureDetections(value) {
71676             _mlyShowFeatureDetections = value;
71677
71678             if (!_mlyShowFeatureDetections && !_mlyShowSignDetections) {
71679               this.resetTags();
71680             }
71681           },
71682           // Show traffic sign detections in image viewer
71683           showSignDetections: function showSignDetections(value) {
71684             _mlyShowSignDetections = value;
71685
71686             if (!_mlyShowFeatureDetections && !_mlyShowSignDetections) {
71687               this.resetTags();
71688             }
71689           },
71690           // Apply filter to image viewer
71691           filterViewer: function filterViewer(context) {
71692             var showsPano = context.photos().showsPanoramic();
71693             var showsFlat = context.photos().showsFlat();
71694             var fromDate = context.photos().fromDate();
71695             var toDate = context.photos().toDate();
71696             var filter = ['all'];
71697             if (!showsPano) filter.push(['!=', 'cameraType', 'spherical']);
71698             if (!showsFlat && showsPano) filter.push(['==', 'pano', true]);
71699
71700             if (fromDate) {
71701               filter.push(['>=', 'capturedAt', new Date(fromDate).getTime()]);
71702             }
71703
71704             if (toDate) {
71705               filter.push(['>=', 'capturedAt', new Date(toDate).getTime()]);
71706             }
71707
71708             if (_mlyViewer) {
71709               _mlyViewer.setFilter(filter);
71710             }
71711
71712             _mlyViewerFilter = filter;
71713             return filter;
71714           },
71715           // Make the image viewer visible
71716           showViewer: function showViewer(context) {
71717             var wrap = context.container().select('.photoviewer').classed('hide', false);
71718             var isHidden = wrap.selectAll('.photo-wrapper.mly-wrapper.hide').size();
71719
71720             if (isHidden && _mlyViewer) {
71721               wrap.selectAll('.photo-wrapper:not(.mly-wrapper)').classed('hide', true);
71722               wrap.selectAll('.photo-wrapper.mly-wrapper').classed('hide', false);
71723
71724               _mlyViewer.resize();
71725             }
71726
71727             return this;
71728           },
71729           // Hide the image viewer and resets map markers
71730           hideViewer: function hideViewer(context) {
71731             _mlyActiveImage = null;
71732
71733             if (!_mlyFallback && _mlyViewer) {
71734               _mlyViewer.getComponent('sequence').stop();
71735             }
71736
71737             var viewer = context.container().select('.photoviewer');
71738             if (!viewer.empty()) viewer.datum(null);
71739             viewer.classed('hide', true).selectAll('.photo-wrapper').classed('hide', true);
71740             this.updateUrlImage(null);
71741             dispatch$4.call('imageChanged');
71742             dispatch$4.call('loadedMapFeatures');
71743             dispatch$4.call('loadedSigns');
71744             return this.setStyles(context, null);
71745           },
71746           // Update the URL with current image id
71747           updateUrlImage: function updateUrlImage(imageId) {
71748             if (!window.mocha) {
71749               var hash = utilStringQs(window.location.hash);
71750
71751               if (imageId) {
71752                 hash.photo = 'mapillary/' + imageId;
71753               } else {
71754                 delete hash.photo;
71755               }
71756
71757               window.location.replace('#' + utilQsString(hash, true));
71758             }
71759           },
71760           // Highlight the detection in the viewer that is related to the clicked map feature
71761           highlightDetection: function highlightDetection(detection) {
71762             if (detection) {
71763               _mlyHighlightedDetection = detection.id;
71764             }
71765
71766             return this;
71767           },
71768           // Initialize image viewer (Mapillar JS)
71769           initViewer: function initViewer(context) {
71770             var that = this;
71771             if (!window.mapillary) return;
71772             var opts = {
71773               accessToken: accessToken,
71774               component: {
71775                 cover: false,
71776                 keyboard: false,
71777                 tag: true
71778               },
71779               container: 'ideditor-mly'
71780             }; // Disable components requiring WebGL support
71781
71782             if (!mapillary.isSupported() && mapillary.isFallbackSupported()) {
71783               _mlyFallback = true;
71784               opts.component = {
71785                 cover: false,
71786                 direction: false,
71787                 imagePlane: false,
71788                 keyboard: false,
71789                 mouse: false,
71790                 sequence: false,
71791                 tag: false,
71792                 image: true,
71793                 // fallback
71794                 navigation: true // fallback
71795
71796               };
71797             }
71798
71799             _mlyViewer = new mapillary.Viewer(opts);
71800
71801             _mlyViewer.on('image', imageChanged);
71802
71803             _mlyViewer.on('bearing', bearingChanged);
71804
71805             if (_mlyViewerFilter) {
71806               _mlyViewer.setFilter(_mlyViewerFilter);
71807             } // Register viewer resize handler
71808
71809
71810             context.ui().photoviewer.on('resize.mapillary', function () {
71811               if (_mlyViewer) _mlyViewer.resize();
71812             }); // imageChanged: called after the viewer has changed images and is ready.
71813
71814             function imageChanged(node) {
71815               that.resetTags();
71816               var image = node.image;
71817               that.setActiveImage(image);
71818               that.setStyles(context, null);
71819               var loc = [image.originalLngLat.lng, image.originalLngLat.lat];
71820               context.map().centerEase(loc);
71821               that.updateUrlImage(image.id);
71822
71823               if (_mlyShowFeatureDetections || _mlyShowSignDetections) {
71824                 that.updateDetections(image.id, "".concat(apiUrl, "/").concat(image.id, "/detections?access_token=").concat(accessToken, "&fields=id,image,geometry,value"));
71825               }
71826
71827               dispatch$4.call('imageChanged');
71828             } // bearingChanged: called when the bearing changes in the image viewer.
71829
71830
71831             function bearingChanged(e) {
71832               dispatch$4.call('bearingChanged', undefined, e);
71833             }
71834           },
71835           // Move to an image
71836           selectImage: function selectImage(context, imageId) {
71837             if (_mlyViewer && imageId) {
71838               _mlyViewer.moveTo(imageId)["catch"](function (e) {
71839                 console.error('mly3', e); // eslint-disable-line no-console
71840               });
71841             }
71842
71843             return this;
71844           },
71845           // Return the currently displayed image
71846           getActiveImage: function getActiveImage() {
71847             return _mlyActiveImage;
71848           },
71849           // Return a list of detection objects for the given id
71850           getDetections: function getDetections(id) {
71851             return loadData("".concat(apiUrl, "/").concat(id, "/detections?access_token=").concat(accessToken, "&fields=id,value,image"));
71852           },
71853           // Set the currently visible image
71854           setActiveImage: function setActiveImage(image) {
71855             if (image) {
71856               _mlyActiveImage = {
71857                 ca: image.originalCompassAngle,
71858                 id: image.id,
71859                 loc: [image.originalLngLat.lng, image.originalLngLat.lat],
71860                 is_pano: image.cameraType === 'spherical',
71861                 sequence_id: image.sequenceId
71862               };
71863             } else {
71864               _mlyActiveImage = null;
71865             }
71866           },
71867           // Update the currently highlighted sequence and selected bubble.
71868           setStyles: function setStyles(context, hovered) {
71869             var hoveredImageId = hovered && hovered.id;
71870             var hoveredSequenceId = hovered && hovered.sequence_id;
71871             var selectedSequenceId = _mlyActiveImage && _mlyActiveImage.sequence_id;
71872             context.container().selectAll('.layer-mapillary .viewfield-group').classed('highlighted', function (d) {
71873               return d.sequence_id === selectedSequenceId || d.id === hoveredImageId;
71874             }).classed('hovered', function (d) {
71875               return d.id === hoveredImageId;
71876             });
71877             context.container().selectAll('.layer-mapillary .sequence').classed('highlighted', function (d) {
71878               return d.properties.id === hoveredSequenceId;
71879             }).classed('currentView', function (d) {
71880               return d.properties.id === selectedSequenceId;
71881             });
71882             return this;
71883           },
71884           // Get detections for the current image and shows them in the image viewer
71885           updateDetections: function updateDetections(imageId, url) {
71886             if (!_mlyViewer || _mlyFallback) return;
71887             if (!imageId) return;
71888             var cache = _mlyCache.image_detections;
71889
71890             if (cache.forImageId[imageId]) {
71891               showDetections(_mlyCache.image_detections.forImageId[imageId]);
71892             } else {
71893               loadData(url).then(function (detections) {
71894                 detections.forEach(function (detection) {
71895                   if (!cache.forImageId[imageId]) {
71896                     cache.forImageId[imageId] = [];
71897                   }
71898
71899                   cache.forImageId[imageId].push({
71900                     geometry: detection.geometry,
71901                     id: detection.id,
71902                     image_id: imageId,
71903                     value: detection.value
71904                   });
71905                 });
71906                 showDetections(_mlyCache.image_detections.forImageId[imageId] || []);
71907               });
71908             } // Create a tag for each detection and shows it in the image viewer
71909
71910
71911             function showDetections(detections) {
71912               var tagComponent = _mlyViewer.getComponent('tag');
71913
71914               detections.forEach(function (data) {
71915                 var tag = makeTag(data);
71916
71917                 if (tag) {
71918                   tagComponent.add([tag]);
71919                 }
71920               });
71921             } // Create a Mapillary JS tag object
71922
71923
71924             function makeTag(data) {
71925               var valueParts = data.value.split('--');
71926               if (!valueParts.length) return;
71927               var tag;
71928               var text;
71929               var color = 0xffffff;
71930
71931               if (_mlyHighlightedDetection === data.id) {
71932                 color = 0xffff00;
71933                 text = valueParts[1];
71934
71935                 if (text === 'flat' || text === 'discrete' || text === 'sign') {
71936                   text = valueParts[2];
71937                 }
71938
71939                 text = text.replace(/-/g, ' ');
71940                 text = text.charAt(0).toUpperCase() + text.slice(1);
71941                 _mlyHighlightedDetection = null;
71942               }
71943
71944               var decodedGeometry = window.atob(data.geometry);
71945               var uintArray = new Uint8Array(decodedGeometry.length);
71946
71947               for (var i = 0; i < decodedGeometry.length; i++) {
71948                 uintArray[i] = decodedGeometry.charCodeAt(i);
71949               }
71950
71951               var tile = new VectorTile(new pbf(uintArray.buffer));
71952               var layer = tile.layers['mpy-or'];
71953               var geometries = layer.feature(0).loadGeometry();
71954               var polygon = geometries.map(function (ring) {
71955                 return ring.map(function (point) {
71956                   return [point.x / layer.extent, point.y / layer.extent];
71957                 });
71958               });
71959               tag = new mapillary.OutlineTag(data.id, new mapillary.PolygonGeometry(polygon[0]), {
71960                 text: text,
71961                 textColor: color,
71962                 lineColor: color,
71963                 lineWidth: 2,
71964                 fillColor: color,
71965                 fillOpacity: 0.3
71966               });
71967               return tag;
71968             }
71969           },
71970           // Return the current cache
71971           cache: function cache() {
71972             return _mlyCache;
71973           }
71974         };
71975
71976         function validationIssue(attrs) {
71977           this.type = attrs.type; // required - name of rule that created the issue (e.g. 'missing_tag')
71978
71979           this.subtype = attrs.subtype; // optional - category of the issue within the type (e.g. 'relation_type' under 'missing_tag')
71980
71981           this.severity = attrs.severity; // required - 'warning' or 'error'
71982
71983           this.message = attrs.message; // required - function returning localized string
71984
71985           this.reference = attrs.reference; // optional - function(selection) to render reference information
71986
71987           this.entityIds = attrs.entityIds; // optional - array of IDs of entities involved in the issue
71988
71989           this.loc = attrs.loc; // optional - [lon, lat] to zoom in on to see the issue
71990
71991           this.data = attrs.data; // optional - object containing extra data for the fixes
71992
71993           this.dynamicFixes = attrs.dynamicFixes; // optional - function(context) returning fixes
71994
71995           this.hash = attrs.hash; // optional - string to further differentiate the issue
71996
71997           this.id = generateID.apply(this); // generated - see below
71998
71999           this.key = generateKey.apply(this); // generated - see below (call after generating this.id)
72000
72001           this.autoFix = null; // generated - if autofix exists, will be set below
72002           // A unique, deterministic string hash.
72003           // Issues with identical id values are considered identical.
72004
72005           function generateID() {
72006             var parts = [this.type];
72007
72008             if (this.hash) {
72009               // subclasses can pass in their own differentiator
72010               parts.push(this.hash);
72011             }
72012
72013             if (this.subtype) {
72014               parts.push(this.subtype);
72015             } // include the entities this issue is for
72016             // (sort them so the id is deterministic)
72017
72018
72019             if (this.entityIds) {
72020               var entityKeys = this.entityIds.slice().sort();
72021               parts.push.apply(parts, entityKeys);
72022             }
72023
72024             return parts.join(':');
72025           } // An identifier suitable for use as the second argument to d3.selection#data().
72026           // (i.e. this should change whenever the data needs to be refreshed)
72027
72028
72029           function generateKey() {
72030             return this.id + ':' + Date.now().toString(); // include time of creation
72031           }
72032
72033           this.extent = function (resolver) {
72034             if (this.loc) {
72035               return geoExtent(this.loc);
72036             }
72037
72038             if (this.entityIds && this.entityIds.length) {
72039               return this.entityIds.reduce(function (extent, entityId) {
72040                 return extent.extend(resolver.entity(entityId).extent(resolver));
72041               }, geoExtent());
72042             }
72043
72044             return null;
72045           };
72046
72047           this.fixes = function (context) {
72048             var fixes = this.dynamicFixes ? this.dynamicFixes(context) : [];
72049             var issue = this;
72050
72051             if (issue.severity === 'warning') {
72052               // allow ignoring any issue that's not an error
72053               fixes.push(new validationIssueFix({
72054                 title: _t.html('issues.fix.ignore_issue.title'),
72055                 icon: 'iD-icon-close',
72056                 onClick: function onClick() {
72057                   context.validator().ignoreIssue(this.issue.id);
72058                 }
72059               }));
72060             }
72061
72062             fixes.forEach(function (fix) {
72063               // the id doesn't matter as long as it's unique to this issue/fix
72064               fix.id = fix.title; // add a reference to the issue for use in actions
72065
72066               fix.issue = issue;
72067
72068               if (fix.autoArgs) {
72069                 issue.autoFix = fix;
72070               }
72071             });
72072             return fixes;
72073           };
72074         }
72075         function validationIssueFix(attrs) {
72076           this.title = attrs.title; // Required
72077
72078           this.onClick = attrs.onClick; // Optional - the function to run to apply the fix
72079
72080           this.disabledReason = attrs.disabledReason; // Optional - a string explaining why the fix is unavailable, if any
72081
72082           this.icon = attrs.icon; // Optional - shows 'iD-icon-wrench' if not set
72083
72084           this.entityIds = attrs.entityIds || []; // Optional - used for hover-higlighting.
72085
72086           this.autoArgs = attrs.autoArgs; // Optional - pass [actions, annotation] arglist if this fix can automatically run
72087
72088           this.issue = null; // Generated link - added by validationIssue
72089         }
72090
72091         var buildRuleChecks = function buildRuleChecks() {
72092           return {
72093             equals: function equals(_equals) {
72094               return function (tags) {
72095                 return Object.keys(_equals).every(function (k) {
72096                   return _equals[k] === tags[k];
72097                 });
72098               };
72099             },
72100             notEquals: function notEquals(_notEquals) {
72101               return function (tags) {
72102                 return Object.keys(_notEquals).some(function (k) {
72103                   return _notEquals[k] !== tags[k];
72104                 });
72105               };
72106             },
72107             absence: function absence(_absence) {
72108               return function (tags) {
72109                 return Object.keys(tags).indexOf(_absence) === -1;
72110               };
72111             },
72112             presence: function presence(_presence) {
72113               return function (tags) {
72114                 return Object.keys(tags).indexOf(_presence) > -1;
72115               };
72116             },
72117             greaterThan: function greaterThan(_greaterThan) {
72118               var key = Object.keys(_greaterThan)[0];
72119               var value = _greaterThan[key];
72120               return function (tags) {
72121                 return tags[key] > value;
72122               };
72123             },
72124             greaterThanEqual: function greaterThanEqual(_greaterThanEqual) {
72125               var key = Object.keys(_greaterThanEqual)[0];
72126               var value = _greaterThanEqual[key];
72127               return function (tags) {
72128                 return tags[key] >= value;
72129               };
72130             },
72131             lessThan: function lessThan(_lessThan) {
72132               var key = Object.keys(_lessThan)[0];
72133               var value = _lessThan[key];
72134               return function (tags) {
72135                 return tags[key] < value;
72136               };
72137             },
72138             lessThanEqual: function lessThanEqual(_lessThanEqual) {
72139               var key = Object.keys(_lessThanEqual)[0];
72140               var value = _lessThanEqual[key];
72141               return function (tags) {
72142                 return tags[key] <= value;
72143               };
72144             },
72145             positiveRegex: function positiveRegex(_positiveRegex) {
72146               var tagKey = Object.keys(_positiveRegex)[0];
72147
72148               var expression = _positiveRegex[tagKey].join('|');
72149
72150               var regex = new RegExp(expression);
72151               return function (tags) {
72152                 return regex.test(tags[tagKey]);
72153               };
72154             },
72155             negativeRegex: function negativeRegex(_negativeRegex) {
72156               var tagKey = Object.keys(_negativeRegex)[0];
72157
72158               var expression = _negativeRegex[tagKey].join('|');
72159
72160               var regex = new RegExp(expression);
72161               return function (tags) {
72162                 return !regex.test(tags[tagKey]);
72163               };
72164             }
72165           };
72166         };
72167
72168         var buildLineKeys = function buildLineKeys() {
72169           return {
72170             highway: {
72171               rest_area: true,
72172               services: true
72173             },
72174             railway: {
72175               roundhouse: true,
72176               station: true,
72177               traverser: true,
72178               turntable: true,
72179               wash: true
72180             }
72181           };
72182         };
72183
72184         var serviceMapRules = {
72185           init: function init() {
72186             this._ruleChecks = buildRuleChecks();
72187             this._validationRules = [];
72188             this._areaKeys = osmAreaKeys;
72189             this._lineKeys = buildLineKeys();
72190           },
72191           // list of rules only relevant to tag checks...
72192           filterRuleChecks: function filterRuleChecks(selector) {
72193             var _ruleChecks = this._ruleChecks;
72194             return Object.keys(selector).reduce(function (rules, key) {
72195               if (['geometry', 'error', 'warning'].indexOf(key) === -1) {
72196                 rules.push(_ruleChecks[key](selector[key]));
72197               }
72198
72199               return rules;
72200             }, []);
72201           },
72202           // builds tagMap from mapcss-parse selector object...
72203           buildTagMap: function buildTagMap(selector) {
72204             var getRegexValues = function getRegexValues(regexes) {
72205               return regexes.map(function (regex) {
72206                 return regex.replace(/\$|\^/g, '');
72207               });
72208             };
72209
72210             var tagMap = Object.keys(selector).reduce(function (expectedTags, key) {
72211               var values;
72212               var isRegex = /regex/gi.test(key);
72213               var isEqual = /equals/gi.test(key);
72214
72215               if (isRegex || isEqual) {
72216                 Object.keys(selector[key]).forEach(function (selectorKey) {
72217                   values = isEqual ? [selector[key][selectorKey]] : getRegexValues(selector[key][selectorKey]);
72218
72219                   if (expectedTags.hasOwnProperty(selectorKey)) {
72220                     values = values.concat(expectedTags[selectorKey]);
72221                   }
72222
72223                   expectedTags[selectorKey] = values;
72224                 });
72225               } else if (/(greater|less)Than(Equal)?|presence/g.test(key)) {
72226                 var tagKey = /presence/.test(key) ? selector[key] : Object.keys(selector[key])[0];
72227                 values = [selector[key][tagKey]];
72228
72229                 if (expectedTags.hasOwnProperty(tagKey)) {
72230                   values = values.concat(expectedTags[tagKey]);
72231                 }
72232
72233                 expectedTags[tagKey] = values;
72234               }
72235
72236               return expectedTags;
72237             }, {});
72238             return tagMap;
72239           },
72240           // inspired by osmWay#isArea()
72241           inferGeometry: function inferGeometry(tagMap) {
72242             var _lineKeys = this._lineKeys;
72243             var _areaKeys = this._areaKeys;
72244
72245             var keyValueDoesNotImplyArea = function keyValueDoesNotImplyArea(key) {
72246               return utilArrayIntersection(tagMap[key], Object.keys(_areaKeys[key])).length > 0;
72247             };
72248
72249             var keyValueImpliesLine = function keyValueImpliesLine(key) {
72250               return utilArrayIntersection(tagMap[key], Object.keys(_lineKeys[key])).length > 0;
72251             };
72252
72253             if (tagMap.hasOwnProperty('area')) {
72254               if (tagMap.area.indexOf('yes') > -1) {
72255                 return 'area';
72256               }
72257
72258               if (tagMap.area.indexOf('no') > -1) {
72259                 return 'line';
72260               }
72261             }
72262
72263             for (var key in tagMap) {
72264               if (key in _areaKeys && !keyValueDoesNotImplyArea(key)) {
72265                 return 'area';
72266               }
72267
72268               if (key in _lineKeys && keyValueImpliesLine(key)) {
72269                 return 'area';
72270               }
72271             }
72272
72273             return 'line';
72274           },
72275           // adds from mapcss-parse selector check...
72276           addRule: function addRule(selector) {
72277             var rule = {
72278               // checks relevant to mapcss-selector
72279               checks: this.filterRuleChecks(selector),
72280               // true if all conditions for a tag error are true..
72281               matches: function matches(entity) {
72282                 return this.checks.every(function (check) {
72283                   return check(entity.tags);
72284                 });
72285               },
72286               // borrowed from Way#isArea()
72287               inferredGeometry: this.inferGeometry(this.buildTagMap(selector), this._areaKeys),
72288               geometryMatches: function geometryMatches(entity, graph) {
72289                 if (entity.type === 'node' || entity.type === 'relation') {
72290                   return selector.geometry === entity.type;
72291                 } else if (entity.type === 'way') {
72292                   return this.inferredGeometry === entity.geometry(graph);
72293                 }
72294               },
72295               // when geometries match and tag matches are present, return a warning...
72296               findIssues: function findIssues(entity, graph, issues) {
72297                 if (this.geometryMatches(entity, graph) && this.matches(entity)) {
72298                   var severity = Object.keys(selector).indexOf('error') > -1 ? 'error' : 'warning';
72299                   var _message = selector[severity];
72300                   issues.push(new validationIssue({
72301                     type: 'maprules',
72302                     severity: severity,
72303                     message: function message() {
72304                       return _message;
72305                     },
72306                     entityIds: [entity.id]
72307                   }));
72308                 }
72309               }
72310             };
72311
72312             this._validationRules.push(rule);
72313           },
72314           clearRules: function clearRules() {
72315             this._validationRules = [];
72316           },
72317           // returns validationRules...
72318           validationRules: function validationRules() {
72319             return this._validationRules;
72320           },
72321           // returns ruleChecks
72322           ruleChecks: function ruleChecks() {
72323             return this._ruleChecks;
72324           }
72325         };
72326
72327         var apibase$2 = 'https://nominatim.openstreetmap.org/';
72328         var _inflight$2 = {};
72329
72330         var _nominatimCache;
72331
72332         var serviceNominatim = {
72333           init: function init() {
72334             _inflight$2 = {};
72335             _nominatimCache = new RBush();
72336           },
72337           reset: function reset() {
72338             Object.values(_inflight$2).forEach(function (controller) {
72339               controller.abort();
72340             });
72341             _inflight$2 = {};
72342             _nominatimCache = new RBush();
72343           },
72344           countryCode: function countryCode(location, callback) {
72345             this.reverse(location, function (err, result) {
72346               if (err) {
72347                 return callback(err);
72348               } else if (result.address) {
72349                 return callback(null, result.address.country_code);
72350               } else {
72351                 return callback('Unable to geocode', null);
72352               }
72353             });
72354           },
72355           reverse: function reverse(loc, callback) {
72356             var cached = _nominatimCache.search({
72357               minX: loc[0],
72358               minY: loc[1],
72359               maxX: loc[0],
72360               maxY: loc[1]
72361             });
72362
72363             if (cached.length > 0) {
72364               if (callback) callback(null, cached[0].data);
72365               return;
72366             }
72367
72368             var params = {
72369               zoom: 13,
72370               format: 'json',
72371               addressdetails: 1,
72372               lat: loc[1],
72373               lon: loc[0]
72374             };
72375             var url = apibase$2 + 'reverse?' + utilQsString(params);
72376             if (_inflight$2[url]) return;
72377             var controller = new AbortController();
72378             _inflight$2[url] = controller;
72379             d3_json(url, {
72380               signal: controller.signal
72381             }).then(function (result) {
72382               delete _inflight$2[url];
72383
72384               if (result && result.error) {
72385                 throw new Error(result.error);
72386               }
72387
72388               var extent = geoExtent(loc).padByMeters(200);
72389
72390               _nominatimCache.insert(Object.assign(extent.bbox(), {
72391                 data: result
72392               }));
72393
72394               if (callback) callback(null, result);
72395             })["catch"](function (err) {
72396               delete _inflight$2[url];
72397               if (err.name === 'AbortError') return;
72398               if (callback) callback(err.message);
72399             });
72400           },
72401           search: function search(val, callback) {
72402             var searchVal = encodeURIComponent(val);
72403             var url = apibase$2 + 'search/' + searchVal + '?limit=10&format=json';
72404             if (_inflight$2[url]) return;
72405             var controller = new AbortController();
72406             _inflight$2[url] = controller;
72407             d3_json(url, {
72408               signal: controller.signal
72409             }).then(function (result) {
72410               delete _inflight$2[url];
72411
72412               if (result && result.error) {
72413                 throw new Error(result.error);
72414               }
72415
72416               if (callback) callback(null, result);
72417             })["catch"](function (err) {
72418               delete _inflight$2[url];
72419               if (err.name === 'AbortError') return;
72420               if (callback) callback(err.message);
72421             });
72422           }
72423         };
72424
72425         // for punction see https://stackoverflow.com/a/21224179
72426
72427         function simplify$1(str) {
72428           if (typeof str !== 'string') return '';
72429           return diacritics.remove(str.replace(/&/g, 'and').replace(/İ/ig, 'i') // for BİM, İşbank - #5017
72430           .replace(/[\s\-=_!"#%'*{},.\/:;?\(\)\[\]@\\$\^*+<>«»~`’\u00a1\u00a7\u00b6\u00b7\u00bf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0af0\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166d\u166e\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cc0-\u1cc7\u1cd3\u2000-\u206f\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00-\u2e7f\u3001-\u3003\u303d\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uaaf0\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a\ufe6b\ufeff\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e\uff0f\uff1a\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65]+/g, '').toLowerCase());
72431         }
72432
72433         var matchGroups$1 = {adult_gaming_centre:["amenity/casino","amenity/gambling","leisure/adult_gaming_centre"],beauty:["shop/beauty","shop/hairdresser_supply"],bed:["shop/bed","shop/furniture"],beverages:["shop/alcohol","shop/beer","shop/beverages","shop/wine"],camping:["leisure/park","tourism/camp_site","tourism/caravan_site"],car_parts:["shop/car_parts","shop/car_repair","shop/tires","shop/tyres"],clinic:["amenity/clinic","amenity/doctors","healthcare/clinic","healthcare/laboratory","healthcare/physiotherapist","healthcare/sample_collection","healthcare/dialysis"],confectionery:["shop/candy","shop/chocolate","shop/confectionery"],convenience:["shop/beauty","shop/chemist","shop/convenience","shop/cosmetics","shop/grocery","shop/newsagent","shop/perfumery"],coworking:["amenity/coworking_space","office/coworking","office/coworking_space"],dentist:["amenity/dentist","amenity/doctors","healthcare/dentist"],electronics:["office/telecommunication","shop/computer","shop/electronics","shop/hifi","shop/mobile","shop/mobile_phone","shop/telecommunication"],fabric:["shop/fabric","shop/haberdashery","shop/sewing"],fashion:["shop/accessories","shop/bag","shop/boutique","shop/clothes","shop/department_store","shop/fashion","shop/fashion_accessories","shop/sports","shop/shoes"],financial:["amenity/bank","office/accountant","office/financial","office/financial_advisor","office/tax_advisor","shop/tax"],fitness:["leisure/fitness_centre","leisure/fitness_center","leisure/sports_centre","leisure/sports_center"],food:["amenity/pub","amenity/bar","amenity/cafe","amenity/fast_food","amenity/ice_cream","amenity/restaurant","shop/bakery","shop/ice_cream","shop/pastry","shop/tea","shop/coffee"],fuel:["amenity/fuel","shop/gas","shop/convenience;gas","shop/gas;convenience"],gift:["shop/gift","shop/card","shop/cards","shop/stationery"],hardware:["shop/bathroom_furnishing","shop/carpet","shop/diy","shop/doityourself","shop/doors","shop/electrical","shop/flooring","shop/hardware","shop/hardware_store","shop/power_tools","shop/tool_hire","shop/tools","shop/trade"],health_food:["shop/health","shop/health_food","shop/herbalist","shop/nutrition_supplements"],hobby:["shop/electronics","shop/hobby","shop/books","shop/games","shop/collector","shop/toys","shop/model","shop/video_games","shop/anime"],hospital:["amenity/doctors","amenity/hospital","healthcare/hospital"],houseware:["shop/houseware","shop/interior_decoration"],lifeboat_station:["amenity/lifeboat_station","emergency/lifeboat_station","emergency/marine_rescue"],lodging:["tourism/hotel","tourism/motel"],money_transfer:["amenity/money_transfer","shop/money_transfer"],office_supplies:["shop/office_supplies","shop/stationary","shop/stationery"],outdoor:["shop/outdoor","shop/sports"],parcel_locker:["amenity/parcel_locker","amenity/vending_machine"],pharmacy:["amenity/doctors","amenity/pharmacy","healthcare/pharmacy"],playground:["amenity/theme_park","leisure/amusement_arcade","leisure/playground"],rental:["amenity/bicycle_rental","amenity/boat_rental","amenity/car_rental","amenity/truck_rental","amenity/vehicle_rental","shop/rental"],school:["amenity/childcare","amenity/college","amenity/kindergarten","amenity/language_school","amenity/prep_school","amenity/school","amenity/university"],storage:["shop/storage_units","shop/storage_rental"],substation:["power/station","power/substation","power/sub_station"],supermarket:["shop/food","shop/frozen_food","shop/greengrocer","shop/grocery","shop/supermarket","shop/wholesale"],variety_store:["shop/variety_store","shop/discount","shop/convenience"],vending:["amenity/vending_machine","shop/vending_machine"],weight_loss:["amenity/clinic","amenity/doctors","amenity/weight_clinic","healthcare/counselling","leisure/fitness_centre","office/therapist","shop/beauty","shop/diet","shop/food","shop/health_food","shop/herbalist","shop/nutrition","shop/nutrition_supplements","shop/weight_loss"],wholesale:["shop/wholesale","shop/supermarket","shop/department_store"]};
72434         var matchGroupsJSON = {
72435         matchGroups: matchGroups$1
72436         };
72437
72438         var genericWords = ["^(barn|bazaa?r|bench|bou?tique|building|casa|church)$","^(baseball|basketball|football|soccer|softball|tennis(halle)?)\\s?(field|court)?$","^(club|green|out|ware)\\s?house$","^(driveway|el árbol|fountain|golf|government|graveyard)$","^(fixme|n\\s?\\/?\\s?a|name|no\\s?name|none|null|temporary|test|unknown)$","^(hofladen|librairie|magazine?|maison)$","^(mobile home|skate)?\\s?park$","^(obuwie|pond|pool|sale|shops?|sklep|stores?)$","^\\?+$","^private$","^tattoo( studio)?$","^windmill$","^церковная( лавка)?$"];
72439         var genericWordsJSON = {
72440         genericWords: genericWords
72441         };
72442
72443         var trees$1 = {brands:{emoji:"🍔",mainTag:"brand:wikidata",sourceTags:["brand","name"],nameTags:{primary:"^(name|name:\\w+)$",alternate:"^(brand|brand:\\w+|operator|operator:\\w+|\\w+_name|\\w+_name:\\w+)$"}},flags:{emoji:"🚩",mainTag:"flag:wikidata",nameTags:{primary:"^(flag:name|flag:name:\\w+)$",alternate:"^(country|country:\\w+|flag|flag:\\w+|subject|subject:\\w+)$"}},operators:{emoji:"💼",mainTag:"operator:wikidata",sourceTags:["operator"],nameTags:{primary:"^(name|name:\\w+|operator|operator:\\w+)$",alternate:"^(brand|brand:\\w+|\\w+_name|\\w+_name:\\w+)$"}},transit:{emoji:"🚇",mainTag:"network:wikidata",sourceTags:["network"],nameTags:{primary:"^network$",alternate:"^(operator|operator:\\w+|network:\\w+|\\w+_name|\\w+_name:\\w+)$"}}};
72444         var treesJSON = {
72445         trees: trees$1
72446         };
72447
72448         var matchGroups = matchGroupsJSON.matchGroups;
72449         var trees = treesJSON.trees;
72450         var Matcher = /*#__PURE__*/function () {
72451           //
72452           // `constructor`
72453           // initialize the genericWords regexes
72454           function Matcher() {
72455             var _this = this;
72456
72457             _classCallCheck$1(this, Matcher);
72458
72459             // The `matchIndex` is a specialized structure that allows us to quickly answer
72460             //   _"Given a [key/value tagpair, name, location], what canonical items (brands etc) can match it?"_
72461             //
72462             // The index contains all valid combinations of k/v tagpairs and names
72463             // matchIndex:
72464             // {
72465             //   'k/v': {
72466             //     'primary':         Map (String 'nsimple' -> Set (itemIDs…),   // matches for tags like `name`, `name:xx`, etc.
72467             //     'alternate':       Map (String 'nsimple' -> Set (itemIDs…),   // matches for tags like `alt_name`, `brand`, etc.
72468             //     'excludeNamed':    Map (String 'pattern' -> RegExp),
72469             //     'excludeGeneric':  Map (String 'pattern' -> RegExp)
72470             //   },
72471             // }
72472             //
72473             // {
72474             //   'amenity/bank': {
72475             //     'primary': {
72476             //       'firstbank':              Set ("firstbank-978cca", "firstbank-9794e6", "firstbank-f17495", …),
72477             //       …
72478             //     },
72479             //     'alternate': {
72480             //       '1stbank':                Set ("firstbank-f17495"),
72481             //       …
72482             //     }
72483             //   },
72484             //   'shop/supermarket': {
72485             //     'primary': {
72486             //       'coop':                   Set ("coop-76454b", "coop-ebf2d9", "coop-36e991", …),
72487             //       'coopfood':               Set ("coopfood-a8278b", …),
72488             //       …
72489             //     },
72490             //     'alternate': {
72491             //       'coop':                   Set ("coopfood-a8278b", …),
72492             //       'federatedcooperatives':  Set ("coop-76454b", …),
72493             //       'thecooperative':         Set ("coopfood-a8278b", …),
72494             //       …
72495             //     }
72496             //   }
72497             // }
72498             //
72499             this.matchIndex = undefined; // The `genericWords` structure matches the contents of genericWords.json to instantiated RegExp objects
72500             // Map (String 'pattern' -> RegExp),
72501
72502             this.genericWords = new Map();
72503             (genericWordsJSON.genericWords || []).forEach(function (s) {
72504               return _this.genericWords.set(s, new RegExp(s, 'i'));
72505             }); // The `itemLocation` structure maps itemIDs to locationSetIDs:
72506             // {
72507             //   'firstbank-f17495':  '+[first_bank_western_us.geojson]',
72508             //   'firstbank-978cca':  '+[first_bank_carolinas.geojson]',
72509             //   'coop-76454b':       '+[Q16]',
72510             //   'coopfood-a8278b':   '+[Q23666]',
72511             //   …
72512             // }
72513
72514             this.itemLocation = undefined; // The `locationSets` structure maps locationSetIDs to *resolved* locationSets:
72515             // {
72516             //   '+[first_bank_western_us.geojson]':  GeoJSON {…},
72517             //   '+[first_bank_carolinas.geojson]':   GeoJSON {…},
72518             //   '+[Q16]':                            GeoJSON {…},
72519             //   '+[Q23666]':                         GeoJSON {…},
72520             //   …
72521             // }
72522
72523             this.locationSets = undefined; // The `locationIndex` is an instance of which-polygon spatial index for the locationSets.
72524
72525             this.locationIndex = undefined; // Array of match conflict pairs (currently unused)
72526
72527             this.warnings = [];
72528           } //
72529           // `buildMatchIndex()`
72530           // Call this to prepare the matcher for use
72531           //
72532           // `data` needs to be an Object indexed on a 'tree/key/value' path.
72533           // (e.g. cache filled by `fileTree.read` or data found in `dist/nsi.json`)
72534           // {
72535           //    'brands/amenity/bank': { properties: {}, items: [ {}, {}, … ] },
72536           //    'brands/amenity/bar':  { properties: {}, items: [ {}, {}, … ] },
72537           //    …
72538           // }
72539           //
72540
72541
72542           _createClass$1(Matcher, [{
72543             key: "buildMatchIndex",
72544             value: function buildMatchIndex(data) {
72545               var that = this;
72546               if (that.matchIndex) return; // it was built already
72547
72548               that.matchIndex = new Map();
72549               var seenTree = new Map(); // warn if the same [k, v, nsimple] appears in multiple trees - #5625
72550
72551               Object.keys(data).forEach(function (tkv) {
72552                 var category = data[tkv];
72553                 var parts = tkv.split('/', 3); // tkv = "tree/key/value"
72554
72555                 var t = parts[0];
72556                 var k = parts[1];
72557                 var v = parts[2];
72558                 var thiskv = "".concat(k, "/").concat(v);
72559                 var tree = trees[t];
72560                 var branch = that.matchIndex.get(thiskv);
72561
72562                 if (!branch) {
72563                   branch = {
72564                     primary: new Map(),
72565                     alternate: new Map(),
72566                     excludeGeneric: new Map(),
72567                     excludeNamed: new Map()
72568                   };
72569                   that.matchIndex.set(thiskv, branch);
72570                 } // ADD EXCLUSIONS
72571
72572
72573                 var properties = category.properties || {};
72574                 var exclude = properties.exclude || {};
72575                 (exclude.generic || []).forEach(function (s) {
72576                   return branch.excludeGeneric.set(s, new RegExp(s, 'i'));
72577                 });
72578                 (exclude.named || []).forEach(function (s) {
72579                   return branch.excludeNamed.set(s, new RegExp(s, 'i'));
72580                 });
72581                 var excludeRegexes = [].concat(_toConsumableArray(branch.excludeGeneric.values()), _toConsumableArray(branch.excludeNamed.values())); // ADD ITEMS
72582
72583                 var items = category.items;
72584                 if (!Array.isArray(items) || !items.length) return; // Primary name patterns, match tags to take first
72585                 //  e.g. `name`, `name:ru`
72586
72587                 var primaryName = new RegExp(tree.nameTags.primary, 'i'); // Alternate name patterns, match tags to consider after primary
72588                 //  e.g. `alt_name`, `short_name`, `brand`, `brand:ru`, etc..
72589
72590                 var alternateName = new RegExp(tree.nameTags.alternate, 'i'); // There are a few exceptions to the name matching regexes.
72591                 // Usually a tag suffix contains a language code like `name:en`, `name:ru`
72592                 // but we want to exclude things like `operator:type`, `name:etymology`, etc..
72593
72594                 var notName = /:(colou?r|type|forward|backward|left|right|etymology|pronunciation|wikipedia)$/i; // For certain categories we do not want to match generic KV pairs like `building/yes` or `amenity/yes`
72595
72596                 var skipGenericKV = skipGenericKVMatches(t, k, v); // We will collect the generic KV pairs anyway (for the purpose of filtering them out of matchTags)
72597
72598                 var genericKV = new Set(["".concat(k, "/yes"), "building/yes"]); // Collect alternate tagpairs for this kv category from matchGroups.
72599                 // We might also pick up a few more generic KVs (like `shop/yes`)
72600
72601                 var matchGroupKV = new Set();
72602                 Object.values(matchGroups).forEach(function (matchGroup) {
72603                   var inGroup = matchGroup.some(function (otherkv) {
72604                     return otherkv === thiskv;
72605                   });
72606                   if (!inGroup) return;
72607                   matchGroup.forEach(function (otherkv) {
72608                     if (otherkv === thiskv) return; // skip self
72609
72610                     matchGroupKV.add(otherkv);
72611                     var otherk = otherkv.split('/', 2)[0]; // we might pick up a `shop/yes`
72612
72613                     genericKV.add("".concat(otherk, "/yes"));
72614                   });
72615                 }); // For each item, insert all [key, value, name] combinations into the match index
72616
72617                 items.forEach(function (item) {
72618                   if (!item.id) return; // Automatically remove redundant `matchTags` - #3417
72619                   // (i.e. This kv is already covered by matchGroups, so it doesn't need to be in `item.matchTags`)
72620
72621                   if (Array.isArray(item.matchTags) && item.matchTags.length) {
72622                     item.matchTags = item.matchTags.filter(function (matchTag) {
72623                       return !matchGroupKV.has(matchTag) && !genericKV.has(matchTag);
72624                     });
72625                     if (!item.matchTags.length) delete item.matchTags;
72626                   } // key/value tagpairs to insert into the match index..
72627
72628
72629                   var kvTags = ["".concat(thiskv)].concat(item.matchTags || []);
72630
72631                   if (!skipGenericKV) {
72632                     kvTags = kvTags.concat(Array.from(genericKV)); // #3454 - match some generic tags
72633                   } // Index all the namelike tag values
72634
72635
72636                   Object.keys(item.tags).forEach(function (osmkey) {
72637                     if (notName.test(osmkey)) return; // osmkey is not a namelike tag, skip
72638
72639                     var osmvalue = item.tags[osmkey];
72640                     if (!osmvalue || excludeRegexes.some(function (regex) {
72641                       return regex.test(osmvalue);
72642                     })) return; // osmvalue missing or excluded
72643
72644                     if (primaryName.test(osmkey)) {
72645                       kvTags.forEach(function (kv) {
72646                         return insertName('primary', t, kv, simplify$1(osmvalue), item.id);
72647                       });
72648                     } else if (alternateName.test(osmkey)) {
72649                       kvTags.forEach(function (kv) {
72650                         return insertName('alternate', t, kv, simplify$1(osmvalue), item.id);
72651                       });
72652                     }
72653                   }); // Index `matchNames` after indexing all other names..
72654
72655                   var keepMatchNames = new Set();
72656                   (item.matchNames || []).forEach(function (matchName) {
72657                     // If this matchname isn't already indexed, add it to the alternate index
72658                     var nsimple = simplify$1(matchName);
72659                     kvTags.forEach(function (kv) {
72660                       var branch = that.matchIndex.get(kv);
72661                       var primaryLeaf = branch && branch.primary.get(nsimple);
72662                       var alternateLeaf = branch && branch.alternate.get(nsimple);
72663                       var inPrimary = primaryLeaf && primaryLeaf.has(item.id);
72664                       var inAlternate = alternateLeaf && alternateLeaf.has(item.id);
72665
72666                       if (!inPrimary && !inAlternate) {
72667                         insertName('alternate', t, kv, nsimple, item.id);
72668                         keepMatchNames.add(matchName);
72669                       }
72670                     });
72671                   }); // Automatically remove redundant `matchNames` - #3417
72672                   // (i.e. This name got indexed some other way, so it doesn't need to be in `item.matchNames`)
72673
72674                   if (keepMatchNames.size) {
72675                     item.matchNames = Array.from(keepMatchNames);
72676                   } else {
72677                     delete item.matchNames;
72678                   }
72679                 }); // each item
72680               }); // each tkv
72681               // Insert this item into the matchIndex
72682
72683               function insertName(which, t, kv, nsimple, itemID) {
72684                 if (!nsimple) {
72685                   that.warnings.push("Warning: skipping empty ".concat(which, " name for item ").concat(t, "/").concat(kv, ": ").concat(itemID));
72686                   return;
72687                 }
72688
72689                 var branch = that.matchIndex.get(kv);
72690
72691                 if (!branch) {
72692                   branch = {
72693                     primary: new Map(),
72694                     alternate: new Map(),
72695                     excludeGeneric: new Map(),
72696                     excludeNamed: new Map()
72697                   };
72698                   that.matchIndex.set(kv, branch);
72699                 }
72700
72701                 var leaf = branch[which].get(nsimple);
72702
72703                 if (!leaf) {
72704                   leaf = new Set();
72705                   branch[which].set(nsimple, leaf);
72706                 }
72707
72708                 leaf.add(itemID); // insert
72709                 // check for duplicates - #5625
72710
72711                 if (!/yes$/.test(kv)) {
72712                   // ignore genericKV like amenity/yes, building/yes, etc
72713                   var kvnsimple = "".concat(kv, "/").concat(nsimple);
72714                   var existing = seenTree.get(kvnsimple);
72715
72716                   if (existing && existing !== t) {
72717                     var items = Array.from(leaf);
72718                     that.warnings.push("Duplicate cache key \"".concat(kvnsimple, "\" in trees \"").concat(t, "\" and \"").concat(existing, "\", check items: ").concat(items));
72719                     return;
72720                   }
72721
72722                   seenTree.set(kvnsimple, t);
72723                 }
72724               } // For certain categories we do not want to match generic KV pairs like `building/yes` or `amenity/yes`
72725
72726
72727               function skipGenericKVMatches(t, k, v) {
72728                 return t === 'flags' || t === 'transit' || k === 'landuse' || v === 'atm' || v === 'bicycle_parking' || v === 'car_sharing' || v === 'caravan_site' || v === 'charging_station' || v === 'dog_park' || v === 'parking' || v === 'phone' || v === 'playground' || v === 'post_box' || v === 'public_bookcase' || v === 'recycling' || v === 'vending_machine';
72729               }
72730             } //
72731             // `buildLocationIndex()`
72732             // Call this to prepare a which-polygon location index.
72733             // This *resolves* all the locationSets into GeoJSON, which takes some time.
72734             // You can skip this step if you don't care about matching within a location.
72735             //
72736             // `data` needs to be an Object indexed on a 'tree/key/value' path.
72737             // (e.g. cache filled by `fileTree.read` or data found in `dist/nsi.json`)
72738             // {
72739             //    'brands/amenity/bank': { properties: {}, items: [ {}, {}, … ] },
72740             //    'brands/amenity/bar':  { properties: {}, items: [ {}, {}, … ] },
72741             //    …
72742             // }
72743             //
72744
72745           }, {
72746             key: "buildLocationIndex",
72747             value: function buildLocationIndex(data, loco) {
72748               var that = this;
72749               if (that.locationIndex) return; // it was built already
72750
72751               that.itemLocation = new Map();
72752               that.locationSets = new Map();
72753               Object.keys(data).forEach(function (tkv) {
72754                 var items = data[tkv].items;
72755                 if (!Array.isArray(items) || !items.length) return;
72756                 items.forEach(function (item) {
72757                   if (that.itemLocation.has(item.id)) return; // we've seen item id already - shouldn't be possible?
72758
72759                   var resolved;
72760
72761                   try {
72762                     resolved = loco.resolveLocationSet(item.locationSet); // resolve a feature for this locationSet
72763                   } catch (err) {
72764                     console.warn("buildLocationIndex: ".concat(err.message)); // couldn't resolve
72765                   }
72766
72767                   if (!resolved || !resolved.id) return;
72768                   that.itemLocation.set(item.id, resolved.id); // link it to the item
72769
72770                   if (that.locationSets.has(resolved.id)) return; // we've seen this locationSet feature before..
72771                   // First time seeing this locationSet feature, make a copy and add to locationSet cache..
72772
72773                   var feature = _cloneDeep(resolved.feature);
72774
72775                   feature.id = resolved.id; // Important: always use the locationSet `id` (`+[Q30]`), not the feature `id` (`Q30`)
72776
72777                   feature.properties.id = resolved.id;
72778
72779                   if (!feature.geometry.coordinates.length || !feature.properties.area) {
72780                     console.warn("buildLocationIndex: locationSet ".concat(resolved.id, " for ").concat(item.id, " resolves to an empty feature:"));
72781                     console.warn(JSON.stringify(feature));
72782                     return;
72783                   }
72784
72785                   that.locationSets.set(resolved.id, feature);
72786                 });
72787               });
72788               that.locationIndex = whichPolygon_1({
72789                 type: 'FeatureCollection',
72790                 features: _toConsumableArray(that.locationSets.values())
72791               });
72792
72793               function _cloneDeep(obj) {
72794                 return JSON.parse(JSON.stringify(obj));
72795               }
72796             } //
72797             // `match()`
72798             // Pass parts and return an Array of matches.
72799             // `k` - key
72800             // `v` - value
72801             // `n` - namelike
72802             // `loc` - optional - [lon,lat] location to search
72803             //
72804             // 1. If the [k,v,n] tuple matches a canonical item…
72805             // Return an Array of match results.
72806             // Each result will include the area in km² that the item is valid.
72807             //
72808             // Order of results:
72809             // Primary ordering will be on the "match" column:
72810             //   "primary" - where the query matches the `name` tag, followed by
72811             //   "alternate" - where the query matches an alternate name tag (e.g. short_name, brand, operator, etc)
72812             // Secondary ordering will be on the "area" column:
72813             //   "area descending" if no location was provided, (worldwide before local)
72814             //   "area ascending" if location was provided (local before worldwide)
72815             //
72816             // [
72817             //   { match: 'primary',   itemID: String,  area: Number,  kv: String,  nsimple: String },
72818             //   { match: 'primary',   itemID: String,  area: Number,  kv: String,  nsimple: String },
72819             //   { match: 'alternate', itemID: String,  area: Number,  kv: String,  nsimple: String },
72820             //   { match: 'alternate', itemID: String,  area: Number,  kv: String,  nsimple: String },
72821             //   …
72822             // ]
72823             //
72824             // -or-
72825             //
72826             // 2. If the [k,v,n] tuple matches an exclude pattern…
72827             // Return an Array with a single exclude result, either
72828             //
72829             // [ { match: 'excludeGeneric', pattern: String,  kv: String } ]  // "generic" e.g. "Food Court"
72830             //   or
72831             // [ { match: 'excludeNamed', pattern: String,  kv: String } ]    // "named", e.g. "Kebabai"
72832             //
72833             // About results
72834             //   "generic" - a generic word that is probably not really a name.
72835             //     For these, iD should warn the user "Hey don't put 'food court' in the name tag".
72836             //   "named" - a real name like "Kebabai" that is just common, but not a brand.
72837             //     For these, iD should just let it be. We don't include these in NSI, but we don't want to nag users about it either.
72838             //
72839             // -or-
72840             //
72841             // 3. If the [k,v,n] tuple matches nothing of any kind, return `null`
72842             //
72843             //
72844
72845           }, {
72846             key: "match",
72847             value: function match(k, v, n, loc) {
72848               var that = this;
72849
72850               if (!that.matchIndex) {
72851                 throw new Error('match:  matchIndex not built.');
72852               } // If we were supplied a location, and a that.locationIndex has been set up,
72853               // get the locationSets that are valid there so we can filter results.
72854
72855
72856               var matchLocations;
72857
72858               if (Array.isArray(loc) && that.locationIndex) {
72859                 // which-polygon query returns an array of GeoJSON properties, pass true to return all results
72860                 matchLocations = that.locationIndex([loc[0], loc[1], loc[0], loc[1]], true);
72861               }
72862
72863               var nsimple = simplify$1(n);
72864               var seen = new Set();
72865               var results = [];
72866               gatherResults('primary');
72867               gatherResults('alternate');
72868               if (results.length) return results;
72869               gatherResults('exclude');
72870               return results.length ? results : null;
72871
72872               function gatherResults(which) {
72873                 // First try an exact match on k/v
72874                 var kv = "".concat(k, "/").concat(v);
72875                 var didMatch = tryMatch(which, kv);
72876                 if (didMatch) return; // If that didn't work, look in match groups for other pairs considered equivalent to k/v..
72877
72878                 for (var mg in matchGroups) {
72879                   var matchGroup = matchGroups[mg];
72880                   var inGroup = matchGroup.some(function (otherkv) {
72881                     return otherkv === kv;
72882                   });
72883                   if (!inGroup) continue;
72884
72885                   for (var i = 0; i < matchGroup.length; i++) {
72886                     var otherkv = matchGroup[i];
72887                     if (otherkv === kv) continue; // skip self
72888
72889                     didMatch = tryMatch(which, otherkv);
72890                     if (didMatch) return;
72891                   }
72892                 } // If finished 'exclude' pass and still haven't matched anything, try the global `genericWords.json` patterns
72893
72894
72895                 if (which === 'exclude') {
72896                   var regex = _toConsumableArray(that.genericWords.values()).find(function (regex) {
72897                     return regex.test(n);
72898                   });
72899
72900                   if (regex) {
72901                     results.push({
72902                       match: 'excludeGeneric',
72903                       pattern: String(regex)
72904                     }); // note no `branch`, no `kv`
72905
72906                     return;
72907                   }
72908                 }
72909               }
72910
72911               function tryMatch(which, kv) {
72912                 var branch = that.matchIndex.get(kv);
72913                 if (!branch) return;
72914
72915                 if (which === 'exclude') {
72916                   // Test name `n` against named and generic exclude patterns
72917                   var regex = _toConsumableArray(branch.excludeNamed.values()).find(function (regex) {
72918                     return regex.test(n);
72919                   });
72920
72921                   if (regex) {
72922                     results.push({
72923                       match: 'excludeNamed',
72924                       pattern: String(regex),
72925                       kv: kv
72926                     });
72927                     return;
72928                   }
72929
72930                   regex = _toConsumableArray(branch.excludeGeneric.values()).find(function (regex) {
72931                     return regex.test(n);
72932                   });
72933
72934                   if (regex) {
72935                     results.push({
72936                       match: 'excludeGeneric',
72937                       pattern: String(regex),
72938                       kv: kv
72939                     });
72940                     return;
72941                   }
72942
72943                   return;
72944                 }
72945
72946                 var leaf = branch[which].get(nsimple);
72947                 if (!leaf || !leaf.size) return; // If we get here, we matched something..
72948                 // Prepare the results, calculate areas (if location index was set up)
72949
72950                 var hits = Array.from(leaf).map(function (itemID) {
72951                   var area = Infinity;
72952
72953                   if (that.itemLocation && that.locationSets) {
72954                     var location = that.locationSets.get(that.itemLocation.get(itemID));
72955                     area = location && location.properties.area || Infinity;
72956                   }
72957
72958                   return {
72959                     match: which,
72960                     itemID: itemID,
72961                     area: area,
72962                     kv: kv,
72963                     nsimple: nsimple
72964                   };
72965                 });
72966                 var sortFn = byAreaDescending; // Filter the match to include only results valid in the requested `loc`..
72967
72968                 if (matchLocations) {
72969                   hits = hits.filter(isValidLocation);
72970                   sortFn = byAreaAscending;
72971                 }
72972
72973                 if (!hits.length) return; // push results
72974
72975                 hits.sort(sortFn).forEach(function (hit) {
72976                   if (seen.has(hit.itemID)) return;
72977                   seen.add(hit.itemID);
72978                   results.push(hit);
72979                 });
72980                 return true;
72981
72982                 function isValidLocation(hit) {
72983                   if (!that.itemLocation) return true;
72984                   return matchLocations.find(function (props) {
72985                     return props.id === that.itemLocation.get(hit.itemID);
72986                   });
72987                 } // Sort smaller (more local) locations first.
72988
72989
72990                 function byAreaAscending(hitA, hitB) {
72991                   return hitA.area - hitB.area;
72992                 } // Sort larger (more worldwide) locations first.
72993
72994
72995                 function byAreaDescending(hitA, hitB) {
72996                   return hitB.area - hitA.area;
72997                 }
72998               }
72999             } //
73000             // `getWarnings()`
73001             // Return any warnings discovered when buiding the index.
73002             // (currently this does nothing)
73003             //
73004
73005           }, {
73006             key: "getWarnings",
73007             value: function getWarnings() {
73008               return this.warnings;
73009             }
73010           }]);
73011
73012           return Matcher;
73013         }();
73014
73015         /*
73016             iD.coreDifference represents the difference between two graphs.
73017             It knows how to calculate the set of entities that were
73018             created, modified, or deleted, and also contains the logic
73019             for recursively extending a difference to the complete set
73020             of entities that will require a redraw, taking into account
73021             child and parent relationships.
73022          */
73023
73024         function coreDifference(base, head) {
73025           var _changes = {};
73026           var _didChange = {}; // 'addition', 'deletion', 'geometry', 'properties'
73027
73028           var _diff = {};
73029
73030           function checkEntityID(id) {
73031             var h = head.entities[id];
73032             var b = base.entities[id];
73033             if (h === b) return;
73034             if (_changes[id]) return;
73035
73036             if (!h && b) {
73037               _changes[id] = {
73038                 base: b,
73039                 head: h
73040               };
73041               _didChange.deletion = true;
73042               return;
73043             }
73044
73045             if (h && !b) {
73046               _changes[id] = {
73047                 base: b,
73048                 head: h
73049               };
73050               _didChange.addition = true;
73051               return;
73052             }
73053
73054             if (h && b) {
73055               if (h.members && b.members && !fastDeepEqual(h.members, b.members)) {
73056                 _changes[id] = {
73057                   base: b,
73058                   head: h
73059                 };
73060                 _didChange.geometry = true;
73061                 _didChange.properties = true;
73062                 return;
73063               }
73064
73065               if (h.loc && b.loc && !geoVecEqual(h.loc, b.loc)) {
73066                 _changes[id] = {
73067                   base: b,
73068                   head: h
73069                 };
73070                 _didChange.geometry = true;
73071               }
73072
73073               if (h.nodes && b.nodes && !fastDeepEqual(h.nodes, b.nodes)) {
73074                 _changes[id] = {
73075                   base: b,
73076                   head: h
73077                 };
73078                 _didChange.geometry = true;
73079               }
73080
73081               if (h.tags && b.tags && !fastDeepEqual(h.tags, b.tags)) {
73082                 _changes[id] = {
73083                   base: b,
73084                   head: h
73085                 };
73086                 _didChange.properties = true;
73087               }
73088             }
73089           }
73090
73091           function load() {
73092             // HOT CODE: there can be many thousands of downloaded entities, so looping
73093             // through them all can become a performance bottleneck. Optimize by
73094             // resolving duplicates and using a basic `for` loop
73095             var ids = utilArrayUniq(Object.keys(head.entities).concat(Object.keys(base.entities)));
73096
73097             for (var i = 0; i < ids.length; i++) {
73098               checkEntityID(ids[i]);
73099             }
73100           }
73101
73102           load();
73103
73104           _diff.length = function length() {
73105             return Object.keys(_changes).length;
73106           };
73107
73108           _diff.changes = function changes() {
73109             return _changes;
73110           };
73111
73112           _diff.didChange = _didChange; // pass true to include affected relation members
73113
73114           _diff.extantIDs = function extantIDs(includeRelMembers) {
73115             var result = new Set();
73116             Object.keys(_changes).forEach(function (id) {
73117               if (_changes[id].head) {
73118                 result.add(id);
73119               }
73120
73121               var h = _changes[id].head;
73122               var b = _changes[id].base;
73123               var entity = h || b;
73124
73125               if (includeRelMembers && entity.type === 'relation') {
73126                 var mh = h ? h.members.map(function (m) {
73127                   return m.id;
73128                 }) : [];
73129                 var mb = b ? b.members.map(function (m) {
73130                   return m.id;
73131                 }) : [];
73132                 utilArrayUnion(mh, mb).forEach(function (memberID) {
73133                   if (head.hasEntity(memberID)) {
73134                     result.add(memberID);
73135                   }
73136                 });
73137               }
73138             });
73139             return Array.from(result);
73140           };
73141
73142           _diff.modified = function modified() {
73143             var result = [];
73144             Object.values(_changes).forEach(function (change) {
73145               if (change.base && change.head) {
73146                 result.push(change.head);
73147               }
73148             });
73149             return result;
73150           };
73151
73152           _diff.created = function created() {
73153             var result = [];
73154             Object.values(_changes).forEach(function (change) {
73155               if (!change.base && change.head) {
73156                 result.push(change.head);
73157               }
73158             });
73159             return result;
73160           };
73161
73162           _diff.deleted = function deleted() {
73163             var result = [];
73164             Object.values(_changes).forEach(function (change) {
73165               if (change.base && !change.head) {
73166                 result.push(change.base);
73167               }
73168             });
73169             return result;
73170           };
73171
73172           _diff.summary = function summary() {
73173             var relevant = {};
73174             var keys = Object.keys(_changes);
73175
73176             for (var i = 0; i < keys.length; i++) {
73177               var change = _changes[keys[i]];
73178
73179               if (change.head && change.head.geometry(head) !== 'vertex') {
73180                 addEntity(change.head, head, change.base ? 'modified' : 'created');
73181               } else if (change.base && change.base.geometry(base) !== 'vertex') {
73182                 addEntity(change.base, base, 'deleted');
73183               } else if (change.base && change.head) {
73184                 // modified vertex
73185                 var moved = !fastDeepEqual(change.base.loc, change.head.loc);
73186                 var retagged = !fastDeepEqual(change.base.tags, change.head.tags);
73187
73188                 if (moved) {
73189                   addParents(change.head);
73190                 }
73191
73192                 if (retagged || moved && change.head.hasInterestingTags()) {
73193                   addEntity(change.head, head, 'modified');
73194                 }
73195               } else if (change.head && change.head.hasInterestingTags()) {
73196                 // created vertex
73197                 addEntity(change.head, head, 'created');
73198               } else if (change.base && change.base.hasInterestingTags()) {
73199                 // deleted vertex
73200                 addEntity(change.base, base, 'deleted');
73201               }
73202             }
73203
73204             return Object.values(relevant);
73205
73206             function addEntity(entity, graph, changeType) {
73207               relevant[entity.id] = {
73208                 entity: entity,
73209                 graph: graph,
73210                 changeType: changeType
73211               };
73212             }
73213
73214             function addParents(entity) {
73215               var parents = head.parentWays(entity);
73216
73217               for (var j = parents.length - 1; j >= 0; j--) {
73218                 var parent = parents[j];
73219
73220                 if (!(parent.id in relevant)) {
73221                   addEntity(parent, head, 'modified');
73222                 }
73223               }
73224             }
73225           }; // returns complete set of entities that require a redraw
73226           //  (optionally within given `extent`)
73227
73228
73229           _diff.complete = function complete(extent) {
73230             var result = {};
73231             var id, change;
73232
73233             for (id in _changes) {
73234               change = _changes[id];
73235               var h = change.head;
73236               var b = change.base;
73237               var entity = h || b;
73238               var i;
73239
73240               if (extent && (!h || !h.intersects(extent, head)) && (!b || !b.intersects(extent, base))) {
73241                 continue;
73242               }
73243
73244               result[id] = h;
73245
73246               if (entity.type === 'way') {
73247                 var nh = h ? h.nodes : [];
73248                 var nb = b ? b.nodes : [];
73249                 var diff;
73250                 diff = utilArrayDifference(nh, nb);
73251
73252                 for (i = 0; i < diff.length; i++) {
73253                   result[diff[i]] = head.hasEntity(diff[i]);
73254                 }
73255
73256                 diff = utilArrayDifference(nb, nh);
73257
73258                 for (i = 0; i < diff.length; i++) {
73259                   result[diff[i]] = head.hasEntity(diff[i]);
73260                 }
73261               }
73262
73263               if (entity.type === 'relation' && entity.isMultipolygon()) {
73264                 var mh = h ? h.members.map(function (m) {
73265                   return m.id;
73266                 }) : [];
73267                 var mb = b ? b.members.map(function (m) {
73268                   return m.id;
73269                 }) : [];
73270                 var ids = utilArrayUnion(mh, mb);
73271
73272                 for (i = 0; i < ids.length; i++) {
73273                   var member = head.hasEntity(ids[i]);
73274                   if (!member) continue; // not downloaded
73275
73276                   if (extent && !member.intersects(extent, head)) continue; // not visible
73277
73278                   result[ids[i]] = member;
73279                 }
73280               }
73281
73282               addParents(head.parentWays(entity), result);
73283               addParents(head.parentRelations(entity), result);
73284             }
73285
73286             return result;
73287
73288             function addParents(parents, result) {
73289               for (var i = 0; i < parents.length; i++) {
73290                 var parent = parents[i];
73291                 if (parent.id in result) continue;
73292                 result[parent.id] = parent;
73293                 addParents(head.parentRelations(parent), result);
73294               }
73295             }
73296           };
73297
73298           return _diff;
73299         }
73300
73301         function coreTree(head) {
73302           // tree for entities
73303           var _rtree = new RBush();
73304
73305           var _bboxes = {}; // maintain a separate tree for granular way segments
73306
73307           var _segmentsRTree = new RBush();
73308
73309           var _segmentsBBoxes = {};
73310           var _segmentsByWayId = {};
73311           var tree = {};
73312
73313           function entityBBox(entity) {
73314             var bbox = entity.extent(head).bbox();
73315             bbox.id = entity.id;
73316             _bboxes[entity.id] = bbox;
73317             return bbox;
73318           }
73319
73320           function segmentBBox(segment) {
73321             var extent = segment.extent(head); // extent can be null if the node entities aren't in the graph for some reason
73322
73323             if (!extent) return null;
73324             var bbox = extent.bbox();
73325             bbox.segment = segment;
73326             _segmentsBBoxes[segment.id] = bbox;
73327             return bbox;
73328           }
73329
73330           function removeEntity(entity) {
73331             _rtree.remove(_bboxes[entity.id]);
73332
73333             delete _bboxes[entity.id];
73334
73335             if (_segmentsByWayId[entity.id]) {
73336               _segmentsByWayId[entity.id].forEach(function (segment) {
73337                 _segmentsRTree.remove(_segmentsBBoxes[segment.id]);
73338
73339                 delete _segmentsBBoxes[segment.id];
73340               });
73341
73342               delete _segmentsByWayId[entity.id];
73343             }
73344           }
73345
73346           function loadEntities(entities) {
73347             _rtree.load(entities.map(entityBBox));
73348
73349             var segments = [];
73350             entities.forEach(function (entity) {
73351               if (entity.segments) {
73352                 var entitySegments = entity.segments(head); // cache these to make them easy to remove later
73353
73354                 _segmentsByWayId[entity.id] = entitySegments;
73355                 segments = segments.concat(entitySegments);
73356               }
73357             });
73358             if (segments.length) _segmentsRTree.load(segments.map(segmentBBox).filter(Boolean));
73359           }
73360
73361           function updateParents(entity, insertions, memo) {
73362             head.parentWays(entity).forEach(function (way) {
73363               if (_bboxes[way.id]) {
73364                 removeEntity(way);
73365                 insertions[way.id] = way;
73366               }
73367
73368               updateParents(way, insertions, memo);
73369             });
73370             head.parentRelations(entity).forEach(function (relation) {
73371               if (memo[entity.id]) return;
73372               memo[entity.id] = true;
73373
73374               if (_bboxes[relation.id]) {
73375                 removeEntity(relation);
73376                 insertions[relation.id] = relation;
73377               }
73378
73379               updateParents(relation, insertions, memo);
73380             });
73381           }
73382
73383           tree.rebase = function (entities, force) {
73384             var insertions = {};
73385
73386             for (var i = 0; i < entities.length; i++) {
73387               var entity = entities[i];
73388               if (!entity.visible) continue;
73389
73390               if (head.entities.hasOwnProperty(entity.id) || _bboxes[entity.id]) {
73391                 if (!force) {
73392                   continue;
73393                 } else if (_bboxes[entity.id]) {
73394                   removeEntity(entity);
73395                 }
73396               }
73397
73398               insertions[entity.id] = entity;
73399               updateParents(entity, insertions, {});
73400             }
73401
73402             loadEntities(Object.values(insertions));
73403             return tree;
73404           };
73405
73406           function updateToGraph(graph) {
73407             if (graph === head) return;
73408             var diff = coreDifference(head, graph);
73409             head = graph;
73410             var changed = diff.didChange;
73411             if (!changed.addition && !changed.deletion && !changed.geometry) return;
73412             var insertions = {};
73413
73414             if (changed.deletion) {
73415               diff.deleted().forEach(function (entity) {
73416                 removeEntity(entity);
73417               });
73418             }
73419
73420             if (changed.geometry) {
73421               diff.modified().forEach(function (entity) {
73422                 removeEntity(entity);
73423                 insertions[entity.id] = entity;
73424                 updateParents(entity, insertions, {});
73425               });
73426             }
73427
73428             if (changed.addition) {
73429               diff.created().forEach(function (entity) {
73430                 insertions[entity.id] = entity;
73431               });
73432             }
73433
73434             loadEntities(Object.values(insertions));
73435           } // returns an array of entities with bounding boxes overlapping `extent` for the given `graph`
73436
73437
73438           tree.intersects = function (extent, graph) {
73439             updateToGraph(graph);
73440             return _rtree.search(extent.bbox()).map(function (bbox) {
73441               return graph.entity(bbox.id);
73442             });
73443           }; // returns an array of segment objects with bounding boxes overlapping `extent` for the given `graph`
73444
73445
73446           tree.waySegments = function (extent, graph) {
73447             updateToGraph(graph);
73448             return _segmentsRTree.search(extent.bbox()).map(function (bbox) {
73449               return bbox.segment;
73450             });
73451           };
73452
73453           return tree;
73454         }
73455
73456         function svgIcon(name, svgklass, useklass) {
73457           return function drawIcon(selection) {
73458             selection.selectAll('svg.icon' + (svgklass ? '.' + svgklass.split(' ')[0] : '')).data([0]).enter().append('svg').attr('class', 'icon ' + (svgklass || '')).append('use').attr('xlink:href', name).attr('class', useklass);
73459           };
73460         }
73461
73462         function uiModal(selection, blocking) {
73463           var _this = this;
73464
73465           var keybinding = utilKeybinding('modal');
73466           var previous = selection.select('div.modal');
73467           var animate = previous.empty();
73468           previous.transition().duration(200).style('opacity', 0).remove();
73469           var shaded = selection.append('div').attr('class', 'shaded').style('opacity', 0);
73470
73471           shaded.close = function () {
73472             shaded.transition().duration(200).style('opacity', 0).remove();
73473             modal.transition().duration(200).style('top', '0px');
73474             select(document).call(keybinding.unbind);
73475           };
73476
73477           var modal = shaded.append('div').attr('class', 'modal fillL');
73478           modal.append('input').attr('class', 'keytrap keytrap-first').on('focus.keytrap', moveFocusToLast);
73479
73480           if (!blocking) {
73481             shaded.on('click.remove-modal', function (d3_event) {
73482               if (d3_event.target === _this) {
73483                 shaded.close();
73484               }
73485             });
73486             modal.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', shaded.close).call(svgIcon('#iD-icon-close'));
73487             keybinding.on('⌫', shaded.close).on('⎋', shaded.close);
73488             select(document).call(keybinding);
73489           }
73490
73491           modal.append('div').attr('class', 'content');
73492           modal.append('input').attr('class', 'keytrap keytrap-last').on('focus.keytrap', moveFocusToFirst);
73493
73494           if (animate) {
73495             shaded.transition().style('opacity', 1);
73496           } else {
73497             shaded.style('opacity', 1);
73498           }
73499
73500           return shaded;
73501
73502           function moveFocusToFirst() {
73503             var node = modal // there are additional rules about what's focusable, but this suits our purposes
73504             .select('a, button, input:not(.keytrap), select, textarea').node();
73505
73506             if (node) {
73507               node.focus();
73508             } else {
73509               select(this).node().blur();
73510             }
73511           }
73512
73513           function moveFocusToLast() {
73514             var nodes = modal.selectAll('a, button, input:not(.keytrap), select, textarea').nodes();
73515
73516             if (nodes.length) {
73517               nodes[nodes.length - 1].focus();
73518             } else {
73519               select(this).node().blur();
73520             }
73521           }
73522         }
73523
73524         function uiLoading(context) {
73525           var _modalSelection = select(null);
73526
73527           var _message = '';
73528           var _blocking = false;
73529
73530           var loading = function loading(selection) {
73531             _modalSelection = uiModal(selection, _blocking);
73532
73533             var loadertext = _modalSelection.select('.content').classed('loading-modal', true).append('div').attr('class', 'modal-section fillL');
73534
73535             loadertext.append('img').attr('class', 'loader').attr('src', context.imagePath('loader-white.gif'));
73536             loadertext.append('h3').html(_message);
73537
73538             _modalSelection.select('button.close').attr('class', 'hide');
73539
73540             return loading;
73541           };
73542
73543           loading.message = function (val) {
73544             if (!arguments.length) return _message;
73545             _message = val;
73546             return loading;
73547           };
73548
73549           loading.blocking = function (val) {
73550             if (!arguments.length) return _blocking;
73551             _blocking = val;
73552             return loading;
73553           };
73554
73555           loading.close = function () {
73556             _modalSelection.remove();
73557           };
73558
73559           loading.isShown = function () {
73560             return _modalSelection && !_modalSelection.empty() && _modalSelection.node().parentNode;
73561           };
73562
73563           return loading;
73564         }
73565
73566         function coreHistory(context) {
73567           var dispatch = dispatch$8('reset', 'change', 'merge', 'restore', 'undone', 'redone', 'storage_error');
73568
73569           var _lock = utilSessionMutex('lock'); // restorable if iD not open in another window/tab and a saved history exists in localStorage
73570
73571
73572           var _hasUnresolvedRestorableChanges = _lock.lock() && !!corePreferences(getKey('saved_history'));
73573
73574           var duration = 150;
73575           var _imageryUsed = [];
73576           var _photoOverlaysUsed = [];
73577           var _checkpoints = {};
73578
73579           var _pausedGraph;
73580
73581           var _stack;
73582
73583           var _index;
73584
73585           var _tree; // internal _act, accepts list of actions and eased time
73586
73587
73588           function _act(actions, t) {
73589             actions = Array.prototype.slice.call(actions);
73590             var annotation;
73591
73592             if (typeof actions[actions.length - 1] !== 'function') {
73593               annotation = actions.pop();
73594             }
73595
73596             var graph = _stack[_index].graph;
73597
73598             for (var i = 0; i < actions.length; i++) {
73599               graph = actions[i](graph, t);
73600             }
73601
73602             return {
73603               graph: graph,
73604               annotation: annotation,
73605               imageryUsed: _imageryUsed,
73606               photoOverlaysUsed: _photoOverlaysUsed,
73607               transform: context.projection.transform(),
73608               selectedIDs: context.selectedIDs()
73609             };
73610           } // internal _perform with eased time
73611
73612
73613           function _perform(args, t) {
73614             var previous = _stack[_index].graph;
73615             _stack = _stack.slice(0, _index + 1);
73616
73617             var actionResult = _act(args, t);
73618
73619             _stack.push(actionResult);
73620
73621             _index++;
73622             return change(previous);
73623           } // internal _replace with eased time
73624
73625
73626           function _replace(args, t) {
73627             var previous = _stack[_index].graph; // assert(_index == _stack.length - 1)
73628
73629             var actionResult = _act(args, t);
73630
73631             _stack[_index] = actionResult;
73632             return change(previous);
73633           } // internal _overwrite with eased time
73634
73635
73636           function _overwrite(args, t) {
73637             var previous = _stack[_index].graph;
73638
73639             if (_index > 0) {
73640               _index--;
73641
73642               _stack.pop();
73643             }
73644
73645             _stack = _stack.slice(0, _index + 1);
73646
73647             var actionResult = _act(args, t);
73648
73649             _stack.push(actionResult);
73650
73651             _index++;
73652             return change(previous);
73653           } // determine difference and dispatch a change event
73654
73655
73656           function change(previous) {
73657             var difference = coreDifference(previous, history.graph());
73658
73659             if (!_pausedGraph) {
73660               dispatch.call('change', this, difference);
73661             }
73662
73663             return difference;
73664           } // iD uses namespaced keys so multiple installations do not conflict
73665
73666
73667           function getKey(n) {
73668             return 'iD_' + window.location.origin + '_' + n;
73669           }
73670
73671           var history = {
73672             graph: function graph() {
73673               return _stack[_index].graph;
73674             },
73675             tree: function tree() {
73676               return _tree;
73677             },
73678             base: function base() {
73679               return _stack[0].graph;
73680             },
73681             merge: function merge(entities
73682             /*, extent*/
73683             ) {
73684               var stack = _stack.map(function (state) {
73685                 return state.graph;
73686               });
73687
73688               _stack[0].graph.rebase(entities, stack, false);
73689
73690               _tree.rebase(entities, false);
73691
73692               dispatch.call('merge', this, entities);
73693             },
73694             perform: function perform() {
73695               // complete any transition already in progress
73696               select(document).interrupt('history.perform');
73697               var transitionable = false;
73698               var action0 = arguments[0];
73699
73700               if (arguments.length === 1 || arguments.length === 2 && typeof arguments[1] !== 'function') {
73701                 transitionable = !!action0.transitionable;
73702               }
73703
73704               if (transitionable) {
73705                 var origArguments = arguments;
73706                 select(document).transition('history.perform').duration(duration).ease(linear$1).tween('history.tween', function () {
73707                   return function (t) {
73708                     if (t < 1) _overwrite([action0], t);
73709                   };
73710                 }).on('start', function () {
73711                   _perform([action0], 0);
73712                 }).on('end interrupt', function () {
73713                   _overwrite(origArguments, 1);
73714                 });
73715               } else {
73716                 return _perform(arguments);
73717               }
73718             },
73719             replace: function replace() {
73720               select(document).interrupt('history.perform');
73721               return _replace(arguments, 1);
73722             },
73723             // Same as calling pop and then perform
73724             overwrite: function overwrite() {
73725               select(document).interrupt('history.perform');
73726               return _overwrite(arguments, 1);
73727             },
73728             pop: function pop(n) {
73729               select(document).interrupt('history.perform');
73730               var previous = _stack[_index].graph;
73731
73732               if (isNaN(+n) || +n < 0) {
73733                 n = 1;
73734               }
73735
73736               while (n-- > 0 && _index > 0) {
73737                 _index--;
73738
73739                 _stack.pop();
73740               }
73741
73742               return change(previous);
73743             },
73744             // Back to the previous annotated state or _index = 0.
73745             undo: function undo() {
73746               select(document).interrupt('history.perform');
73747               var previousStack = _stack[_index];
73748               var previous = previousStack.graph;
73749
73750               while (_index > 0) {
73751                 _index--;
73752                 if (_stack[_index].annotation) break;
73753               }
73754
73755               dispatch.call('undone', this, _stack[_index], previousStack);
73756               return change(previous);
73757             },
73758             // Forward to the next annotated state.
73759             redo: function redo() {
73760               select(document).interrupt('history.perform');
73761               var previousStack = _stack[_index];
73762               var previous = previousStack.graph;
73763               var tryIndex = _index;
73764
73765               while (tryIndex < _stack.length - 1) {
73766                 tryIndex++;
73767
73768                 if (_stack[tryIndex].annotation) {
73769                   _index = tryIndex;
73770                   dispatch.call('redone', this, _stack[_index], previousStack);
73771                   break;
73772                 }
73773               }
73774
73775               return change(previous);
73776             },
73777             pauseChangeDispatch: function pauseChangeDispatch() {
73778               if (!_pausedGraph) {
73779                 _pausedGraph = _stack[_index].graph;
73780               }
73781             },
73782             resumeChangeDispatch: function resumeChangeDispatch() {
73783               if (_pausedGraph) {
73784                 var previous = _pausedGraph;
73785                 _pausedGraph = null;
73786                 return change(previous);
73787               }
73788             },
73789             undoAnnotation: function undoAnnotation() {
73790               var i = _index;
73791
73792               while (i >= 0) {
73793                 if (_stack[i].annotation) return _stack[i].annotation;
73794                 i--;
73795               }
73796             },
73797             redoAnnotation: function redoAnnotation() {
73798               var i = _index + 1;
73799
73800               while (i <= _stack.length - 1) {
73801                 if (_stack[i].annotation) return _stack[i].annotation;
73802                 i++;
73803               }
73804             },
73805             // Returns the entities from the active graph with bounding boxes
73806             // overlapping the given `extent`.
73807             intersects: function intersects(extent) {
73808               return _tree.intersects(extent, _stack[_index].graph);
73809             },
73810             difference: function difference() {
73811               var base = _stack[0].graph;
73812               var head = _stack[_index].graph;
73813               return coreDifference(base, head);
73814             },
73815             changes: function changes(action) {
73816               var base = _stack[0].graph;
73817               var head = _stack[_index].graph;
73818
73819               if (action) {
73820                 head = action(head);
73821               }
73822
73823               var difference = coreDifference(base, head);
73824               return {
73825                 modified: difference.modified(),
73826                 created: difference.created(),
73827                 deleted: difference.deleted()
73828               };
73829             },
73830             hasChanges: function hasChanges() {
73831               return this.difference().length() > 0;
73832             },
73833             imageryUsed: function imageryUsed(sources) {
73834               if (sources) {
73835                 _imageryUsed = sources;
73836                 return history;
73837               } else {
73838                 var s = new Set();
73839
73840                 _stack.slice(1, _index + 1).forEach(function (state) {
73841                   state.imageryUsed.forEach(function (source) {
73842                     if (source !== 'Custom') {
73843                       s.add(source);
73844                     }
73845                   });
73846                 });
73847
73848                 return Array.from(s);
73849               }
73850             },
73851             photoOverlaysUsed: function photoOverlaysUsed(sources) {
73852               if (sources) {
73853                 _photoOverlaysUsed = sources;
73854                 return history;
73855               } else {
73856                 var s = new Set();
73857
73858                 _stack.slice(1, _index + 1).forEach(function (state) {
73859                   if (state.photoOverlaysUsed && Array.isArray(state.photoOverlaysUsed)) {
73860                     state.photoOverlaysUsed.forEach(function (photoOverlay) {
73861                       s.add(photoOverlay);
73862                     });
73863                   }
73864                 });
73865
73866                 return Array.from(s);
73867               }
73868             },
73869             // save the current history state
73870             checkpoint: function checkpoint(key) {
73871               _checkpoints[key] = {
73872                 stack: _stack,
73873                 index: _index
73874               };
73875               return history;
73876             },
73877             // restore history state to a given checkpoint or reset completely
73878             reset: function reset(key) {
73879               if (key !== undefined && _checkpoints.hasOwnProperty(key)) {
73880                 _stack = _checkpoints[key].stack;
73881                 _index = _checkpoints[key].index;
73882               } else {
73883                 _stack = [{
73884                   graph: coreGraph()
73885                 }];
73886                 _index = 0;
73887                 _tree = coreTree(_stack[0].graph);
73888                 _checkpoints = {};
73889               }
73890
73891               dispatch.call('reset');
73892               dispatch.call('change');
73893               return history;
73894             },
73895             // `toIntroGraph()` is used to export the intro graph used by the walkthrough.
73896             //
73897             // To use it:
73898             //  1. Start the walkthrough.
73899             //  2. Get to a "free editing" tutorial step
73900             //  3. Make your edits to the walkthrough map
73901             //  4. In your browser dev console run:
73902             //        `id.history().toIntroGraph()`
73903             //  5. This outputs stringified JSON to the browser console
73904             //  6. Copy it to `data/intro_graph.json` and prettify it in your code editor
73905             toIntroGraph: function toIntroGraph() {
73906               var nextID = {
73907                 n: 0,
73908                 r: 0,
73909                 w: 0
73910               };
73911               var permIDs = {};
73912               var graph = this.graph();
73913               var baseEntities = {}; // clone base entities..
73914
73915               Object.values(graph.base().entities).forEach(function (entity) {
73916                 var copy = copyIntroEntity(entity);
73917                 baseEntities[copy.id] = copy;
73918               }); // replace base entities with head entities..
73919
73920               Object.keys(graph.entities).forEach(function (id) {
73921                 var entity = graph.entities[id];
73922
73923                 if (entity) {
73924                   var copy = copyIntroEntity(entity);
73925                   baseEntities[copy.id] = copy;
73926                 } else {
73927                   delete baseEntities[id];
73928                 }
73929               }); // swap temporary for permanent ids..
73930
73931               Object.values(baseEntities).forEach(function (entity) {
73932                 if (Array.isArray(entity.nodes)) {
73933                   entity.nodes = entity.nodes.map(function (node) {
73934                     return permIDs[node] || node;
73935                   });
73936                 }
73937
73938                 if (Array.isArray(entity.members)) {
73939                   entity.members = entity.members.map(function (member) {
73940                     member.id = permIDs[member.id] || member.id;
73941                     return member;
73942                   });
73943                 }
73944               });
73945               return JSON.stringify({
73946                 dataIntroGraph: baseEntities
73947               });
73948
73949               function copyIntroEntity(source) {
73950                 var copy = utilObjectOmit(source, ['type', 'user', 'v', 'version', 'visible']); // Note: the copy is no longer an osmEntity, so it might not have `tags`
73951
73952                 if (copy.tags && !Object.keys(copy.tags)) {
73953                   delete copy.tags;
73954                 }
73955
73956                 if (Array.isArray(copy.loc)) {
73957                   copy.loc[0] = +copy.loc[0].toFixed(6);
73958                   copy.loc[1] = +copy.loc[1].toFixed(6);
73959                 }
73960
73961                 var match = source.id.match(/([nrw])-\d*/); // temporary id
73962
73963                 if (match !== null) {
73964                   var nrw = match[1];
73965                   var permID;
73966
73967                   do {
73968                     permID = nrw + ++nextID[nrw];
73969                   } while (baseEntities.hasOwnProperty(permID));
73970
73971                   copy.id = permIDs[source.id] = permID;
73972                 }
73973
73974                 return copy;
73975               }
73976             },
73977             toJSON: function toJSON() {
73978               if (!this.hasChanges()) return;
73979               var allEntities = {};
73980               var baseEntities = {};
73981               var base = _stack[0];
73982
73983               var s = _stack.map(function (i) {
73984                 var modified = [];
73985                 var deleted = [];
73986                 Object.keys(i.graph.entities).forEach(function (id) {
73987                   var entity = i.graph.entities[id];
73988
73989                   if (entity) {
73990                     var key = osmEntity.key(entity);
73991                     allEntities[key] = entity;
73992                     modified.push(key);
73993                   } else {
73994                     deleted.push(id);
73995                   } // make sure that the originals of changed or deleted entities get merged
73996                   // into the base of the _stack after restoring the data from JSON.
73997
73998
73999                   if (id in base.graph.entities) {
74000                     baseEntities[id] = base.graph.entities[id];
74001                   }
74002
74003                   if (entity && entity.nodes) {
74004                     // get originals of pre-existing child nodes
74005                     entity.nodes.forEach(function (nodeID) {
74006                       if (nodeID in base.graph.entities) {
74007                         baseEntities[nodeID] = base.graph.entities[nodeID];
74008                       }
74009                     });
74010                   } // get originals of parent entities too
74011
74012
74013                   var baseParents = base.graph._parentWays[id];
74014
74015                   if (baseParents) {
74016                     baseParents.forEach(function (parentID) {
74017                       if (parentID in base.graph.entities) {
74018                         baseEntities[parentID] = base.graph.entities[parentID];
74019                       }
74020                     });
74021                   }
74022                 });
74023                 var x = {};
74024                 if (modified.length) x.modified = modified;
74025                 if (deleted.length) x.deleted = deleted;
74026                 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
74027                 if (i.photoOverlaysUsed) x.photoOverlaysUsed = i.photoOverlaysUsed;
74028                 if (i.annotation) x.annotation = i.annotation;
74029                 if (i.transform) x.transform = i.transform;
74030                 if (i.selectedIDs) x.selectedIDs = i.selectedIDs;
74031                 return x;
74032               });
74033
74034               return JSON.stringify({
74035                 version: 3,
74036                 entities: Object.values(allEntities),
74037                 baseEntities: Object.values(baseEntities),
74038                 stack: s,
74039                 nextIDs: osmEntity.id.next,
74040                 index: _index,
74041                 // note the time the changes were saved
74042                 timestamp: new Date().getTime()
74043               });
74044             },
74045             fromJSON: function fromJSON(json, loadChildNodes) {
74046               var h = JSON.parse(json);
74047               var loadComplete = true;
74048               osmEntity.id.next = h.nextIDs;
74049               _index = h.index;
74050
74051               if (h.version === 2 || h.version === 3) {
74052                 var allEntities = {};
74053                 h.entities.forEach(function (entity) {
74054                   allEntities[osmEntity.key(entity)] = osmEntity(entity);
74055                 });
74056
74057                 if (h.version === 3) {
74058                   // This merges originals for changed entities into the base of
74059                   // the _stack even if the current _stack doesn't have them (for
74060                   // example when iD has been restarted in a different region)
74061                   var baseEntities = h.baseEntities.map(function (d) {
74062                     return osmEntity(d);
74063                   });
74064
74065                   var stack = _stack.map(function (state) {
74066                     return state.graph;
74067                   });
74068
74069                   _stack[0].graph.rebase(baseEntities, stack, true);
74070
74071                   _tree.rebase(baseEntities, true); // When we restore a modified way, we also need to fetch any missing
74072                   // childnodes that would normally have been downloaded with it.. #2142
74073
74074
74075                   if (loadChildNodes) {
74076                     var osm = context.connection();
74077                     var baseWays = baseEntities.filter(function (e) {
74078                       return e.type === 'way';
74079                     });
74080                     var nodeIDs = baseWays.reduce(function (acc, way) {
74081                       return utilArrayUnion(acc, way.nodes);
74082                     }, []);
74083                     var missing = nodeIDs.filter(function (n) {
74084                       return !_stack[0].graph.hasEntity(n);
74085                     });
74086
74087                     if (missing.length && osm) {
74088                       loadComplete = false;
74089                       context.map().redrawEnable(false);
74090                       var loading = uiLoading(context).blocking(true);
74091                       context.container().call(loading);
74092
74093                       var childNodesLoaded = function childNodesLoaded(err, result) {
74094                         if (!err) {
74095                           var visibleGroups = utilArrayGroupBy(result.data, 'visible');
74096                           var visibles = visibleGroups["true"] || []; // alive nodes
74097
74098                           var invisibles = visibleGroups["false"] || []; // deleted nodes
74099
74100                           if (visibles.length) {
74101                             var visibleIDs = visibles.map(function (entity) {
74102                               return entity.id;
74103                             });
74104
74105                             var stack = _stack.map(function (state) {
74106                               return state.graph;
74107                             });
74108
74109                             missing = utilArrayDifference(missing, visibleIDs);
74110
74111                             _stack[0].graph.rebase(visibles, stack, true);
74112
74113                             _tree.rebase(visibles, true);
74114                           } // fetch older versions of nodes that were deleted..
74115
74116
74117                           invisibles.forEach(function (entity) {
74118                             osm.loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
74119                           });
74120                         }
74121
74122                         if (err || !missing.length) {
74123                           loading.close();
74124                           context.map().redrawEnable(true);
74125                           dispatch.call('change');
74126                           dispatch.call('restore', this);
74127                         }
74128                       };
74129
74130                       osm.loadMultiple(missing, childNodesLoaded);
74131                     }
74132                   }
74133                 }
74134
74135                 _stack = h.stack.map(function (d) {
74136                   var entities = {},
74137                       entity;
74138
74139                   if (d.modified) {
74140                     d.modified.forEach(function (key) {
74141                       entity = allEntities[key];
74142                       entities[entity.id] = entity;
74143                     });
74144                   }
74145
74146                   if (d.deleted) {
74147                     d.deleted.forEach(function (id) {
74148                       entities[id] = undefined;
74149                     });
74150                   }
74151
74152                   return {
74153                     graph: coreGraph(_stack[0].graph).load(entities),
74154                     annotation: d.annotation,
74155                     imageryUsed: d.imageryUsed,
74156                     photoOverlaysUsed: d.photoOverlaysUsed,
74157                     transform: d.transform,
74158                     selectedIDs: d.selectedIDs
74159                   };
74160                 });
74161               } else {
74162                 // original version
74163                 _stack = h.stack.map(function (d) {
74164                   var entities = {};
74165
74166                   for (var i in d.entities) {
74167                     var entity = d.entities[i];
74168                     entities[i] = entity === 'undefined' ? undefined : osmEntity(entity);
74169                   }
74170
74171                   d.graph = coreGraph(_stack[0].graph).load(entities);
74172                   return d;
74173                 });
74174               }
74175
74176               var transform = _stack[_index].transform;
74177
74178               if (transform) {
74179                 context.map().transformEase(transform, 0); // 0 = immediate, no easing
74180               }
74181
74182               if (loadComplete) {
74183                 dispatch.call('change');
74184                 dispatch.call('restore', this);
74185               }
74186
74187               return history;
74188             },
74189             lock: function lock() {
74190               return _lock.lock();
74191             },
74192             unlock: function unlock() {
74193               _lock.unlock();
74194             },
74195             save: function save() {
74196               if (_lock.locked() && // don't overwrite existing, unresolved changes
74197               !_hasUnresolvedRestorableChanges) {
74198                 var success = corePreferences(getKey('saved_history'), history.toJSON() || null);
74199                 if (!success) dispatch.call('storage_error');
74200               }
74201
74202               return history;
74203             },
74204             // delete the history version saved in localStorage
74205             clearSaved: function clearSaved() {
74206               context.debouncedSave.cancel();
74207
74208               if (_lock.locked()) {
74209                 _hasUnresolvedRestorableChanges = false;
74210                 corePreferences(getKey('saved_history'), null); // clear the changeset metadata associated with the saved history
74211
74212                 corePreferences('comment', null);
74213                 corePreferences('hashtags', null);
74214                 corePreferences('source', null);
74215               }
74216
74217               return history;
74218             },
74219             savedHistoryJSON: function savedHistoryJSON() {
74220               return corePreferences(getKey('saved_history'));
74221             },
74222             hasRestorableChanges: function hasRestorableChanges() {
74223               return _hasUnresolvedRestorableChanges;
74224             },
74225             // load history from a version stored in localStorage
74226             restore: function restore() {
74227               if (_lock.locked()) {
74228                 _hasUnresolvedRestorableChanges = false;
74229                 var json = this.savedHistoryJSON();
74230                 if (json) history.fromJSON(json, true);
74231               }
74232             },
74233             _getKey: getKey
74234           };
74235           history.reset();
74236           return utilRebind(history, dispatch, 'on');
74237         }
74238
74239         /**
74240          * Look for roads that can be connected to other roads with a short extension
74241          */
74242
74243         function validationAlmostJunction(context) {
74244           var type = 'almost_junction';
74245           var EXTEND_TH_METERS = 5;
74246           var WELD_TH_METERS = 0.75; // Comes from considering bounding case of parallel ways
74247
74248           var CLOSE_NODE_TH = EXTEND_TH_METERS - WELD_TH_METERS; // Comes from considering bounding case of perpendicular ways
74249
74250           var SIG_ANGLE_TH = Math.atan(WELD_TH_METERS / EXTEND_TH_METERS);
74251
74252           function isHighway(entity) {
74253             return entity.type === 'way' && osmRoutableHighwayTagValues[entity.tags.highway];
74254           }
74255
74256           function isTaggedAsNotContinuing(node) {
74257             return node.tags.noexit === 'yes' || node.tags.amenity === 'parking_entrance' || node.tags.entrance && node.tags.entrance !== 'no';
74258           }
74259
74260           var validation = function checkAlmostJunction(entity, graph) {
74261             if (!isHighway(entity)) return [];
74262             if (entity.isDegenerate()) return [];
74263             var tree = context.history().tree();
74264             var extendableNodeInfos = findConnectableEndNodesByExtension(entity);
74265             var issues = [];
74266             extendableNodeInfos.forEach(function (extendableNodeInfo) {
74267               issues.push(new validationIssue({
74268                 type: type,
74269                 subtype: 'highway-highway',
74270                 severity: 'warning',
74271                 message: function message(context) {
74272                   var entity1 = context.hasEntity(this.entityIds[0]);
74273
74274                   if (this.entityIds[0] === this.entityIds[2]) {
74275                     return entity1 ? _t.html('issues.almost_junction.self.message', {
74276                       feature: utilDisplayLabel(entity1, context.graph())
74277                     }) : '';
74278                   } else {
74279                     var entity2 = context.hasEntity(this.entityIds[2]);
74280                     return entity1 && entity2 ? _t.html('issues.almost_junction.message', {
74281                       feature: utilDisplayLabel(entity1, context.graph()),
74282                       feature2: utilDisplayLabel(entity2, context.graph())
74283                     }) : '';
74284                   }
74285                 },
74286                 reference: showReference,
74287                 entityIds: [entity.id, extendableNodeInfo.node.id, extendableNodeInfo.wid],
74288                 loc: extendableNodeInfo.node.loc,
74289                 hash: JSON.stringify(extendableNodeInfo.node.loc),
74290                 data: {
74291                   midId: extendableNodeInfo.mid.id,
74292                   edge: extendableNodeInfo.edge,
74293                   cross_loc: extendableNodeInfo.cross_loc
74294                 },
74295                 dynamicFixes: makeFixes
74296               }));
74297             });
74298             return issues;
74299
74300             function makeFixes(context) {
74301               var fixes = [new validationIssueFix({
74302                 icon: 'iD-icon-abutment',
74303                 title: _t.html('issues.fix.connect_features.title'),
74304                 onClick: function onClick(context) {
74305                   var annotation = _t('issues.fix.connect_almost_junction.annotation');
74306
74307                   var _this$issue$entityIds = _slicedToArray(this.issue.entityIds, 3),
74308                       endNodeId = _this$issue$entityIds[1],
74309                       crossWayId = _this$issue$entityIds[2];
74310
74311                   var midNode = context.entity(this.issue.data.midId);
74312                   var endNode = context.entity(endNodeId);
74313                   var crossWay = context.entity(crossWayId); // When endpoints are close, just join if resulting small change in angle (#7201)
74314
74315                   var nearEndNodes = findNearbyEndNodes(endNode, crossWay);
74316
74317                   if (nearEndNodes.length > 0) {
74318                     var collinear = findSmallJoinAngle(midNode, endNode, nearEndNodes);
74319
74320                     if (collinear) {
74321                       context.perform(actionMergeNodes([collinear.id, endNode.id], collinear.loc), annotation);
74322                       return;
74323                     }
74324                   }
74325
74326                   var targetEdge = this.issue.data.edge;
74327                   var crossLoc = this.issue.data.cross_loc;
74328                   var edgeNodes = [context.entity(targetEdge[0]), context.entity(targetEdge[1])];
74329                   var closestNodeInfo = geoSphericalClosestNode(edgeNodes, crossLoc); // already a point nearby, just connect to that
74330
74331                   if (closestNodeInfo.distance < WELD_TH_METERS) {
74332                     context.perform(actionMergeNodes([closestNodeInfo.node.id, endNode.id], closestNodeInfo.node.loc), annotation); // else add the end node to the edge way
74333                   } else {
74334                     context.perform(actionAddMidpoint({
74335                       loc: crossLoc,
74336                       edge: targetEdge
74337                     }, endNode), annotation);
74338                   }
74339                 }
74340               })];
74341               var node = context.hasEntity(this.entityIds[1]);
74342
74343               if (node && !node.hasInterestingTags()) {
74344                 // node has no descriptive tags, suggest noexit fix
74345                 fixes.push(new validationIssueFix({
74346                   icon: 'maki-barrier',
74347                   title: _t.html('issues.fix.tag_as_disconnected.title'),
74348                   onClick: function onClick(context) {
74349                     var nodeID = this.issue.entityIds[1];
74350                     var tags = Object.assign({}, context.entity(nodeID).tags);
74351                     tags.noexit = 'yes';
74352                     context.perform(actionChangeTags(nodeID, tags), _t('issues.fix.tag_as_disconnected.annotation'));
74353                   }
74354                 }));
74355               }
74356
74357               return fixes;
74358             }
74359
74360             function showReference(selection) {
74361               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.almost_junction.highway-highway.reference'));
74362             }
74363
74364             function isExtendableCandidate(node, way) {
74365               // can not accurately test vertices on tiles not downloaded from osm - #5938
74366               var osm = services.osm;
74367
74368               if (osm && !osm.isDataLoaded(node.loc)) {
74369                 return false;
74370               }
74371
74372               if (isTaggedAsNotContinuing(node) || graph.parentWays(node).length !== 1) {
74373                 return false;
74374               }
74375
74376               var occurrences = 0;
74377
74378               for (var index in way.nodes) {
74379                 if (way.nodes[index] === node.id) {
74380                   occurrences += 1;
74381
74382                   if (occurrences > 1) {
74383                     return false;
74384                   }
74385                 }
74386               }
74387
74388               return true;
74389             }
74390
74391             function findConnectableEndNodesByExtension(way) {
74392               var results = [];
74393               if (way.isClosed()) return results;
74394               var testNodes;
74395               var indices = [0, way.nodes.length - 1];
74396               indices.forEach(function (nodeIndex) {
74397                 var nodeID = way.nodes[nodeIndex];
74398                 var node = graph.entity(nodeID);
74399                 if (!isExtendableCandidate(node, way)) return;
74400                 var connectionInfo = canConnectByExtend(way, nodeIndex);
74401                 if (!connectionInfo) return;
74402                 testNodes = graph.childNodes(way).slice(); // shallow copy
74403
74404                 testNodes[nodeIndex] = testNodes[nodeIndex].move(connectionInfo.cross_loc); // don't flag issue if connecting the ways would cause self-intersection
74405
74406                 if (geoHasSelfIntersections(testNodes, nodeID)) return;
74407                 results.push(connectionInfo);
74408               });
74409               return results;
74410             }
74411
74412             function findNearbyEndNodes(node, way) {
74413               return [way.nodes[0], way.nodes[way.nodes.length - 1]].map(function (d) {
74414                 return graph.entity(d);
74415               }).filter(function (d) {
74416                 // Node cannot be near to itself, but other endnode of same way could be
74417                 return d.id !== node.id && geoSphericalDistance(node.loc, d.loc) <= CLOSE_NODE_TH;
74418               });
74419             }
74420
74421             function findSmallJoinAngle(midNode, tipNode, endNodes) {
74422               // Both nodes could be close, so want to join whichever is closest to collinear
74423               var joinTo;
74424               var minAngle = Infinity; // Checks midNode -> tipNode -> endNode for collinearity
74425
74426               endNodes.forEach(function (endNode) {
74427                 var a1 = geoAngle(midNode, tipNode, context.projection) + Math.PI;
74428                 var a2 = geoAngle(midNode, endNode, context.projection) + Math.PI;
74429                 var diff = Math.max(a1, a2) - Math.min(a1, a2);
74430
74431                 if (diff < minAngle) {
74432                   joinTo = endNode;
74433                   minAngle = diff;
74434                 }
74435               });
74436               /* Threshold set by considering right angle triangle
74437               based on node joining threshold and extension distance */
74438
74439               if (minAngle <= SIG_ANGLE_TH) return joinTo;
74440               return null;
74441             }
74442
74443             function hasTag(tags, key) {
74444               return tags[key] !== undefined && tags[key] !== 'no';
74445             }
74446
74447             function canConnectWays(way, way2) {
74448               // allow self-connections
74449               if (way.id === way2.id) return true; // if one is bridge or tunnel, both must be bridge or tunnel
74450
74451               if ((hasTag(way.tags, 'bridge') || hasTag(way2.tags, 'bridge')) && !(hasTag(way.tags, 'bridge') && hasTag(way2.tags, 'bridge'))) return false;
74452               if ((hasTag(way.tags, 'tunnel') || hasTag(way2.tags, 'tunnel')) && !(hasTag(way.tags, 'tunnel') && hasTag(way2.tags, 'tunnel'))) return false; // must have equivalent layers and levels
74453
74454               var layer1 = way.tags.layer || '0',
74455                   layer2 = way2.tags.layer || '0';
74456               if (layer1 !== layer2) return false;
74457               var level1 = way.tags.level || '0',
74458                   level2 = way2.tags.level || '0';
74459               if (level1 !== level2) return false;
74460               return true;
74461             }
74462
74463             function canConnectByExtend(way, endNodeIdx) {
74464               var tipNid = way.nodes[endNodeIdx]; // the 'tip' node for extension point
74465
74466               var midNid = endNodeIdx === 0 ? way.nodes[1] : way.nodes[way.nodes.length - 2]; // the other node of the edge
74467
74468               var tipNode = graph.entity(tipNid);
74469               var midNode = graph.entity(midNid);
74470               var lon = tipNode.loc[0];
74471               var lat = tipNode.loc[1];
74472               var lon_range = geoMetersToLon(EXTEND_TH_METERS, lat) / 2;
74473               var lat_range = geoMetersToLat(EXTEND_TH_METERS) / 2;
74474               var queryExtent = geoExtent([[lon - lon_range, lat - lat_range], [lon + lon_range, lat + lat_range]]); // first, extend the edge of [midNode -> tipNode] by EXTEND_TH_METERS and find the "extended tip" location
74475
74476               var edgeLen = geoSphericalDistance(midNode.loc, tipNode.loc);
74477               var t = EXTEND_TH_METERS / edgeLen + 1.0;
74478               var extTipLoc = geoVecInterp(midNode.loc, tipNode.loc, t); // then, check if the extension part [tipNode.loc -> extTipLoc] intersects any other ways
74479
74480               var segmentInfos = tree.waySegments(queryExtent, graph);
74481
74482               for (var i = 0; i < segmentInfos.length; i++) {
74483                 var segmentInfo = segmentInfos[i];
74484                 var way2 = graph.entity(segmentInfo.wayId);
74485                 if (!isHighway(way2)) continue;
74486                 if (!canConnectWays(way, way2)) continue;
74487                 var nAid = segmentInfo.nodes[0],
74488                     nBid = segmentInfo.nodes[1];
74489                 if (nAid === tipNid || nBid === tipNid) continue;
74490                 var nA = graph.entity(nAid),
74491                     nB = graph.entity(nBid);
74492                 var crossLoc = geoLineIntersection([tipNode.loc, extTipLoc], [nA.loc, nB.loc]);
74493
74494                 if (crossLoc) {
74495                   return {
74496                     mid: midNode,
74497                     node: tipNode,
74498                     wid: way2.id,
74499                     edge: [nA.id, nB.id],
74500                     cross_loc: crossLoc
74501                   };
74502                 }
74503               }
74504
74505               return null;
74506             }
74507           };
74508
74509           validation.type = type;
74510           return validation;
74511         }
74512
74513         function validationCloseNodes(context) {
74514           var type = 'close_nodes';
74515           var pointThresholdMeters = 0.2;
74516
74517           var validation = function validation(entity, graph) {
74518             if (entity.type === 'node') {
74519               return getIssuesForNode(entity);
74520             } else if (entity.type === 'way') {
74521               return getIssuesForWay(entity);
74522             }
74523
74524             return [];
74525
74526             function getIssuesForNode(node) {
74527               var parentWays = graph.parentWays(node);
74528
74529               if (parentWays.length) {
74530                 return getIssuesForVertex(node, parentWays);
74531               } else {
74532                 return getIssuesForDetachedPoint(node);
74533               }
74534             }
74535
74536             function wayTypeFor(way) {
74537               if (way.tags.boundary && way.tags.boundary !== 'no') return 'boundary';
74538               if (way.tags.indoor && way.tags.indoor !== 'no') return 'indoor';
74539               if (way.tags.building && way.tags.building !== 'no' || way.tags['building:part'] && way.tags['building:part'] !== 'no') return 'building';
74540               if (osmPathHighwayTagValues[way.tags.highway]) return 'path';
74541               var parentRelations = graph.parentRelations(way);
74542
74543               for (var i in parentRelations) {
74544                 var relation = parentRelations[i];
74545                 if (relation.tags.type === 'boundary') return 'boundary';
74546
74547                 if (relation.isMultipolygon()) {
74548                   if (relation.tags.indoor && relation.tags.indoor !== 'no') return 'indoor';
74549                   if (relation.tags.building && relation.tags.building !== 'no' || relation.tags['building:part'] && relation.tags['building:part'] !== 'no') return 'building';
74550                 }
74551               }
74552
74553               return 'other';
74554             }
74555
74556             function shouldCheckWay(way) {
74557               // don't flag issues where merging would create degenerate ways
74558               if (way.nodes.length <= 2 || way.isClosed() && way.nodes.length <= 4) return false;
74559               var bbox = way.extent(graph).bbox();
74560               var hypotenuseMeters = geoSphericalDistance([bbox.minX, bbox.minY], [bbox.maxX, bbox.maxY]); // don't flag close nodes in very small ways
74561
74562               if (hypotenuseMeters < 1.5) return false;
74563               return true;
74564             }
74565
74566             function getIssuesForWay(way) {
74567               if (!shouldCheckWay(way)) return [];
74568               var issues = [],
74569                   nodes = graph.childNodes(way);
74570
74571               for (var i = 0; i < nodes.length - 1; i++) {
74572                 var node1 = nodes[i];
74573                 var node2 = nodes[i + 1];
74574                 var issue = getWayIssueIfAny(node1, node2, way);
74575                 if (issue) issues.push(issue);
74576               }
74577
74578               return issues;
74579             }
74580
74581             function getIssuesForVertex(node, parentWays) {
74582               var issues = [];
74583
74584               function checkForCloseness(node1, node2, way) {
74585                 var issue = getWayIssueIfAny(node1, node2, way);
74586                 if (issue) issues.push(issue);
74587               }
74588
74589               for (var i = 0; i < parentWays.length; i++) {
74590                 var parentWay = parentWays[i];
74591                 if (!shouldCheckWay(parentWay)) continue;
74592                 var lastIndex = parentWay.nodes.length - 1;
74593
74594                 for (var j = 0; j < parentWay.nodes.length; j++) {
74595                   if (j !== 0) {
74596                     if (parentWay.nodes[j - 1] === node.id) {
74597                       checkForCloseness(node, graph.entity(parentWay.nodes[j]), parentWay);
74598                     }
74599                   }
74600
74601                   if (j !== lastIndex) {
74602                     if (parentWay.nodes[j + 1] === node.id) {
74603                       checkForCloseness(graph.entity(parentWay.nodes[j]), node, parentWay);
74604                     }
74605                   }
74606                 }
74607               }
74608
74609               return issues;
74610             }
74611
74612             function thresholdMetersForWay(way) {
74613               if (!shouldCheckWay(way)) return 0;
74614               var wayType = wayTypeFor(way); // don't flag boundaries since they might be highly detailed and can't be easily verified
74615
74616               if (wayType === 'boundary') return 0; // expect some features to be mapped with higher levels of detail
74617
74618               if (wayType === 'indoor') return 0.01;
74619               if (wayType === 'building') return 0.05;
74620               if (wayType === 'path') return 0.1;
74621               return 0.2;
74622             }
74623
74624             function getIssuesForDetachedPoint(node) {
74625               var issues = [];
74626               var lon = node.loc[0];
74627               var lat = node.loc[1];
74628               var lon_range = geoMetersToLon(pointThresholdMeters, lat) / 2;
74629               var lat_range = geoMetersToLat(pointThresholdMeters) / 2;
74630               var queryExtent = geoExtent([[lon - lon_range, lat - lat_range], [lon + lon_range, lat + lat_range]]);
74631               var intersected = context.history().tree().intersects(queryExtent, graph);
74632
74633               for (var j = 0; j < intersected.length; j++) {
74634                 var nearby = intersected[j];
74635                 if (nearby.id === node.id) continue;
74636                 if (nearby.type !== 'node' || nearby.geometry(graph) !== 'point') continue;
74637
74638                 if (nearby.loc === node.loc || geoSphericalDistance(node.loc, nearby.loc) < pointThresholdMeters) {
74639                   // allow very close points if tags indicate the z-axis might vary
74640                   var zAxisKeys = {
74641                     layer: true,
74642                     level: true,
74643                     'addr:housenumber': true,
74644                     'addr:unit': true
74645                   };
74646                   var zAxisDifferentiates = false;
74647
74648                   for (var key in zAxisKeys) {
74649                     var nodeValue = node.tags[key] || '0';
74650                     var nearbyValue = nearby.tags[key] || '0';
74651
74652                     if (nodeValue !== nearbyValue) {
74653                       zAxisDifferentiates = true;
74654                       break;
74655                     }
74656                   }
74657
74658                   if (zAxisDifferentiates) continue;
74659                   issues.push(new validationIssue({
74660                     type: type,
74661                     subtype: 'detached',
74662                     severity: 'warning',
74663                     message: function message(context) {
74664                       var entity = context.hasEntity(this.entityIds[0]),
74665                           entity2 = context.hasEntity(this.entityIds[1]);
74666                       return entity && entity2 ? _t.html('issues.close_nodes.detached.message', {
74667                         feature: utilDisplayLabel(entity, context.graph()),
74668                         feature2: utilDisplayLabel(entity2, context.graph())
74669                       }) : '';
74670                     },
74671                     reference: showReference,
74672                     entityIds: [node.id, nearby.id],
74673                     dynamicFixes: function dynamicFixes() {
74674                       return [new validationIssueFix({
74675                         icon: 'iD-operation-disconnect',
74676                         title: _t.html('issues.fix.move_points_apart.title')
74677                       }), new validationIssueFix({
74678                         icon: 'iD-icon-layers',
74679                         title: _t.html('issues.fix.use_different_layers_or_levels.title')
74680                       })];
74681                     }
74682                   }));
74683                 }
74684               }
74685
74686               return issues;
74687
74688               function showReference(selection) {
74689                 var referenceText = _t('issues.close_nodes.detached.reference');
74690                 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').html(referenceText);
74691               }
74692             }
74693
74694             function getWayIssueIfAny(node1, node2, way) {
74695               if (node1.id === node2.id || node1.hasInterestingTags() && node2.hasInterestingTags()) {
74696                 return null;
74697               }
74698
74699               if (node1.loc !== node2.loc) {
74700                 var parentWays1 = graph.parentWays(node1);
74701                 var parentWays2 = new Set(graph.parentWays(node2));
74702                 var sharedWays = parentWays1.filter(function (parentWay) {
74703                   return parentWays2.has(parentWay);
74704                 });
74705                 var thresholds = sharedWays.map(function (parentWay) {
74706                   return thresholdMetersForWay(parentWay);
74707                 });
74708                 var threshold = Math.min.apply(Math, _toConsumableArray(thresholds));
74709                 var distance = geoSphericalDistance(node1.loc, node2.loc);
74710                 if (distance > threshold) return null;
74711               }
74712
74713               return new validationIssue({
74714                 type: type,
74715                 subtype: 'vertices',
74716                 severity: 'warning',
74717                 message: function message(context) {
74718                   var entity = context.hasEntity(this.entityIds[0]);
74719                   return entity ? _t.html('issues.close_nodes.message', {
74720                     way: utilDisplayLabel(entity, context.graph())
74721                   }) : '';
74722                 },
74723                 reference: showReference,
74724                 entityIds: [way.id, node1.id, node2.id],
74725                 loc: node1.loc,
74726                 dynamicFixes: function dynamicFixes() {
74727                   return [new validationIssueFix({
74728                     icon: 'iD-icon-plus',
74729                     title: _t.html('issues.fix.merge_points.title'),
74730                     onClick: function onClick(context) {
74731                       var entityIds = this.issue.entityIds;
74732                       var action = actionMergeNodes([entityIds[1], entityIds[2]]);
74733                       context.perform(action, _t('issues.fix.merge_close_vertices.annotation'));
74734                     }
74735                   }), new validationIssueFix({
74736                     icon: 'iD-operation-disconnect',
74737                     title: _t.html('issues.fix.move_points_apart.title')
74738                   })];
74739                 }
74740               });
74741
74742               function showReference(selection) {
74743                 var referenceText = _t('issues.close_nodes.reference');
74744                 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').html(referenceText);
74745               }
74746             }
74747           };
74748
74749           validation.type = type;
74750           return validation;
74751         }
74752
74753         function validationCrossingWays(context) {
74754           var type = 'crossing_ways'; // returns the way or its parent relation, whichever has a useful feature type
74755
74756           function getFeatureWithFeatureTypeTagsForWay(way, graph) {
74757             if (getFeatureType(way, graph) === null) {
74758               // if the way doesn't match a feature type, check its parent relations
74759               var parentRels = graph.parentRelations(way);
74760
74761               for (var i = 0; i < parentRels.length; i++) {
74762                 var rel = parentRels[i];
74763
74764                 if (getFeatureType(rel, graph) !== null) {
74765                   return rel;
74766                 }
74767               }
74768             }
74769
74770             return way;
74771           }
74772
74773           function hasTag(tags, key) {
74774             return tags[key] !== undefined && tags[key] !== 'no';
74775           }
74776
74777           function taggedAsIndoor(tags) {
74778             return hasTag(tags, 'indoor') || hasTag(tags, 'level') || tags.highway === 'corridor';
74779           }
74780
74781           function allowsBridge(featureType) {
74782             return featureType === 'highway' || featureType === 'railway' || featureType === 'waterway';
74783           }
74784
74785           function allowsTunnel(featureType) {
74786             return featureType === 'highway' || featureType === 'railway' || featureType === 'waterway';
74787           } // discard
74788
74789
74790           var ignoredBuildings = {
74791             demolished: true,
74792             dismantled: true,
74793             proposed: true,
74794             razed: true
74795           };
74796
74797           function getFeatureType(entity, graph) {
74798             var geometry = entity.geometry(graph);
74799             if (geometry !== 'line' && geometry !== 'area') return null;
74800             var tags = entity.tags;
74801             if (hasTag(tags, 'building') && !ignoredBuildings[tags.building]) return 'building';
74802             if (hasTag(tags, 'highway') && osmRoutableHighwayTagValues[tags.highway]) return 'highway'; // don't check railway or waterway areas
74803
74804             if (geometry !== 'line') return null;
74805             if (hasTag(tags, 'railway') && osmRailwayTrackTagValues[tags.railway]) return 'railway';
74806             if (hasTag(tags, 'waterway') && osmFlowingWaterwayTagValues[tags.waterway]) return 'waterway';
74807             return null;
74808           }
74809
74810           function isLegitCrossing(tags1, featureType1, tags2, featureType2) {
74811             // assume 0 by default
74812             var level1 = tags1.level || '0';
74813             var level2 = tags2.level || '0';
74814
74815             if (taggedAsIndoor(tags1) && taggedAsIndoor(tags2) && level1 !== level2) {
74816               // assume features don't interact if they're indoor on different levels
74817               return true;
74818             } // assume 0 by default; don't use way.layer() since we account for structures here
74819
74820
74821             var layer1 = tags1.layer || '0';
74822             var layer2 = tags2.layer || '0';
74823
74824             if (allowsBridge(featureType1) && allowsBridge(featureType2)) {
74825               if (hasTag(tags1, 'bridge') && !hasTag(tags2, 'bridge')) return true;
74826               if (!hasTag(tags1, 'bridge') && hasTag(tags2, 'bridge')) return true; // crossing bridges must use different layers
74827
74828               if (hasTag(tags1, 'bridge') && hasTag(tags2, 'bridge') && layer1 !== layer2) return true;
74829             } else if (allowsBridge(featureType1) && hasTag(tags1, 'bridge')) return true;else if (allowsBridge(featureType2) && hasTag(tags2, 'bridge')) return true;
74830
74831             if (allowsTunnel(featureType1) && allowsTunnel(featureType2)) {
74832               if (hasTag(tags1, 'tunnel') && !hasTag(tags2, 'tunnel')) return true;
74833               if (!hasTag(tags1, 'tunnel') && hasTag(tags2, 'tunnel')) return true; // crossing tunnels must use different layers
74834
74835               if (hasTag(tags1, 'tunnel') && hasTag(tags2, 'tunnel') && layer1 !== layer2) return true;
74836             } else if (allowsTunnel(featureType1) && hasTag(tags1, 'tunnel')) return true;else if (allowsTunnel(featureType2) && hasTag(tags2, 'tunnel')) return true; // don't flag crossing waterways and pier/highways
74837
74838
74839             if (featureType1 === 'waterway' && featureType2 === 'highway' && tags2.man_made === 'pier') return true;
74840             if (featureType2 === 'waterway' && featureType1 === 'highway' && tags1.man_made === 'pier') return true;
74841
74842             if (featureType1 === 'building' || featureType2 === 'building') {
74843               // for building crossings, different layers are enough
74844               if (layer1 !== layer2) return true;
74845             }
74846
74847             return false;
74848           } // highway values for which we shouldn't recommend connecting to waterways
74849
74850
74851           var highwaysDisallowingFords = {
74852             motorway: true,
74853             motorway_link: true,
74854             trunk: true,
74855             trunk_link: true,
74856             primary: true,
74857             primary_link: true,
74858             secondary: true,
74859             secondary_link: true
74860           };
74861           var nonCrossingHighways = {
74862             track: true
74863           };
74864
74865           function tagsForConnectionNodeIfAllowed(entity1, entity2, graph) {
74866             var featureType1 = getFeatureType(entity1, graph);
74867             var featureType2 = getFeatureType(entity2, graph);
74868             var geometry1 = entity1.geometry(graph);
74869             var geometry2 = entity2.geometry(graph);
74870             var bothLines = geometry1 === 'line' && geometry2 === 'line';
74871
74872             if (featureType1 === featureType2) {
74873               if (featureType1 === 'highway') {
74874                 var entity1IsPath = osmPathHighwayTagValues[entity1.tags.highway];
74875                 var entity2IsPath = osmPathHighwayTagValues[entity2.tags.highway];
74876
74877                 if ((entity1IsPath || entity2IsPath) && entity1IsPath !== entity2IsPath) {
74878                   // one feature is a path but not both
74879                   var roadFeature = entity1IsPath ? entity2 : entity1;
74880
74881                   if (nonCrossingHighways[roadFeature.tags.highway]) {
74882                     // don't mark path connections with certain roads as crossings
74883                     return {};
74884                   }
74885
74886                   var pathFeature = entity1IsPath ? entity1 : entity2;
74887
74888                   if (['marked', 'unmarked'].indexOf(pathFeature.tags.crossing) !== -1) {
74889                     // if the path is a crossing, match the crossing type
74890                     return bothLines ? {
74891                       highway: 'crossing',
74892                       crossing: pathFeature.tags.crossing
74893                     } : {};
74894                   } // don't add a `crossing` subtag to ambiguous crossings
74895
74896
74897                   return bothLines ? {
74898                     highway: 'crossing'
74899                   } : {};
74900                 }
74901
74902                 return {};
74903               }
74904
74905               if (featureType1 === 'waterway') return {};
74906               if (featureType1 === 'railway') return {};
74907             } else {
74908               var featureTypes = [featureType1, featureType2];
74909
74910               if (featureTypes.indexOf('highway') !== -1) {
74911                 if (featureTypes.indexOf('railway') !== -1) {
74912                   if (!bothLines) return {};
74913                   var isTram = entity1.tags.railway === 'tram' || entity2.tags.railway === 'tram';
74914
74915                   if (osmPathHighwayTagValues[entity1.tags.highway] || osmPathHighwayTagValues[entity2.tags.highway]) {
74916                     // path-tram connections use this tag
74917                     if (isTram) return {
74918                       railway: 'tram_crossing'
74919                     }; // other path-rail connections use this tag
74920
74921                     return {
74922                       railway: 'crossing'
74923                     };
74924                   } else {
74925                     // path-tram connections use this tag
74926                     if (isTram) return {
74927                       railway: 'tram_level_crossing'
74928                     }; // other road-rail connections use this tag
74929
74930                     return {
74931                       railway: 'level_crossing'
74932                     };
74933                   }
74934                 }
74935
74936                 if (featureTypes.indexOf('waterway') !== -1) {
74937                   // do not allow fords on structures
74938                   if (hasTag(entity1.tags, 'tunnel') && hasTag(entity2.tags, 'tunnel')) return null;
74939                   if (hasTag(entity1.tags, 'bridge') && hasTag(entity2.tags, 'bridge')) return null;
74940
74941                   if (highwaysDisallowingFords[entity1.tags.highway] || highwaysDisallowingFords[entity2.tags.highway]) {
74942                     // do not allow fords on major highways
74943                     return null;
74944                   }
74945
74946                   return bothLines ? {
74947                     ford: 'yes'
74948                   } : {};
74949                 }
74950               }
74951             }
74952
74953             return null;
74954           }
74955
74956           function findCrossingsByWay(way1, graph, tree) {
74957             var edgeCrossInfos = [];
74958             if (way1.type !== 'way') return edgeCrossInfos;
74959             var taggedFeature1 = getFeatureWithFeatureTypeTagsForWay(way1, graph);
74960             var way1FeatureType = getFeatureType(taggedFeature1, graph);
74961             if (way1FeatureType === null) return edgeCrossInfos;
74962             var checkedSingleCrossingWays = {}; // declare vars ahead of time to reduce garbage collection
74963
74964             var i, j;
74965             var extent;
74966             var n1, n2, nA, nB, nAId, nBId;
74967             var segment1, segment2;
74968             var oneOnly;
74969             var segmentInfos, segment2Info, way2, taggedFeature2, way2FeatureType;
74970             var way1Nodes = graph.childNodes(way1);
74971             var comparedWays = {};
74972
74973             for (i = 0; i < way1Nodes.length - 1; i++) {
74974               n1 = way1Nodes[i];
74975               n2 = way1Nodes[i + 1];
74976               extent = geoExtent([[Math.min(n1.loc[0], n2.loc[0]), Math.min(n1.loc[1], n2.loc[1])], [Math.max(n1.loc[0], n2.loc[0]), Math.max(n1.loc[1], n2.loc[1])]]); // Optimize by only checking overlapping segments, not every segment
74977               // of overlapping ways
74978
74979               segmentInfos = tree.waySegments(extent, graph);
74980
74981               for (j = 0; j < segmentInfos.length; j++) {
74982                 segment2Info = segmentInfos[j]; // don't check for self-intersection in this validation
74983
74984                 if (segment2Info.wayId === way1.id) continue; // skip if this way was already checked and only one issue is needed
74985
74986                 if (checkedSingleCrossingWays[segment2Info.wayId]) continue; // mark this way as checked even if there are no crossings
74987
74988                 comparedWays[segment2Info.wayId] = true;
74989                 way2 = graph.hasEntity(segment2Info.wayId);
74990                 if (!way2) continue;
74991                 taggedFeature2 = getFeatureWithFeatureTypeTagsForWay(way2, graph); // only check crossing highway, waterway, building, and railway
74992
74993                 way2FeatureType = getFeatureType(taggedFeature2, graph);
74994
74995                 if (way2FeatureType === null || isLegitCrossing(taggedFeature1.tags, way1FeatureType, taggedFeature2.tags, way2FeatureType)) {
74996                   continue;
74997                 } // create only one issue for building crossings
74998
74999
75000                 oneOnly = way1FeatureType === 'building' || way2FeatureType === 'building';
75001                 nAId = segment2Info.nodes[0];
75002                 nBId = segment2Info.nodes[1];
75003
75004                 if (nAId === n1.id || nAId === n2.id || nBId === n1.id || nBId === n2.id) {
75005                   // n1 or n2 is a connection node; skip
75006                   continue;
75007                 }
75008
75009                 nA = graph.hasEntity(nAId);
75010                 if (!nA) continue;
75011                 nB = graph.hasEntity(nBId);
75012                 if (!nB) continue;
75013                 segment1 = [n1.loc, n2.loc];
75014                 segment2 = [nA.loc, nB.loc];
75015                 var point = geoLineIntersection(segment1, segment2);
75016
75017                 if (point) {
75018                   edgeCrossInfos.push({
75019                     wayInfos: [{
75020                       way: way1,
75021                       featureType: way1FeatureType,
75022                       edge: [n1.id, n2.id]
75023                     }, {
75024                       way: way2,
75025                       featureType: way2FeatureType,
75026                       edge: [nA.id, nB.id]
75027                     }],
75028                     crossPoint: point
75029                   });
75030
75031                   if (oneOnly) {
75032                     checkedSingleCrossingWays[way2.id] = true;
75033                     break;
75034                   }
75035                 }
75036               }
75037             }
75038
75039             return edgeCrossInfos;
75040           }
75041
75042           function waysToCheck(entity, graph) {
75043             var featureType = getFeatureType(entity, graph);
75044             if (!featureType) return [];
75045
75046             if (entity.type === 'way') {
75047               return [entity];
75048             } else if (entity.type === 'relation') {
75049               return entity.members.reduce(function (array, member) {
75050                 if (member.type === 'way' && ( // only look at geometry ways
75051                 !member.role || member.role === 'outer' || member.role === 'inner')) {
75052                   var entity = graph.hasEntity(member.id); // don't add duplicates
75053
75054                   if (entity && array.indexOf(entity) === -1) {
75055                     array.push(entity);
75056                   }
75057                 }
75058
75059                 return array;
75060               }, []);
75061             }
75062
75063             return [];
75064           }
75065
75066           var validation = function checkCrossingWays(entity, graph) {
75067             var tree = context.history().tree();
75068             var ways = waysToCheck(entity, graph);
75069             var issues = []; // declare these here to reduce garbage collection
75070
75071             var wayIndex, crossingIndex, crossings;
75072
75073             for (wayIndex in ways) {
75074               crossings = findCrossingsByWay(ways[wayIndex], graph, tree);
75075
75076               for (crossingIndex in crossings) {
75077                 issues.push(createIssue(crossings[crossingIndex], graph));
75078               }
75079             }
75080
75081             return issues;
75082           };
75083
75084           function createIssue(crossing, graph) {
75085             // use the entities with the tags that define the feature type
75086             crossing.wayInfos.sort(function (way1Info, way2Info) {
75087               var type1 = way1Info.featureType;
75088               var type2 = way2Info.featureType;
75089
75090               if (type1 === type2) {
75091                 return utilDisplayLabel(way1Info.way, graph) > utilDisplayLabel(way2Info.way, graph);
75092               } else if (type1 === 'waterway') {
75093                 return true;
75094               } else if (type2 === 'waterway') {
75095                 return false;
75096               }
75097
75098               return type1 < type2;
75099             });
75100             var entities = crossing.wayInfos.map(function (wayInfo) {
75101               return getFeatureWithFeatureTypeTagsForWay(wayInfo.way, graph);
75102             });
75103             var edges = [crossing.wayInfos[0].edge, crossing.wayInfos[1].edge];
75104             var featureTypes = [crossing.wayInfos[0].featureType, crossing.wayInfos[1].featureType];
75105             var connectionTags = tagsForConnectionNodeIfAllowed(entities[0], entities[1], graph);
75106             var featureType1 = crossing.wayInfos[0].featureType;
75107             var featureType2 = crossing.wayInfos[1].featureType;
75108             var isCrossingIndoors = taggedAsIndoor(entities[0].tags) && taggedAsIndoor(entities[1].tags);
75109             var isCrossingTunnels = allowsTunnel(featureType1) && hasTag(entities[0].tags, 'tunnel') && allowsTunnel(featureType2) && hasTag(entities[1].tags, 'tunnel');
75110             var isCrossingBridges = allowsBridge(featureType1) && hasTag(entities[0].tags, 'bridge') && allowsBridge(featureType2) && hasTag(entities[1].tags, 'bridge');
75111             var subtype = [featureType1, featureType2].sort().join('-');
75112             var crossingTypeID = subtype;
75113
75114             if (isCrossingIndoors) {
75115               crossingTypeID = 'indoor-indoor';
75116             } else if (isCrossingTunnels) {
75117               crossingTypeID = 'tunnel-tunnel';
75118             } else if (isCrossingBridges) {
75119               crossingTypeID = 'bridge-bridge';
75120             }
75121
75122             if (connectionTags && (isCrossingIndoors || isCrossingTunnels || isCrossingBridges)) {
75123               crossingTypeID += '_connectable';
75124             } // Differentiate based on the loc rounded to 4 digits, since two ways can cross multiple times.
75125
75126
75127             var uniqueID = crossing.crossPoint[0].toFixed(4) + ',' + crossing.crossPoint[1].toFixed(4);
75128             return new validationIssue({
75129               type: type,
75130               subtype: subtype,
75131               severity: 'warning',
75132               message: function message(context) {
75133                 var graph = context.graph();
75134                 var entity1 = graph.hasEntity(this.entityIds[0]),
75135                     entity2 = graph.hasEntity(this.entityIds[1]);
75136                 return entity1 && entity2 ? _t.html('issues.crossing_ways.message', {
75137                   feature: utilDisplayLabel(entity1, graph),
75138                   feature2: utilDisplayLabel(entity2, graph)
75139                 }) : '';
75140               },
75141               reference: showReference,
75142               entityIds: entities.map(function (entity) {
75143                 return entity.id;
75144               }),
75145               data: {
75146                 edges: edges,
75147                 featureTypes: featureTypes,
75148                 connectionTags: connectionTags
75149               },
75150               hash: uniqueID,
75151               loc: crossing.crossPoint,
75152               dynamicFixes: function dynamicFixes(context) {
75153                 var mode = context.mode();
75154                 if (!mode || mode.id !== 'select' || mode.selectedIDs().length !== 1) return [];
75155                 var selectedIndex = this.entityIds[0] === mode.selectedIDs()[0] ? 0 : 1;
75156                 var selectedFeatureType = this.data.featureTypes[selectedIndex];
75157                 var otherFeatureType = this.data.featureTypes[selectedIndex === 0 ? 1 : 0];
75158                 var fixes = [];
75159
75160                 if (connectionTags) {
75161                   fixes.push(makeConnectWaysFix(this.data.connectionTags));
75162                 }
75163
75164                 if (isCrossingIndoors) {
75165                   fixes.push(new validationIssueFix({
75166                     icon: 'iD-icon-layers',
75167                     title: _t.html('issues.fix.use_different_levels.title')
75168                   }));
75169                 } else if (isCrossingTunnels || isCrossingBridges || featureType1 === 'building' || featureType2 === 'building') {
75170                   fixes.push(makeChangeLayerFix('higher'));
75171                   fixes.push(makeChangeLayerFix('lower')); // can only add bridge/tunnel if both features are lines
75172                 } else if (context.graph().geometry(this.entityIds[0]) === 'line' && context.graph().geometry(this.entityIds[1]) === 'line') {
75173                   // don't recommend adding bridges to waterways since they're uncommon
75174                   if (allowsBridge(selectedFeatureType) && selectedFeatureType !== 'waterway') {
75175                     fixes.push(makeAddBridgeOrTunnelFix('add_a_bridge', 'temaki-bridge', 'bridge'));
75176                   } // don't recommend adding tunnels under waterways since they're uncommon
75177
75178
75179                   var skipTunnelFix = otherFeatureType === 'waterway' && selectedFeatureType !== 'waterway';
75180
75181                   if (allowsTunnel(selectedFeatureType) && !skipTunnelFix) {
75182                     fixes.push(makeAddBridgeOrTunnelFix('add_a_tunnel', 'temaki-tunnel', 'tunnel'));
75183                   }
75184                 } // repositioning the features is always an option
75185
75186
75187                 fixes.push(new validationIssueFix({
75188                   icon: 'iD-operation-move',
75189                   title: _t.html('issues.fix.reposition_features.title')
75190                 }));
75191                 return fixes;
75192               }
75193             });
75194
75195             function showReference(selection) {
75196               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.crossing_ways.' + crossingTypeID + '.reference'));
75197             }
75198           }
75199
75200           function makeAddBridgeOrTunnelFix(fixTitleID, iconName, bridgeOrTunnel) {
75201             return new validationIssueFix({
75202               icon: iconName,
75203               title: _t.html('issues.fix.' + fixTitleID + '.title'),
75204               onClick: function onClick(context) {
75205                 var mode = context.mode();
75206                 if (!mode || mode.id !== 'select') return;
75207                 var selectedIDs = mode.selectedIDs();
75208                 if (selectedIDs.length !== 1) return;
75209                 var selectedWayID = selectedIDs[0];
75210                 if (!context.hasEntity(selectedWayID)) return;
75211                 var resultWayIDs = [selectedWayID];
75212                 var edge, crossedEdge, crossedWayID;
75213
75214                 if (this.issue.entityIds[0] === selectedWayID) {
75215                   edge = this.issue.data.edges[0];
75216                   crossedEdge = this.issue.data.edges[1];
75217                   crossedWayID = this.issue.entityIds[1];
75218                 } else {
75219                   edge = this.issue.data.edges[1];
75220                   crossedEdge = this.issue.data.edges[0];
75221                   crossedWayID = this.issue.entityIds[0];
75222                 }
75223
75224                 var crossingLoc = this.issue.loc;
75225                 var projection = context.projection;
75226
75227                 var action = function actionAddStructure(graph) {
75228                   var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])];
75229                   var crossedWay = graph.hasEntity(crossedWayID); // use the explicit width of the crossed feature as the structure length, if available
75230
75231                   var structLengthMeters = crossedWay && crossedWay.tags.width && parseFloat(crossedWay.tags.width);
75232
75233                   if (!structLengthMeters) {
75234                     // if no explicit width is set, approximate the width based on the tags
75235                     structLengthMeters = crossedWay && crossedWay.impliedLineWidthMeters();
75236                   }
75237
75238                   if (structLengthMeters) {
75239                     if (getFeatureType(crossedWay, graph) === 'railway') {
75240                       // bridges over railways are generally much longer than the rail bed itself, compensate
75241                       structLengthMeters *= 2;
75242                     }
75243                   } else {
75244                     // should ideally never land here since all rail/water/road tags should have an implied width
75245                     structLengthMeters = 8;
75246                   }
75247
75248                   var a1 = geoAngle(edgeNodes[0], edgeNodes[1], projection) + Math.PI;
75249                   var a2 = geoAngle(graph.entity(crossedEdge[0]), graph.entity(crossedEdge[1]), projection) + Math.PI;
75250                   var crossingAngle = Math.max(a1, a2) - Math.min(a1, a2);
75251                   if (crossingAngle > Math.PI) crossingAngle -= Math.PI; // lengthen the structure to account for the angle of the crossing
75252
75253                   structLengthMeters = structLengthMeters / 2 / Math.sin(crossingAngle) * 2; // add padding since the structure must extend past the edges of the crossed feature
75254
75255                   structLengthMeters += 4; // clamp the length to a reasonable range
75256
75257                   structLengthMeters = Math.min(Math.max(structLengthMeters, 4), 50);
75258
75259                   function geomToProj(geoPoint) {
75260                     return [geoLonToMeters(geoPoint[0], geoPoint[1]), geoLatToMeters(geoPoint[1])];
75261                   }
75262
75263                   function projToGeom(projPoint) {
75264                     var lat = geoMetersToLat(projPoint[1]);
75265                     return [geoMetersToLon(projPoint[0], lat), lat];
75266                   }
75267
75268                   var projEdgeNode1 = geomToProj(edgeNodes[0].loc);
75269                   var projEdgeNode2 = geomToProj(edgeNodes[1].loc);
75270                   var projectedAngle = geoVecAngle(projEdgeNode1, projEdgeNode2);
75271                   var projectedCrossingLoc = geomToProj(crossingLoc);
75272                   var linearToSphericalMetersRatio = geoVecLength(projEdgeNode1, projEdgeNode2) / geoSphericalDistance(edgeNodes[0].loc, edgeNodes[1].loc);
75273
75274                   function locSphericalDistanceFromCrossingLoc(angle, distanceMeters) {
75275                     var lengthSphericalMeters = distanceMeters * linearToSphericalMetersRatio;
75276                     return projToGeom([projectedCrossingLoc[0] + Math.cos(angle) * lengthSphericalMeters, projectedCrossingLoc[1] + Math.sin(angle) * lengthSphericalMeters]);
75277                   }
75278
75279                   var endpointLocGetter1 = function endpointLocGetter1(lengthMeters) {
75280                     return locSphericalDistanceFromCrossingLoc(projectedAngle, lengthMeters);
75281                   };
75282
75283                   var endpointLocGetter2 = function endpointLocGetter2(lengthMeters) {
75284                     return locSphericalDistanceFromCrossingLoc(projectedAngle + Math.PI, lengthMeters);
75285                   }; // avoid creating very short edges from splitting too close to another node
75286
75287
75288                   var minEdgeLengthMeters = 0.55; // decide where to bound the structure along the way, splitting as necessary
75289
75290                   function determineEndpoint(edge, endNode, locGetter) {
75291                     var newNode;
75292                     var idealLengthMeters = structLengthMeters / 2; // distance between the crossing location and the end of the edge,
75293                     // the maximum length of this side of the structure
75294
75295                     var crossingToEdgeEndDistance = geoSphericalDistance(crossingLoc, endNode.loc);
75296
75297                     if (crossingToEdgeEndDistance - idealLengthMeters > minEdgeLengthMeters) {
75298                       // the edge is long enough to insert a new node
75299                       // the loc that would result in the full expected length
75300                       var idealNodeLoc = locGetter(idealLengthMeters);
75301                       newNode = osmNode();
75302                       graph = actionAddMidpoint({
75303                         loc: idealNodeLoc,
75304                         edge: edge
75305                       }, newNode)(graph);
75306                     } else {
75307                       var edgeCount = 0;
75308                       endNode.parentIntersectionWays(graph).forEach(function (way) {
75309                         way.nodes.forEach(function (nodeID) {
75310                           if (nodeID === endNode.id) {
75311                             if (endNode.id === way.first() && endNode.id !== way.last() || endNode.id === way.last() && endNode.id !== way.first()) {
75312                               edgeCount += 1;
75313                             } else {
75314                               edgeCount += 2;
75315                             }
75316                           }
75317                         });
75318                       });
75319
75320                       if (edgeCount >= 3) {
75321                         // the end node is a junction, try to leave a segment
75322                         // between it and the structure - #7202
75323                         var insetLength = crossingToEdgeEndDistance - minEdgeLengthMeters;
75324
75325                         if (insetLength > minEdgeLengthMeters) {
75326                           var insetNodeLoc = locGetter(insetLength);
75327                           newNode = osmNode();
75328                           graph = actionAddMidpoint({
75329                             loc: insetNodeLoc,
75330                             edge: edge
75331                           }, newNode)(graph);
75332                         }
75333                       }
75334                     } // if the edge is too short to subdivide as desired, then
75335                     // just bound the structure at the existing end node
75336
75337
75338                     if (!newNode) newNode = endNode;
75339                     var splitAction = actionSplit([newNode.id]).limitWays(resultWayIDs); // only split selected or created ways
75340                     // do the split
75341
75342                     graph = splitAction(graph);
75343
75344                     if (splitAction.getCreatedWayIDs().length) {
75345                       resultWayIDs.push(splitAction.getCreatedWayIDs()[0]);
75346                     }
75347
75348                     return newNode;
75349                   }
75350
75351                   var structEndNode1 = determineEndpoint(edge, edgeNodes[1], endpointLocGetter1);
75352                   var structEndNode2 = determineEndpoint([edgeNodes[0].id, structEndNode1.id], edgeNodes[0], endpointLocGetter2);
75353                   var structureWay = resultWayIDs.map(function (id) {
75354                     return graph.entity(id);
75355                   }).find(function (way) {
75356                     return way.nodes.indexOf(structEndNode1.id) !== -1 && way.nodes.indexOf(structEndNode2.id) !== -1;
75357                   });
75358                   var tags = Object.assign({}, structureWay.tags); // copy tags
75359
75360                   if (bridgeOrTunnel === 'bridge') {
75361                     tags.bridge = 'yes';
75362                     tags.layer = '1';
75363                   } else {
75364                     var tunnelValue = 'yes';
75365
75366                     if (getFeatureType(structureWay, graph) === 'waterway') {
75367                       // use `tunnel=culvert` for waterways by default
75368                       tunnelValue = 'culvert';
75369                     }
75370
75371                     tags.tunnel = tunnelValue;
75372                     tags.layer = '-1';
75373                   } // apply the structure tags to the way
75374
75375
75376                   graph = actionChangeTags(structureWay.id, tags)(graph);
75377                   return graph;
75378                 };
75379
75380                 context.perform(action, _t('issues.fix.' + fixTitleID + '.annotation'));
75381                 context.enter(modeSelect(context, resultWayIDs));
75382               }
75383             });
75384           }
75385
75386           function makeConnectWaysFix(connectionTags) {
75387             var fixTitleID = 'connect_features';
75388
75389             if (connectionTags.ford) {
75390               fixTitleID = 'connect_using_ford';
75391             }
75392
75393             return new validationIssueFix({
75394               icon: 'iD-icon-crossing',
75395               title: _t.html('issues.fix.' + fixTitleID + '.title'),
75396               onClick: function onClick(context) {
75397                 var loc = this.issue.loc;
75398                 var connectionTags = this.issue.data.connectionTags;
75399                 var edges = this.issue.data.edges;
75400                 context.perform(function actionConnectCrossingWays(graph) {
75401                   // create the new node for the points
75402                   var node = osmNode({
75403                     loc: loc,
75404                     tags: connectionTags
75405                   });
75406                   graph = graph.replace(node);
75407                   var nodesToMerge = [node.id];
75408                   var mergeThresholdInMeters = 0.75;
75409                   edges.forEach(function (edge) {
75410                     var edgeNodes = [graph.entity(edge[0]), graph.entity(edge[1])];
75411                     var nearby = geoSphericalClosestNode(edgeNodes, loc); // if there is already a suitable node nearby, use that
75412                     // use the node if node has no interesting tags or if it is a crossing node #8326
75413
75414                     if ((!nearby.node.hasInterestingTags() || nearby.node.isCrossing()) && nearby.distance < mergeThresholdInMeters) {
75415                       nodesToMerge.push(nearby.node.id); // else add the new node to the way
75416                     } else {
75417                       graph = actionAddMidpoint({
75418                         loc: loc,
75419                         edge: edge
75420                       }, node)(graph);
75421                     }
75422                   });
75423
75424                   if (nodesToMerge.length > 1) {
75425                     // if we're using nearby nodes, merge them with the new node
75426                     graph = actionMergeNodes(nodesToMerge, loc)(graph);
75427                   }
75428
75429                   return graph;
75430                 }, _t('issues.fix.connect_crossing_features.annotation'));
75431               }
75432             });
75433           }
75434
75435           function makeChangeLayerFix(higherOrLower) {
75436             return new validationIssueFix({
75437               icon: 'iD-icon-' + (higherOrLower === 'higher' ? 'up' : 'down'),
75438               title: _t.html('issues.fix.tag_this_as_' + higherOrLower + '.title'),
75439               onClick: function onClick(context) {
75440                 var mode = context.mode();
75441                 if (!mode || mode.id !== 'select') return;
75442                 var selectedIDs = mode.selectedIDs();
75443                 if (selectedIDs.length !== 1) return;
75444                 var selectedID = selectedIDs[0];
75445                 if (!this.issue.entityIds.some(function (entityId) {
75446                   return entityId === selectedID;
75447                 })) return;
75448                 var entity = context.hasEntity(selectedID);
75449                 if (!entity) return;
75450                 var tags = Object.assign({}, entity.tags); // shallow copy
75451
75452                 var layer = tags.layer && Number(tags.layer);
75453
75454                 if (layer && !isNaN(layer)) {
75455                   if (higherOrLower === 'higher') {
75456                     layer += 1;
75457                   } else {
75458                     layer -= 1;
75459                   }
75460                 } else {
75461                   if (higherOrLower === 'higher') {
75462                     layer = 1;
75463                   } else {
75464                     layer = -1;
75465                   }
75466                 }
75467
75468                 tags.layer = layer.toString();
75469                 context.perform(actionChangeTags(entity.id, tags), _t('operations.change_tags.annotation'));
75470               }
75471             });
75472           }
75473
75474           validation.type = type;
75475           return validation;
75476         }
75477
75478         function behaviorDrawWay(context, wayID, mode, startGraph) {
75479           var keybinding = utilKeybinding('drawWay');
75480           var dispatch = dispatch$8('rejectedSelfIntersection');
75481           var behavior = behaviorDraw(context); // Must be set by `drawWay.nodeIndex` before each install of this behavior.
75482
75483           var _nodeIndex;
75484
75485           var _origWay;
75486
75487           var _wayGeometry;
75488
75489           var _headNodeID;
75490
75491           var _annotation;
75492
75493           var _pointerHasMoved = false; // The osmNode to be placed.
75494           // This is temporary and just follows the mouse cursor until an "add" event occurs.
75495
75496           var _drawNode;
75497
75498           var _didResolveTempEdit = false;
75499
75500           function createDrawNode(loc) {
75501             // don't make the draw node until we actually need it
75502             _drawNode = osmNode({
75503               loc: loc
75504             });
75505             context.pauseChangeDispatch();
75506             context.replace(function actionAddDrawNode(graph) {
75507               // add the draw node to the graph and insert it into the way
75508               var way = graph.entity(wayID);
75509               return graph.replace(_drawNode).replace(way.addNode(_drawNode.id, _nodeIndex));
75510             }, _annotation);
75511             context.resumeChangeDispatch();
75512             setActiveElements();
75513           }
75514
75515           function removeDrawNode() {
75516             context.pauseChangeDispatch();
75517             context.replace(function actionDeleteDrawNode(graph) {
75518               var way = graph.entity(wayID);
75519               return graph.replace(way.removeNode(_drawNode.id)).remove(_drawNode);
75520             }, _annotation);
75521             _drawNode = undefined;
75522             context.resumeChangeDispatch();
75523           }
75524
75525           function keydown(d3_event) {
75526             if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
75527               if (context.surface().classed('nope')) {
75528                 context.surface().classed('nope-suppressed', true);
75529               }
75530
75531               context.surface().classed('nope', false).classed('nope-disabled', true);
75532             }
75533           }
75534
75535           function keyup(d3_event) {
75536             if (d3_event.keyCode === utilKeybinding.modifierCodes.alt) {
75537               if (context.surface().classed('nope-suppressed')) {
75538                 context.surface().classed('nope', true);
75539               }
75540
75541               context.surface().classed('nope-suppressed', false).classed('nope-disabled', false);
75542             }
75543           }
75544
75545           function allowsVertex(d) {
75546             return d.geometry(context.graph()) === 'vertex' || _mainPresetIndex.allowsVertex(d, context.graph());
75547           } // related code
75548           // - `mode/drag_node.js`     `doMove()`
75549           // - `behavior/draw.js`      `click()`
75550           // - `behavior/draw_way.js`  `move()`
75551
75552
75553           function move(d3_event, datum) {
75554             var loc = context.map().mouseCoordinates();
75555             if (!_drawNode) createDrawNode(loc);
75556             context.surface().classed('nope-disabled', d3_event.altKey);
75557             var targetLoc = datum && datum.properties && datum.properties.entity && allowsVertex(datum.properties.entity) && datum.properties.entity.loc;
75558             var targetNodes = datum && datum.properties && datum.properties.nodes;
75559
75560             if (targetLoc) {
75561               // snap to node/vertex - a point target with `.loc`
75562               loc = targetLoc;
75563             } else if (targetNodes) {
75564               // snap to way - a line target with `.nodes`
75565               var choice = geoChooseEdge(targetNodes, context.map().mouse(), context.projection, _drawNode.id);
75566
75567               if (choice) {
75568                 loc = choice.loc;
75569               }
75570             }
75571
75572             context.replace(actionMoveNode(_drawNode.id, loc), _annotation);
75573             _drawNode = context.entity(_drawNode.id);
75574             checkGeometry(true
75575             /* includeDrawNode */
75576             );
75577           } // Check whether this edit causes the geometry to break.
75578           // If so, class the surface with a nope cursor.
75579           // `includeDrawNode` - Only check the relevant line segments if finishing drawing
75580
75581
75582           function checkGeometry(includeDrawNode) {
75583             var nopeDisabled = context.surface().classed('nope-disabled');
75584             var isInvalid = isInvalidGeometry(includeDrawNode);
75585
75586             if (nopeDisabled) {
75587               context.surface().classed('nope', false).classed('nope-suppressed', isInvalid);
75588             } else {
75589               context.surface().classed('nope', isInvalid).classed('nope-suppressed', false);
75590             }
75591           }
75592
75593           function isInvalidGeometry(includeDrawNode) {
75594             var testNode = _drawNode; // we only need to test the single way we're drawing
75595
75596             var parentWay = context.graph().entity(wayID);
75597             var nodes = context.graph().childNodes(parentWay).slice(); // shallow copy
75598
75599             if (includeDrawNode) {
75600               if (parentWay.isClosed()) {
75601                 // don't test the last segment for closed ways - #4655
75602                 // (still test the first segment)
75603                 nodes.pop();
75604               }
75605             } else {
75606               // discount the draw node
75607               if (parentWay.isClosed()) {
75608                 if (nodes.length < 3) return false;
75609                 if (_drawNode) nodes.splice(-2, 1);
75610                 testNode = nodes[nodes.length - 2];
75611               } else {
75612                 // there's nothing we need to test if we ignore the draw node on open ways
75613                 return false;
75614               }
75615             }
75616
75617             return testNode && geoHasSelfIntersections(nodes, testNode.id);
75618           }
75619
75620           function undone() {
75621             // undoing removed the temp edit
75622             _didResolveTempEdit = true;
75623             context.pauseChangeDispatch();
75624             var nextMode;
75625
75626             if (context.graph() === startGraph) {
75627               // We've undone back to the initial state before we started drawing.
75628               // Just exit the draw mode without undoing whatever we did before
75629               // we entered the draw mode.
75630               nextMode = modeSelect(context, [wayID]);
75631             } else {
75632               // The `undo` only removed the temporary edit, so here we have to
75633               // manually undo to actually remove the last node we added. We can't
75634               // use the `undo` function since the initial "add" graph doesn't have
75635               // an annotation and so cannot be undone to.
75636               context.pop(1); // continue drawing
75637
75638               nextMode = mode;
75639             } // clear the redo stack by adding and removing a blank edit
75640
75641
75642             context.perform(actionNoop());
75643             context.pop(1);
75644             context.resumeChangeDispatch();
75645             context.enter(nextMode);
75646           }
75647
75648           function setActiveElements() {
75649             if (!_drawNode) return;
75650             context.surface().selectAll('.' + _drawNode.id).classed('active', true);
75651           }
75652
75653           function resetToStartGraph() {
75654             while (context.graph() !== startGraph) {
75655               context.pop();
75656             }
75657           }
75658
75659           var drawWay = function drawWay(surface) {
75660             _drawNode = undefined;
75661             _didResolveTempEdit = false;
75662             _origWay = context.entity(wayID);
75663
75664             if (typeof _nodeIndex === 'number') {
75665               _headNodeID = _origWay.nodes[_nodeIndex];
75666             } else if (_origWay.isClosed()) {
75667               _headNodeID = _origWay.nodes[_origWay.nodes.length - 2];
75668             } else {
75669               _headNodeID = _origWay.nodes[_origWay.nodes.length - 1];
75670             }
75671
75672             _wayGeometry = _origWay.geometry(context.graph());
75673             _annotation = _t((_origWay.nodes.length === (_origWay.isClosed() ? 2 : 1) ? 'operations.start.annotation.' : 'operations.continue.annotation.') + _wayGeometry);
75674             _pointerHasMoved = false; // Push an annotated state for undo to return back to.
75675             // We must make sure to replace or remove it later.
75676
75677             context.pauseChangeDispatch();
75678             context.perform(actionNoop(), _annotation);
75679             context.resumeChangeDispatch();
75680             behavior.hover().initialNodeID(_headNodeID);
75681             behavior.on('move', function () {
75682               _pointerHasMoved = true;
75683               move.apply(this, arguments);
75684             }).on('down', function () {
75685               move.apply(this, arguments);
75686             }).on('downcancel', function () {
75687               if (_drawNode) removeDrawNode();
75688             }).on('click', drawWay.add).on('clickWay', drawWay.addWay).on('clickNode', drawWay.addNode).on('undo', context.undo).on('cancel', drawWay.cancel).on('finish', drawWay.finish);
75689             select(window).on('keydown.drawWay', keydown).on('keyup.drawWay', keyup);
75690             context.map().dblclickZoomEnable(false).on('drawn.draw', setActiveElements);
75691             setActiveElements();
75692             surface.call(behavior);
75693             context.history().on('undone.draw', undone);
75694           };
75695
75696           drawWay.off = function (surface) {
75697             if (!_didResolveTempEdit) {
75698               // Drawing was interrupted unexpectedly.
75699               // This can happen if the user changes modes,
75700               // clicks geolocate button, a hashchange event occurs, etc.
75701               context.pauseChangeDispatch();
75702               resetToStartGraph();
75703               context.resumeChangeDispatch();
75704             }
75705
75706             _drawNode = undefined;
75707             _nodeIndex = undefined;
75708             context.map().on('drawn.draw', null);
75709             surface.call(behavior.off).selectAll('.active').classed('active', false);
75710             surface.classed('nope', false).classed('nope-suppressed', false).classed('nope-disabled', false);
75711             select(window).on('keydown.drawWay', null).on('keyup.drawWay', null);
75712             context.history().on('undone.draw', null);
75713           };
75714
75715           function attemptAdd(d, loc, doAdd) {
75716             if (_drawNode) {
75717               // move the node to the final loc in case move wasn't called
75718               // consistently (e.g. on touch devices)
75719               context.replace(actionMoveNode(_drawNode.id, loc), _annotation);
75720               _drawNode = context.entity(_drawNode.id);
75721             } else {
75722               createDrawNode(loc);
75723             }
75724
75725             checkGeometry(true
75726             /* includeDrawNode */
75727             );
75728
75729             if (d && d.properties && d.properties.nope || context.surface().classed('nope')) {
75730               if (!_pointerHasMoved) {
75731                 // prevent the temporary draw node from appearing on touch devices
75732                 removeDrawNode();
75733               }
75734
75735               dispatch.call('rejectedSelfIntersection', this);
75736               return; // can't click here
75737             }
75738
75739             context.pauseChangeDispatch();
75740             doAdd(); // we just replaced the temporary edit with the real one
75741
75742             _didResolveTempEdit = true;
75743             context.resumeChangeDispatch();
75744             context.enter(mode);
75745           } // Accept the current position of the drawing node
75746
75747
75748           drawWay.add = function (loc, d) {
75749             attemptAdd(d, loc, function () {// don't need to do anything extra
75750             });
75751           }; // Connect the way to an existing way
75752
75753
75754           drawWay.addWay = function (loc, edge, d) {
75755             attemptAdd(d, loc, function () {
75756               context.replace(actionAddMidpoint({
75757                 loc: loc,
75758                 edge: edge
75759               }, _drawNode), _annotation);
75760             });
75761           }; // Connect the way to an existing node
75762
75763
75764           drawWay.addNode = function (node, d) {
75765             // finish drawing if the mapper targets the prior node
75766             if (node.id === _headNodeID || // or the first node when drawing an area
75767             _origWay.isClosed() && node.id === _origWay.first()) {
75768               drawWay.finish();
75769               return;
75770             }
75771
75772             attemptAdd(d, node.loc, function () {
75773               context.replace(function actionReplaceDrawNode(graph) {
75774                 // remove the temporary draw node and insert the existing node
75775                 // at the same index
75776                 graph = graph.replace(graph.entity(wayID).removeNode(_drawNode.id)).remove(_drawNode);
75777                 return graph.replace(graph.entity(wayID).addNode(node.id, _nodeIndex));
75778               }, _annotation);
75779             });
75780           };
75781           /**
75782            * @param {(typeof osmWay)[]} ways
75783            * @returns {"line" | "area" | "generic"}
75784            */
75785
75786
75787           function getFeatureType(ways) {
75788             if (ways.every(function (way) {
75789               return way.isClosed();
75790             })) return 'area';
75791             if (ways.every(function (way) {
75792               return !way.isClosed();
75793             })) return 'line';
75794             return 'generic';
75795           }
75796           /** see PR #8671 */
75797
75798
75799           function followMode() {
75800             if (_didResolveTempEdit) return;
75801
75802             try {
75803               // get the last 2 added nodes.
75804               // check if they are both part of only oneway (the same one)
75805               // check if the ways that they're part of are the same way
75806               // find index of the last two nodes, to determine the direction to travel around the existing way
75807               // add the next node to the way we are drawing
75808               // if we're drawing an area, the first node = last node.
75809               var isDrawingArea = _origWay.nodes[0] === _origWay.nodes.slice(-1)[0];
75810
75811               var _origWay$nodes$slice = _origWay.nodes.slice(isDrawingArea ? -3 : -2),
75812                   _origWay$nodes$slice2 = _slicedToArray(_origWay$nodes$slice, 2),
75813                   secondLastNodeId = _origWay$nodes$slice2[0],
75814                   lastNodeId = _origWay$nodes$slice2[1]; // Unlike startGraph, the full history graph may contain unsaved vertices to follow.
75815               // https://github.com/openstreetmap/iD/issues/8749
75816
75817
75818               var historyGraph = context.history().graph();
75819
75820               if (!lastNodeId || !secondLastNodeId || !historyGraph.hasEntity(lastNodeId) || !historyGraph.hasEntity(secondLastNodeId)) {
75821                 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html('operations.follow.error.needs_more_initial_nodes'))();
75822                 return;
75823               } // If the way has looped over itself, follow some other way.
75824
75825
75826               var lastNodesParents = historyGraph.parentWays(historyGraph.entity(lastNodeId)).filter(function (w) {
75827                 return w.id !== wayID;
75828               });
75829               var secondLastNodesParents = historyGraph.parentWays(historyGraph.entity(secondLastNodeId)).filter(function (w) {
75830                 return w.id !== wayID;
75831               });
75832               var featureType = getFeatureType(lastNodesParents);
75833
75834               if (lastNodesParents.length !== 1 || secondLastNodesParents.length === 0) {
75835                 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html("operations.follow.error.intersection_of_multiple_ways.".concat(featureType)))();
75836                 return;
75837               } // Check if the last node's parent is also the parent of the second last node.
75838               // The last node must only have one parent, but the second last node can have
75839               // multiple parents.
75840
75841
75842               if (!secondLastNodesParents.some(function (n) {
75843                 return n.id === lastNodesParents[0].id;
75844               })) {
75845                 context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html("operations.follow.error.intersection_of_different_ways.".concat(featureType)))();
75846                 return;
75847               }
75848
75849               var way = lastNodesParents[0];
75850               var indexOfLast = way.nodes.indexOf(lastNodeId);
75851               var indexOfSecondLast = way.nodes.indexOf(secondLastNodeId); // for a closed way, the first/last node is the same so it appears twice in the array,
75852               // but indexOf always finds the first occurrence. This is only an issue when following a way
75853               // in descending order
75854
75855               var isDescendingPastZero = indexOfLast === way.nodes.length - 2 && indexOfSecondLast === 0;
75856               var nextNodeIndex = indexOfLast + (indexOfLast > indexOfSecondLast && !isDescendingPastZero ? 1 : -1); // if we're following a closed way and we pass the first/last node, the  next index will be -1
75857
75858               if (nextNodeIndex === -1) nextNodeIndex = indexOfSecondLast === 1 ? way.nodes.length - 2 : 1;
75859               var nextNode = historyGraph.entity(way.nodes[nextNodeIndex]);
75860               drawWay.addNode(nextNode, {
75861                 geometry: {
75862                   type: 'Point',
75863                   coordinates: nextNode.loc
75864                 },
75865                 id: nextNode.id,
75866                 properties: {
75867                   target: true,
75868                   entity: nextNode
75869                 }
75870               });
75871             } catch (ex) {
75872               context.ui().flash.duration(4000).iconName('#iD-icon-no').label(_t.html('operations.follow.error.unknown'))();
75873             }
75874           }
75875
75876           keybinding.on(_t('operations.follow.key'), followMode);
75877           select(document).call(keybinding); // Finish the draw operation, removing the temporary edit.
75878           // If the way has enough nodes to be valid, it's selected.
75879           // Otherwise, delete everything and return to browse mode.
75880
75881           drawWay.finish = function () {
75882             checkGeometry(false
75883             /* includeDrawNode */
75884             );
75885
75886             if (context.surface().classed('nope')) {
75887               dispatch.call('rejectedSelfIntersection', this);
75888               return; // can't click here
75889             }
75890
75891             context.pauseChangeDispatch(); // remove the temporary edit
75892
75893             context.pop(1);
75894             _didResolveTempEdit = true;
75895             context.resumeChangeDispatch();
75896             var way = context.hasEntity(wayID);
75897
75898             if (!way || way.isDegenerate()) {
75899               drawWay.cancel();
75900               return;
75901             }
75902
75903             window.setTimeout(function () {
75904               context.map().dblclickZoomEnable(true);
75905             }, 1000);
75906             var isNewFeature = !mode.isContinuing;
75907             context.enter(modeSelect(context, [wayID]).newFeature(isNewFeature));
75908           }; // Cancel the draw operation, delete everything, and return to browse mode.
75909
75910
75911           drawWay.cancel = function () {
75912             context.pauseChangeDispatch();
75913             resetToStartGraph();
75914             context.resumeChangeDispatch();
75915             window.setTimeout(function () {
75916               context.map().dblclickZoomEnable(true);
75917             }, 1000);
75918             context.surface().classed('nope', false).classed('nope-disabled', false).classed('nope-suppressed', false);
75919             context.enter(modeBrowse(context));
75920           };
75921
75922           drawWay.nodeIndex = function (val) {
75923             if (!arguments.length) return _nodeIndex;
75924             _nodeIndex = val;
75925             return drawWay;
75926           };
75927
75928           drawWay.activeID = function () {
75929             if (!arguments.length) return _drawNode && _drawNode.id; // no assign
75930
75931             return drawWay;
75932           };
75933
75934           return utilRebind(drawWay, dispatch, 'on');
75935         }
75936
75937         function modeDrawLine(context, wayID, startGraph, button, affix, continuing) {
75938           var mode = {
75939             button: button,
75940             id: 'draw-line'
75941           };
75942           var behavior = behaviorDrawWay(context, wayID, mode, startGraph).on('rejectedSelfIntersection.modeDrawLine', function () {
75943             context.ui().flash.iconName('#iD-icon-no').label(_t.html('self_intersection.error.lines'))();
75944           });
75945           mode.wayID = wayID;
75946           mode.isContinuing = continuing;
75947
75948           mode.enter = function () {
75949             behavior.nodeIndex(affix === 'prefix' ? 0 : undefined);
75950             context.install(behavior);
75951           };
75952
75953           mode.exit = function () {
75954             context.uninstall(behavior);
75955           };
75956
75957           mode.selectedIDs = function () {
75958             return [wayID];
75959           };
75960
75961           mode.activeID = function () {
75962             return behavior && behavior.activeID() || [];
75963           };
75964
75965           return mode;
75966         }
75967
75968         function validationDisconnectedWay() {
75969           var type = 'disconnected_way';
75970
75971           function isTaggedAsHighway(entity) {
75972             return osmRoutableHighwayTagValues[entity.tags.highway];
75973           }
75974
75975           var validation = function checkDisconnectedWay(entity, graph) {
75976             var routingIslandWays = routingIslandForEntity(entity);
75977             if (!routingIslandWays) return [];
75978             return [new validationIssue({
75979               type: type,
75980               subtype: 'highway',
75981               severity: 'warning',
75982               message: function message(context) {
75983                 var entity = this.entityIds.length && context.hasEntity(this.entityIds[0]);
75984                 var label = entity && utilDisplayLabel(entity, context.graph());
75985                 return _t.html('issues.disconnected_way.routable.message', {
75986                   count: this.entityIds.length,
75987                   highway: label
75988                 });
75989               },
75990               reference: showReference,
75991               entityIds: Array.from(routingIslandWays).map(function (way) {
75992                 return way.id;
75993               }),
75994               dynamicFixes: makeFixes
75995             })];
75996
75997             function makeFixes(context) {
75998               var fixes = [];
75999               var singleEntity = this.entityIds.length === 1 && context.hasEntity(this.entityIds[0]);
76000
76001               if (singleEntity) {
76002                 if (singleEntity.type === 'way' && !singleEntity.isClosed()) {
76003                   var textDirection = _mainLocalizer.textDirection();
76004                   var startFix = makeContinueDrawingFixIfAllowed(textDirection, singleEntity.first(), 'start');
76005                   if (startFix) fixes.push(startFix);
76006                   var endFix = makeContinueDrawingFixIfAllowed(textDirection, singleEntity.last(), 'end');
76007                   if (endFix) fixes.push(endFix);
76008                 }
76009
76010                 if (!fixes.length) {
76011                   fixes.push(new validationIssueFix({
76012                     title: _t.html('issues.fix.connect_feature.title')
76013                   }));
76014                 }
76015
76016                 fixes.push(new validationIssueFix({
76017                   icon: 'iD-operation-delete',
76018                   title: _t.html('issues.fix.delete_feature.title'),
76019                   entityIds: [singleEntity.id],
76020                   onClick: function onClick(context) {
76021                     var id = this.issue.entityIds[0];
76022                     var operation = operationDelete(context, [id]);
76023
76024                     if (!operation.disabled()) {
76025                       operation();
76026                     }
76027                   }
76028                 }));
76029               } else {
76030                 fixes.push(new validationIssueFix({
76031                   title: _t.html('issues.fix.connect_features.title')
76032                 }));
76033               }
76034
76035               return fixes;
76036             }
76037
76038             function showReference(selection) {
76039               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.disconnected_way.routable.reference'));
76040             }
76041
76042             function routingIslandForEntity(entity) {
76043               var routingIsland = new Set(); // the interconnected routable features
76044
76045               var waysToCheck = []; // the queue of remaining routable ways to traverse
76046
76047               function queueParentWays(node) {
76048                 graph.parentWays(node).forEach(function (parentWay) {
76049                   if (!routingIsland.has(parentWay) && // only check each feature once
76050                   isRoutableWay(parentWay, false)) {
76051                     // only check routable features
76052                     routingIsland.add(parentWay);
76053                     waysToCheck.push(parentWay);
76054                   }
76055                 });
76056               }
76057
76058               if (entity.type === 'way' && isRoutableWay(entity, true)) {
76059                 routingIsland.add(entity);
76060                 waysToCheck.push(entity);
76061               } else if (entity.type === 'node' && isRoutableNode(entity)) {
76062                 routingIsland.add(entity);
76063                 queueParentWays(entity);
76064               } else {
76065                 // this feature isn't routable, cannot be a routing island
76066                 return null;
76067               }
76068
76069               while (waysToCheck.length) {
76070                 var wayToCheck = waysToCheck.pop();
76071                 var childNodes = graph.childNodes(wayToCheck);
76072
76073                 for (var i in childNodes) {
76074                   var vertex = childNodes[i];
76075
76076                   if (isConnectedVertex(vertex)) {
76077                     // found a link to the wider network, not a routing island
76078                     return null;
76079                   }
76080
76081                   if (isRoutableNode(vertex)) {
76082                     routingIsland.add(vertex);
76083                   }
76084
76085                   queueParentWays(vertex);
76086                 }
76087               } // no network link found, this is a routing island, return its members
76088
76089
76090               return routingIsland;
76091             }
76092
76093             function isConnectedVertex(vertex) {
76094               // assume ways overlapping unloaded tiles are connected to the wider road network  - #5938
76095               var osm = services.osm;
76096               if (osm && !osm.isDataLoaded(vertex.loc)) return true; // entrances are considered connected
76097
76098               if (vertex.tags.entrance && vertex.tags.entrance !== 'no') return true;
76099               if (vertex.tags.amenity === 'parking_entrance') return true;
76100               return false;
76101             }
76102
76103             function isRoutableNode(node) {
76104               // treat elevators as distinct features in the highway network
76105               if (node.tags.highway === 'elevator') return true;
76106               return false;
76107             }
76108
76109             function isRoutableWay(way, ignoreInnerWays) {
76110               if (isTaggedAsHighway(way) || way.tags.route === 'ferry') return true;
76111               return graph.parentRelations(way).some(function (parentRelation) {
76112                 if (parentRelation.tags.type === 'route' && parentRelation.tags.route === 'ferry') return true;
76113                 if (parentRelation.isMultipolygon() && isTaggedAsHighway(parentRelation) && (!ignoreInnerWays || parentRelation.memberById(way.id).role !== 'inner')) return true;
76114                 return false;
76115               });
76116             }
76117
76118             function makeContinueDrawingFixIfAllowed(textDirection, vertexID, whichEnd) {
76119               var vertex = graph.hasEntity(vertexID);
76120               if (!vertex || vertex.tags.noexit === 'yes') return null;
76121               var useLeftContinue = whichEnd === 'start' && textDirection === 'ltr' || whichEnd === 'end' && textDirection === 'rtl';
76122               return new validationIssueFix({
76123                 icon: 'iD-operation-continue' + (useLeftContinue ? '-left' : ''),
76124                 title: _t.html('issues.fix.continue_from_' + whichEnd + '.title'),
76125                 entityIds: [vertexID],
76126                 onClick: function onClick(context) {
76127                   var wayId = this.issue.entityIds[0];
76128                   var way = context.hasEntity(wayId);
76129                   var vertexId = this.entityIds[0];
76130                   var vertex = context.hasEntity(vertexId);
76131                   if (!way || !vertex) return; // make sure the vertex is actually visible and editable
76132
76133                   var map = context.map();
76134
76135                   if (!context.editable() || !map.trimmedExtent().contains(vertex.loc)) {
76136                     map.zoomToEase(vertex);
76137                   }
76138
76139                   context.enter(modeDrawLine(context, wayId, context.graph(), 'line', way.affix(vertexId), true));
76140                 }
76141               });
76142             }
76143           };
76144
76145           validation.type = type;
76146           return validation;
76147         }
76148
76149         function validationFormatting() {
76150           var type = 'invalid_format';
76151
76152           var validation = function validation(entity) {
76153             var issues = [];
76154
76155             function isValidEmail(email) {
76156               // Emails in OSM are going to be official so they should be pretty simple
76157               // Using negated lists to better support all possible unicode characters (#6494)
76158               var valid_email = /^[^\(\)\\,":;<>@\[\]]+@[^\(\)\\,":;<>@\[\]\.]+(?:\.[a-z0-9-]+)*$/i; // An empty value is also acceptable
76159
76160               return !email || valid_email.test(email);
76161             }
76162
76163             function showReferenceEmail(selection) {
76164               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.invalid_format.email.reference'));
76165             }
76166             /* see https://github.com/openstreetmap/iD/issues/6831#issuecomment-537121379
76167             function isSchemePresent(url) {
76168                 var valid_scheme = /^https?:\/\//i;
76169                 return (!url || valid_scheme.test(url));
76170             }
76171             function showReferenceWebsite(selection) {
76172                 selection.selectAll('.issue-reference')
76173                     .data([0])
76174                     .enter()
76175                     .append('div')
76176                     .attr('class', 'issue-reference')
76177                     .call(t.append('issues.invalid_format.website.reference'));
76178             }
76179              if (entity.tags.website) {
76180                 // Multiple websites are possible
76181                 // If ever we support ES6, arrow functions make this nicer
76182                 var websites = entity.tags.website
76183                     .split(';')
76184                     .map(function(s) { return s.trim(); })
76185                     .filter(function(x) { return !isSchemePresent(x); });
76186                  if (websites.length) {
76187                     issues.push(new validationIssue({
76188                         type: type,
76189                         subtype: 'website',
76190                         severity: 'warning',
76191                         message: function(context) {
76192                             var entity = context.hasEntity(this.entityIds[0]);
76193                             return entity ? t.html('issues.invalid_format.website.message' + this.data,
76194                                 { feature: utilDisplayLabel(entity, context.graph()), site: websites.join(', ') }) : '';
76195                         },
76196                         reference: showReferenceWebsite,
76197                         entityIds: [entity.id],
76198                         hash: websites.join(),
76199                         data: (websites.length > 1) ? '_multi' : ''
76200                     }));
76201                 }
76202             }*/
76203
76204
76205             if (entity.tags.email) {
76206               // Multiple emails are possible
76207               var emails = entity.tags.email.split(';').map(function (s) {
76208                 return s.trim();
76209               }).filter(function (x) {
76210                 return !isValidEmail(x);
76211               });
76212
76213               if (emails.length) {
76214                 issues.push(new validationIssue({
76215                   type: type,
76216                   subtype: 'email',
76217                   severity: 'warning',
76218                   message: function message(context) {
76219                     var entity = context.hasEntity(this.entityIds[0]);
76220                     return entity ? _t.html('issues.invalid_format.email.message' + this.data, {
76221                       feature: utilDisplayLabel(entity, context.graph()),
76222                       email: emails.join(', ')
76223                     }) : '';
76224                   },
76225                   reference: showReferenceEmail,
76226                   entityIds: [entity.id],
76227                   hash: emails.join(),
76228                   data: emails.length > 1 ? '_multi' : ''
76229                 }));
76230               }
76231             }
76232
76233             return issues;
76234           };
76235
76236           validation.type = type;
76237           return validation;
76238         }
76239
76240         function validationHelpRequest(context) {
76241           var type = 'help_request';
76242
76243           var validation = function checkFixmeTag(entity) {
76244             if (!entity.tags.fixme) return []; // don't flag fixmes on features added by the user
76245
76246             if (entity.version === undefined) return [];
76247
76248             if (entity.v !== undefined) {
76249               var baseEntity = context.history().base().hasEntity(entity.id); // don't flag fixmes added by the user on existing features
76250
76251               if (!baseEntity || !baseEntity.tags.fixme) return [];
76252             }
76253
76254             return [new validationIssue({
76255               type: type,
76256               subtype: 'fixme_tag',
76257               severity: 'warning',
76258               message: function message(context) {
76259                 var entity = context.hasEntity(this.entityIds[0]);
76260                 return entity ? _t.html('issues.fixme_tag.message', {
76261                   feature: utilDisplayLabel(entity, context.graph(), true
76262                   /* verbose */
76263                   )
76264                 }) : '';
76265               },
76266               dynamicFixes: function dynamicFixes() {
76267                 return [new validationIssueFix({
76268                   title: _t.html('issues.fix.address_the_concern.title')
76269                 })];
76270               },
76271               reference: showReference,
76272               entityIds: [entity.id]
76273             })];
76274
76275             function showReference(selection) {
76276               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.fixme_tag.reference'));
76277             }
76278           };
76279
76280           validation.type = type;
76281           return validation;
76282         }
76283
76284         function validationImpossibleOneway() {
76285           var type = 'impossible_oneway';
76286
76287           var validation = function checkImpossibleOneway(entity, graph) {
76288             if (entity.type !== 'way' || entity.geometry(graph) !== 'line') return [];
76289             if (entity.isClosed()) return [];
76290             if (!typeForWay(entity)) return [];
76291             if (!isOneway(entity)) return [];
76292             var firstIssues = issuesForNode(entity, entity.first());
76293             var lastIssues = issuesForNode(entity, entity.last());
76294             return firstIssues.concat(lastIssues);
76295
76296             function typeForWay(way) {
76297               if (way.geometry(graph) !== 'line') return null;
76298               if (osmRoutableHighwayTagValues[way.tags.highway]) return 'highway';
76299               if (osmFlowingWaterwayTagValues[way.tags.waterway]) return 'waterway';
76300               return null;
76301             }
76302
76303             function isOneway(way) {
76304               if (way.tags.oneway === 'yes') return true;
76305               if (way.tags.oneway) return false;
76306
76307               for (var key in way.tags) {
76308                 if (osmOneWayTags[key] && osmOneWayTags[key][way.tags[key]]) {
76309                   return true;
76310                 }
76311               }
76312
76313               return false;
76314             }
76315
76316             function nodeOccursMoreThanOnce(way, nodeID) {
76317               var occurrences = 0;
76318
76319               for (var index in way.nodes) {
76320                 if (way.nodes[index] === nodeID) {
76321                   occurrences += 1;
76322                   if (occurrences > 1) return true;
76323                 }
76324               }
76325
76326               return false;
76327             }
76328
76329             function isConnectedViaOtherTypes(way, node) {
76330               var wayType = typeForWay(way);
76331
76332               if (wayType === 'highway') {
76333                 // entrances are considered connected
76334                 if (node.tags.entrance && node.tags.entrance !== 'no') return true;
76335                 if (node.tags.amenity === 'parking_entrance') return true;
76336               } else if (wayType === 'waterway') {
76337                 if (node.id === way.first()) {
76338                   // multiple waterways may start at the same spring
76339                   if (node.tags.natural === 'spring') return true;
76340                 } else {
76341                   // multiple waterways may end at the same drain
76342                   if (node.tags.manhole === 'drain') return true;
76343                 }
76344               }
76345
76346               return graph.parentWays(node).some(function (parentWay) {
76347                 if (parentWay.id === way.id) return false;
76348
76349                 if (wayType === 'highway') {
76350                   // allow connections to highway areas
76351                   if (parentWay.geometry(graph) === 'area' && osmRoutableHighwayTagValues[parentWay.tags.highway]) return true; // count connections to ferry routes as connected
76352
76353                   if (parentWay.tags.route === 'ferry') return true;
76354                   return graph.parentRelations(parentWay).some(function (parentRelation) {
76355                     if (parentRelation.tags.type === 'route' && parentRelation.tags.route === 'ferry') return true; // allow connections to highway multipolygons
76356
76357                     return parentRelation.isMultipolygon() && osmRoutableHighwayTagValues[parentRelation.tags.highway];
76358                   });
76359                 } else if (wayType === 'waterway') {
76360                   // multiple waterways may start or end at a water body at the same node
76361                   if (parentWay.tags.natural === 'water' || parentWay.tags.natural === 'coastline') return true;
76362                 }
76363
76364                 return false;
76365               });
76366             }
76367
76368             function issuesForNode(way, nodeID) {
76369               var isFirst = nodeID === way.first();
76370               var wayType = typeForWay(way); // ignore if this way is self-connected at this node
76371
76372               if (nodeOccursMoreThanOnce(way, nodeID)) return [];
76373               var osm = services.osm;
76374               if (!osm) return [];
76375               var node = graph.hasEntity(nodeID); // ignore if this node or its tile are unloaded
76376
76377               if (!node || !osm.isDataLoaded(node.loc)) return [];
76378               if (isConnectedViaOtherTypes(way, node)) return [];
76379               var attachedWaysOfSameType = graph.parentWays(node).filter(function (parentWay) {
76380                 if (parentWay.id === way.id) return false;
76381                 return typeForWay(parentWay) === wayType;
76382               }); // assume it's okay for waterways to start or end disconnected for now
76383
76384               if (wayType === 'waterway' && attachedWaysOfSameType.length === 0) return [];
76385               var attachedOneways = attachedWaysOfSameType.filter(function (attachedWay) {
76386                 return isOneway(attachedWay);
76387               }); // ignore if the way is connected to some non-oneway features
76388
76389               if (attachedOneways.length < attachedWaysOfSameType.length) return [];
76390
76391               if (attachedOneways.length) {
76392                 var connectedEndpointsOkay = attachedOneways.some(function (attachedOneway) {
76393                   if ((isFirst ? attachedOneway.first() : attachedOneway.last()) !== nodeID) return true;
76394                   if (nodeOccursMoreThanOnce(attachedOneway, nodeID)) return true;
76395                   return false;
76396                 });
76397                 if (connectedEndpointsOkay) return [];
76398               }
76399
76400               var placement = isFirst ? 'start' : 'end',
76401                   messageID = wayType + '.',
76402                   referenceID = wayType + '.';
76403
76404               if (wayType === 'waterway') {
76405                 messageID += 'connected.' + placement;
76406                 referenceID += 'connected';
76407               } else {
76408                 messageID += placement;
76409                 referenceID += placement;
76410               }
76411
76412               return [new validationIssue({
76413                 type: type,
76414                 subtype: wayType,
76415                 severity: 'warning',
76416                 message: function message(context) {
76417                   var entity = context.hasEntity(this.entityIds[0]);
76418                   return entity ? _t.html('issues.impossible_oneway.' + messageID + '.message', {
76419                     feature: utilDisplayLabel(entity, context.graph())
76420                   }) : '';
76421                 },
76422                 reference: getReference(referenceID),
76423                 entityIds: [way.id, node.id],
76424                 dynamicFixes: function dynamicFixes() {
76425                   var fixes = [];
76426
76427                   if (attachedOneways.length) {
76428                     fixes.push(new validationIssueFix({
76429                       icon: 'iD-operation-reverse',
76430                       title: _t.html('issues.fix.reverse_feature.title'),
76431                       entityIds: [way.id],
76432                       onClick: function onClick(context) {
76433                         var id = this.issue.entityIds[0];
76434                         context.perform(actionReverse(id), _t('operations.reverse.annotation.line', {
76435                           n: 1
76436                         }));
76437                       }
76438                     }));
76439                   }
76440
76441                   if (node.tags.noexit !== 'yes') {
76442                     var textDirection = _mainLocalizer.textDirection();
76443                     var useLeftContinue = isFirst && textDirection === 'ltr' || !isFirst && textDirection === 'rtl';
76444                     fixes.push(new validationIssueFix({
76445                       icon: 'iD-operation-continue' + (useLeftContinue ? '-left' : ''),
76446                       title: _t.html('issues.fix.continue_from_' + (isFirst ? 'start' : 'end') + '.title'),
76447                       onClick: function onClick(context) {
76448                         var entityID = this.issue.entityIds[0];
76449                         var vertexID = this.issue.entityIds[1];
76450                         var way = context.entity(entityID);
76451                         var vertex = context.entity(vertexID);
76452                         continueDrawing(way, vertex, context);
76453                       }
76454                     }));
76455                   }
76456
76457                   return fixes;
76458                 },
76459                 loc: node.loc
76460               })];
76461
76462               function getReference(referenceID) {
76463                 return function showReference(selection) {
76464                   selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.impossible_oneway.' + referenceID + '.reference'));
76465                 };
76466               }
76467             }
76468           };
76469
76470           function continueDrawing(way, vertex, context) {
76471             // make sure the vertex is actually visible and editable
76472             var map = context.map();
76473
76474             if (!context.editable() || !map.trimmedExtent().contains(vertex.loc)) {
76475               map.zoomToEase(vertex);
76476             }
76477
76478             context.enter(modeDrawLine(context, way.id, context.graph(), 'line', way.affix(vertex.id), true));
76479           }
76480
76481           validation.type = type;
76482           return validation;
76483         }
76484
76485         function validationIncompatibleSource() {
76486           var type = 'incompatible_source';
76487           var incompatibleRules = [{
76488             id: 'amap',
76489             regex: /(^amap$|^amap\.com|autonavi|mapabc|高德)/i
76490           }, {
76491             id: 'baidu',
76492             regex: /(baidu|mapbar|百度)/i
76493           }, {
76494             id: 'google',
76495             regex: /google/i,
76496             exceptRegex: /((books|drive)\.google|google\s?(books|drive|plus))|(esri\/Google_Africa_Buildings)/i
76497           }];
76498
76499           var validation = function checkIncompatibleSource(entity) {
76500             var entitySources = entity.tags && entity.tags.source && entity.tags.source.split(';');
76501             if (!entitySources) return [];
76502             var entityID = entity.id;
76503             return entitySources.map(function (source) {
76504               var matchRule = incompatibleRules.find(function (rule) {
76505                 if (!rule.regex.test(source)) return false;
76506                 if (rule.exceptRegex && rule.exceptRegex.test(source)) return false;
76507                 return true;
76508               });
76509               if (!matchRule) return null;
76510               return new validationIssue({
76511                 type: type,
76512                 severity: 'warning',
76513                 message: function message(context) {
76514                   var entity = context.hasEntity(entityID);
76515                   return entity ? _t.html('issues.incompatible_source.feature.message', {
76516                     feature: utilDisplayLabel(entity, context.graph(), true
76517                     /* verbose */
76518                     ),
76519                     value: source
76520                   }) : '';
76521                 },
76522                 reference: getReference(matchRule.id),
76523                 entityIds: [entityID],
76524                 hash: source,
76525                 dynamicFixes: function dynamicFixes() {
76526                   return [new validationIssueFix({
76527                     title: _t.html('issues.fix.remove_proprietary_data.title')
76528                   })];
76529                 }
76530               });
76531             }).filter(Boolean);
76532
76533             function getReference(id) {
76534               return function showReference(selection) {
76535                 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append("issues.incompatible_source.reference.".concat(id)));
76536               };
76537             }
76538           };
76539
76540           validation.type = type;
76541           return validation;
76542         }
76543
76544         function validationMaprules() {
76545           var type = 'maprules';
76546
76547           var validation = function checkMaprules(entity, graph) {
76548             if (!services.maprules) return [];
76549             var rules = services.maprules.validationRules();
76550             var issues = [];
76551
76552             for (var i = 0; i < rules.length; i++) {
76553               var rule = rules[i];
76554               rule.findIssues(entity, graph, issues);
76555             }
76556
76557             return issues;
76558           };
76559
76560           validation.type = type;
76561           return validation;
76562         }
76563
76564         function validationMismatchedGeometry() {
76565           var type = 'mismatched_geometry';
76566
76567           function tagSuggestingLineIsArea(entity) {
76568             if (entity.type !== 'way' || entity.isClosed()) return null;
76569             var tagSuggestingArea = entity.tagSuggestingArea();
76570
76571             if (!tagSuggestingArea) {
76572               return null;
76573             }
76574
76575             var asLine = _mainPresetIndex.matchTags(tagSuggestingArea, 'line');
76576             var asArea = _mainPresetIndex.matchTags(tagSuggestingArea, 'area');
76577
76578             if (asLine && asArea && asLine === asArea) {
76579               // these tags also allow lines and making this an area wouldn't matter
76580               return null;
76581             }
76582
76583             return tagSuggestingArea;
76584           }
76585
76586           function makeConnectEndpointsFixOnClick(way, graph) {
76587             // must have at least three nodes to close this automatically
76588             if (way.nodes.length < 3) return null;
76589             var nodes = graph.childNodes(way),
76590                 testNodes;
76591             var firstToLastDistanceMeters = geoSphericalDistance(nodes[0].loc, nodes[nodes.length - 1].loc); // if the distance is very small, attempt to merge the endpoints
76592
76593             if (firstToLastDistanceMeters < 0.75) {
76594               testNodes = nodes.slice(); // shallow copy
76595
76596               testNodes.pop();
76597               testNodes.push(testNodes[0]); // make sure this will not create a self-intersection
76598
76599               if (!geoHasSelfIntersections(testNodes, testNodes[0].id)) {
76600                 return function (context) {
76601                   var way = context.entity(this.issue.entityIds[0]);
76602                   context.perform(actionMergeNodes([way.nodes[0], way.nodes[way.nodes.length - 1]], nodes[0].loc), _t('issues.fix.connect_endpoints.annotation'));
76603                 };
76604               }
76605             } // if the points were not merged, attempt to close the way
76606
76607
76608             testNodes = nodes.slice(); // shallow copy
76609
76610             testNodes.push(testNodes[0]); // make sure this will not create a self-intersection
76611
76612             if (!geoHasSelfIntersections(testNodes, testNodes[0].id)) {
76613               return function (context) {
76614                 var wayId = this.issue.entityIds[0];
76615                 var way = context.entity(wayId);
76616                 var nodeId = way.nodes[0];
76617                 var index = way.nodes.length;
76618                 context.perform(actionAddVertex(wayId, nodeId, index), _t('issues.fix.connect_endpoints.annotation'));
76619               };
76620             }
76621           }
76622
76623           function lineTaggedAsAreaIssue(entity) {
76624             var tagSuggestingArea = tagSuggestingLineIsArea(entity);
76625             if (!tagSuggestingArea) return null;
76626             return new validationIssue({
76627               type: type,
76628               subtype: 'area_as_line',
76629               severity: 'warning',
76630               message: function message(context) {
76631                 var entity = context.hasEntity(this.entityIds[0]);
76632                 return entity ? _t.html('issues.tag_suggests_area.message', {
76633                   feature: utilDisplayLabel(entity, 'area', true
76634                   /* verbose */
76635                   ),
76636                   tag: utilTagText({
76637                     tags: tagSuggestingArea
76638                   })
76639                 }) : '';
76640               },
76641               reference: showReference,
76642               entityIds: [entity.id],
76643               hash: JSON.stringify(tagSuggestingArea),
76644               dynamicFixes: function dynamicFixes(context) {
76645                 var fixes = [];
76646                 var entity = context.entity(this.entityIds[0]);
76647                 var connectEndsOnClick = makeConnectEndpointsFixOnClick(entity, context.graph());
76648                 fixes.push(new validationIssueFix({
76649                   title: _t.html('issues.fix.connect_endpoints.title'),
76650                   onClick: connectEndsOnClick
76651                 }));
76652                 fixes.push(new validationIssueFix({
76653                   icon: 'iD-operation-delete',
76654                   title: _t.html('issues.fix.remove_tag.title'),
76655                   onClick: function onClick(context) {
76656                     var entityId = this.issue.entityIds[0];
76657                     var entity = context.entity(entityId);
76658                     var tags = Object.assign({}, entity.tags); // shallow copy
76659
76660                     for (var key in tagSuggestingArea) {
76661                       delete tags[key];
76662                     }
76663
76664                     context.perform(actionChangeTags(entityId, tags), _t('issues.fix.remove_tag.annotation'));
76665                   }
76666                 }));
76667                 return fixes;
76668               }
76669             });
76670
76671             function showReference(selection) {
76672               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.tag_suggests_area.reference'));
76673             }
76674           }
76675
76676           function vertexPointIssue(entity, graph) {
76677             // we only care about nodes
76678             if (entity.type !== 'node') return null; // ignore tagless points
76679
76680             if (Object.keys(entity.tags).length === 0) return null; // address lines are special so just ignore them
76681
76682             if (entity.isOnAddressLine(graph)) return null;
76683             var geometry = entity.geometry(graph);
76684             var allowedGeometries = osmNodeGeometriesForTags(entity.tags);
76685
76686             if (geometry === 'point' && !allowedGeometries.point && allowedGeometries.vertex) {
76687               return new validationIssue({
76688                 type: type,
76689                 subtype: 'vertex_as_point',
76690                 severity: 'warning',
76691                 message: function message(context) {
76692                   var entity = context.hasEntity(this.entityIds[0]);
76693                   return entity ? _t.html('issues.vertex_as_point.message', {
76694                     feature: utilDisplayLabel(entity, 'vertex', true
76695                     /* verbose */
76696                     )
76697                   }) : '';
76698                 },
76699                 reference: function showReference(selection) {
76700                   selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.vertex_as_point.reference'));
76701                 },
76702                 entityIds: [entity.id]
76703               });
76704             } else if (geometry === 'vertex' && !allowedGeometries.vertex && allowedGeometries.point) {
76705               return new validationIssue({
76706                 type: type,
76707                 subtype: 'point_as_vertex',
76708                 severity: 'warning',
76709                 message: function message(context) {
76710                   var entity = context.hasEntity(this.entityIds[0]);
76711                   return entity ? _t.html('issues.point_as_vertex.message', {
76712                     feature: utilDisplayLabel(entity, 'point', true
76713                     /* verbose */
76714                     )
76715                   }) : '';
76716                 },
76717                 reference: function showReference(selection) {
76718                   selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.point_as_vertex.reference'));
76719                 },
76720                 entityIds: [entity.id],
76721                 dynamicFixes: extractPointDynamicFixes
76722               });
76723             }
76724
76725             return null;
76726           }
76727
76728           function otherMismatchIssue(entity, graph) {
76729             // ignore boring features
76730             if (!entity.hasInterestingTags()) return null;
76731             if (entity.type !== 'node' && entity.type !== 'way') return null; // address lines are special so just ignore them
76732
76733             if (entity.type === 'node' && entity.isOnAddressLine(graph)) return null;
76734             var sourceGeom = entity.geometry(graph);
76735             var targetGeoms = entity.type === 'way' ? ['point', 'vertex'] : ['line', 'area'];
76736             if (sourceGeom === 'area') targetGeoms.unshift('line');
76737             var asSource = _mainPresetIndex.match(entity, graph);
76738             var targetGeom = targetGeoms.find(function (nodeGeom) {
76739               var asTarget = _mainPresetIndex.matchTags(entity.tags, nodeGeom);
76740               if (!asSource || !asTarget || asSource === asTarget || // sometimes there are two presets with the same tags for different geometries
76741               fastDeepEqual(asSource.tags, asTarget.tags)) return false;
76742               if (asTarget.isFallback()) return false;
76743               var primaryKey = Object.keys(asTarget.tags)[0]; // special case: buildings-as-points are discouraged by iD, but common in OSM, so ignore them
76744
76745               if (primaryKey === 'building') return false;
76746               if (asTarget.tags[primaryKey] === '*') return false;
76747               return asSource.isFallback() || asSource.tags[primaryKey] === '*';
76748             });
76749             if (!targetGeom) return null;
76750             var subtype = targetGeom + '_as_' + sourceGeom;
76751             if (targetGeom === 'vertex') targetGeom = 'point';
76752             if (sourceGeom === 'vertex') sourceGeom = 'point';
76753             var referenceId = targetGeom + '_as_' + sourceGeom;
76754             var dynamicFixes;
76755
76756             if (targetGeom === 'point') {
76757               dynamicFixes = extractPointDynamicFixes;
76758             } else if (sourceGeom === 'area' && targetGeom === 'line') {
76759               dynamicFixes = lineToAreaDynamicFixes;
76760             }
76761
76762             return new validationIssue({
76763               type: type,
76764               subtype: subtype,
76765               severity: 'warning',
76766               message: function message(context) {
76767                 var entity = context.hasEntity(this.entityIds[0]);
76768                 return entity ? _t.html('issues.' + referenceId + '.message', {
76769                   feature: utilDisplayLabel(entity, targetGeom, true
76770                   /* verbose */
76771                   )
76772                 }) : '';
76773               },
76774               reference: function showReference(selection) {
76775                 selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.mismatched_geometry.reference'));
76776               },
76777               entityIds: [entity.id],
76778               dynamicFixes: dynamicFixes
76779             });
76780           }
76781
76782           function lineToAreaDynamicFixes(context) {
76783             var convertOnClick;
76784             var entityId = this.entityIds[0];
76785             var entity = context.entity(entityId);
76786             var tags = Object.assign({}, entity.tags); // shallow copy
76787
76788             delete tags.area;
76789
76790             if (!osmTagSuggestingArea(tags)) {
76791               // if removing the area tag would make this a line, offer that as a quick fix
76792               convertOnClick = function convertOnClick(context) {
76793                 var entityId = this.issue.entityIds[0];
76794                 var entity = context.entity(entityId);
76795                 var tags = Object.assign({}, entity.tags); // shallow copy
76796
76797                 if (tags.area) {
76798                   delete tags.area;
76799                 }
76800
76801                 context.perform(actionChangeTags(entityId, tags), _t('issues.fix.convert_to_line.annotation'));
76802               };
76803             }
76804
76805             return [new validationIssueFix({
76806               icon: 'iD-icon-line',
76807               title: _t.html('issues.fix.convert_to_line.title'),
76808               onClick: convertOnClick
76809             })];
76810           }
76811
76812           function extractPointDynamicFixes(context) {
76813             var entityId = this.entityIds[0];
76814             var extractOnClick = null;
76815
76816             if (!context.hasHiddenConnections(entityId)) {
76817               extractOnClick = function extractOnClick(context) {
76818                 var entityId = this.issue.entityIds[0];
76819                 var action = actionExtract(entityId, context.projection);
76820                 context.perform(action, _t('operations.extract.annotation', {
76821                   n: 1
76822                 })); // re-enter mode to trigger updates
76823
76824                 context.enter(modeSelect(context, [action.getExtractedNodeID()]));
76825               };
76826             }
76827
76828             return [new validationIssueFix({
76829               icon: 'iD-operation-extract',
76830               title: _t.html('issues.fix.extract_point.title'),
76831               onClick: extractOnClick
76832             })];
76833           }
76834
76835           function unclosedMultipolygonPartIssues(entity, graph) {
76836             if (entity.type !== 'relation' || !entity.isMultipolygon() || entity.isDegenerate() || // cannot determine issues for incompletely-downloaded relations
76837             !entity.isComplete(graph)) return [];
76838             var sequences = osmJoinWays(entity.members, graph);
76839             var issues = [];
76840
76841             for (var i in sequences) {
76842               var sequence = sequences[i];
76843               if (!sequence.nodes) continue;
76844               var firstNode = sequence.nodes[0];
76845               var lastNode = sequence.nodes[sequence.nodes.length - 1]; // part is closed if the first and last nodes are the same
76846
76847               if (firstNode === lastNode) continue;
76848               var issue = new validationIssue({
76849                 type: type,
76850                 subtype: 'unclosed_multipolygon_part',
76851                 severity: 'warning',
76852                 message: function message(context) {
76853                   var entity = context.hasEntity(this.entityIds[0]);
76854                   return entity ? _t.html('issues.unclosed_multipolygon_part.message', {
76855                     feature: utilDisplayLabel(entity, context.graph(), true
76856                     /* verbose */
76857                     )
76858                   }) : '';
76859                 },
76860                 reference: showReference,
76861                 loc: sequence.nodes[0].loc,
76862                 entityIds: [entity.id],
76863                 hash: sequence.map(function (way) {
76864                   return way.id;
76865                 }).join()
76866               });
76867               issues.push(issue);
76868             }
76869
76870             return issues;
76871
76872             function showReference(selection) {
76873               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.unclosed_multipolygon_part.reference'));
76874             }
76875           }
76876
76877           var validation = function checkMismatchedGeometry(entity, graph) {
76878             var vertexPoint = vertexPointIssue(entity, graph);
76879             if (vertexPoint) return [vertexPoint];
76880             var lineAsArea = lineTaggedAsAreaIssue(entity);
76881             if (lineAsArea) return [lineAsArea];
76882             var mismatch = otherMismatchIssue(entity, graph);
76883             if (mismatch) return [mismatch];
76884             return unclosedMultipolygonPartIssues(entity, graph);
76885           };
76886
76887           validation.type = type;
76888           return validation;
76889         }
76890
76891         function validationMissingRole() {
76892           var type = 'missing_role';
76893
76894           var validation = function checkMissingRole(entity, graph) {
76895             var issues = [];
76896
76897             if (entity.type === 'way') {
76898               graph.parentRelations(entity).forEach(function (relation) {
76899                 if (!relation.isMultipolygon()) return;
76900                 var member = relation.memberById(entity.id);
76901
76902                 if (member && isMissingRole(member)) {
76903                   issues.push(makeIssue(entity, relation, member));
76904                 }
76905               });
76906             } else if (entity.type === 'relation' && entity.isMultipolygon()) {
76907               entity.indexedMembers().forEach(function (member) {
76908                 var way = graph.hasEntity(member.id);
76909
76910                 if (way && isMissingRole(member)) {
76911                   issues.push(makeIssue(way, entity, member));
76912                 }
76913               });
76914             }
76915
76916             return issues;
76917           };
76918
76919           function isMissingRole(member) {
76920             return !member.role || !member.role.trim().length;
76921           }
76922
76923           function makeIssue(way, relation, member) {
76924             return new validationIssue({
76925               type: type,
76926               severity: 'warning',
76927               message: function message(context) {
76928                 var member = context.hasEntity(this.entityIds[1]),
76929                     relation = context.hasEntity(this.entityIds[0]);
76930                 return member && relation ? _t.html('issues.missing_role.message', {
76931                   member: utilDisplayLabel(member, context.graph()),
76932                   relation: utilDisplayLabel(relation, context.graph())
76933                 }) : '';
76934               },
76935               reference: showReference,
76936               entityIds: [relation.id, way.id],
76937               data: {
76938                 member: member
76939               },
76940               hash: member.index.toString(),
76941               dynamicFixes: function dynamicFixes() {
76942                 return [makeAddRoleFix('inner'), makeAddRoleFix('outer'), new validationIssueFix({
76943                   icon: 'iD-operation-delete',
76944                   title: _t.html('issues.fix.remove_from_relation.title'),
76945                   onClick: function onClick(context) {
76946                     context.perform(actionDeleteMember(this.issue.entityIds[0], this.issue.data.member.index), _t('operations.delete_member.annotation', {
76947                       n: 1
76948                     }));
76949                   }
76950                 })];
76951               }
76952             });
76953
76954             function showReference(selection) {
76955               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.missing_role.multipolygon.reference'));
76956             }
76957           }
76958
76959           function makeAddRoleFix(role) {
76960             return new validationIssueFix({
76961               title: _t.html('issues.fix.set_as_' + role + '.title'),
76962               onClick: function onClick(context) {
76963                 var oldMember = this.issue.data.member;
76964                 var member = {
76965                   id: this.issue.entityIds[1],
76966                   type: oldMember.type,
76967                   role: role
76968                 };
76969                 context.perform(actionChangeMember(this.issue.entityIds[0], member, oldMember.index), _t('operations.change_role.annotation', {
76970                   n: 1
76971                 }));
76972               }
76973             });
76974           }
76975
76976           validation.type = type;
76977           return validation;
76978         }
76979
76980         function validationMissingTag(context) {
76981           var type = 'missing_tag';
76982
76983           function hasDescriptiveTags(entity, graph) {
76984             var onlyAttributeKeys = ['description', 'name', 'note', 'start_date'];
76985             var entityDescriptiveKeys = Object.keys(entity.tags).filter(function (k) {
76986               if (k === 'area' || !osmIsInterestingTag(k)) return false;
76987               return !onlyAttributeKeys.some(function (attributeKey) {
76988                 return k === attributeKey || k.indexOf(attributeKey + ':') === 0;
76989               });
76990             });
76991
76992             if (entity.type === 'relation' && entityDescriptiveKeys.length === 1 && entity.tags.type === 'multipolygon') {
76993               // this relation's only interesting tag just says its a multipolygon,
76994               // which is not descriptive enough
76995               // It's okay for a simple multipolygon to have no descriptive tags
76996               // if its outer way has them (old model, see `outdated_tags.js`)
76997               return osmOldMultipolygonOuterMemberOfRelation(entity, graph);
76998             }
76999
77000             return entityDescriptiveKeys.length > 0;
77001           }
77002
77003           function isUnknownRoad(entity) {
77004             return entity.type === 'way' && entity.tags.highway === 'road';
77005           }
77006
77007           function isUntypedRelation(entity) {
77008             return entity.type === 'relation' && !entity.tags.type;
77009           }
77010
77011           var validation = function checkMissingTag(entity, graph) {
77012             var subtype;
77013             var osm = context.connection();
77014             var isUnloadedNode = entity.type === 'node' && osm && !osm.isDataLoaded(entity.loc); // we can't know if the node is a vertex if the tile is undownloaded
77015
77016             if (!isUnloadedNode && // allow untagged nodes that are part of ways
77017             entity.geometry(graph) !== 'vertex' && // allow untagged entities that are part of relations
77018             !entity.hasParentRelations(graph)) {
77019               if (Object.keys(entity.tags).length === 0) {
77020                 subtype = 'any';
77021               } else if (!hasDescriptiveTags(entity, graph)) {
77022                 subtype = 'descriptive';
77023               } else if (isUntypedRelation(entity)) {
77024                 subtype = 'relation_type';
77025               }
77026             } // flag an unknown road even if it's a member of a relation
77027
77028
77029             if (!subtype && isUnknownRoad(entity)) {
77030               subtype = 'highway_classification';
77031             }
77032
77033             if (!subtype) return [];
77034             var messageID = subtype === 'highway_classification' ? 'unknown_road' : 'missing_tag.' + subtype;
77035             var referenceID = subtype === 'highway_classification' ? 'unknown_road' : 'missing_tag'; // can always delete if the user created it in the first place..
77036
77037             var canDelete = entity.version === undefined || entity.v !== undefined;
77038             var severity = canDelete && subtype !== 'highway_classification' ? 'error' : 'warning';
77039             return [new validationIssue({
77040               type: type,
77041               subtype: subtype,
77042               severity: severity,
77043               message: function message(context) {
77044                 var entity = context.hasEntity(this.entityIds[0]);
77045                 return entity ? _t.html('issues.' + messageID + '.message', {
77046                   feature: utilDisplayLabel(entity, context.graph())
77047                 }) : '';
77048               },
77049               reference: showReference,
77050               entityIds: [entity.id],
77051               dynamicFixes: function dynamicFixes(context) {
77052                 var fixes = [];
77053                 var selectFixType = subtype === 'highway_classification' ? 'select_road_type' : 'select_preset';
77054                 fixes.push(new validationIssueFix({
77055                   icon: 'iD-icon-search',
77056                   title: _t.html('issues.fix.' + selectFixType + '.title'),
77057                   onClick: function onClick(context) {
77058                     context.ui().sidebar.showPresetList();
77059                   }
77060                 }));
77061                 var deleteOnClick;
77062                 var id = this.entityIds[0];
77063                 var operation = operationDelete(context, [id]);
77064                 var disabledReasonID = operation.disabled();
77065
77066                 if (!disabledReasonID) {
77067                   deleteOnClick = function deleteOnClick(context) {
77068                     var id = this.issue.entityIds[0];
77069                     var operation = operationDelete(context, [id]);
77070
77071                     if (!operation.disabled()) {
77072                       operation();
77073                     }
77074                   };
77075                 }
77076
77077                 fixes.push(new validationIssueFix({
77078                   icon: 'iD-operation-delete',
77079                   title: _t.html('issues.fix.delete_feature.title'),
77080                   disabledReason: disabledReasonID ? _t('operations.delete.' + disabledReasonID + '.single') : undefined,
77081                   onClick: deleteOnClick
77082                 }));
77083                 return fixes;
77084               }
77085             })];
77086
77087             function showReference(selection) {
77088               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.' + referenceID + '.reference'));
77089             }
77090           };
77091
77092           validation.type = type;
77093           return validation;
77094         }
77095
77096         function validationOutdatedTags() {
77097           var type = 'outdated_tags';
77098           var _waitingForDeprecated = true;
77099
77100           var _dataDeprecated; // fetch deprecated tags
77101
77102
77103           _mainFileFetcher.get('deprecated').then(function (d) {
77104             return _dataDeprecated = d;
77105           })["catch"](function () {
77106             /* ignore */
77107           })["finally"](function () {
77108             return _waitingForDeprecated = false;
77109           });
77110
77111           function oldTagIssues(entity, graph) {
77112             var oldTags = Object.assign({}, entity.tags); // shallow copy
77113
77114             var preset = _mainPresetIndex.match(entity, graph);
77115             var subtype = 'deprecated_tags';
77116             if (!preset) return [];
77117             if (!entity.hasInterestingTags()) return []; // Upgrade preset, if a replacement is available..
77118
77119             if (preset.replacement) {
77120               var newPreset = _mainPresetIndex.item(preset.replacement);
77121               graph = actionChangePreset(entity.id, preset, newPreset, true
77122               /* skip field defaults */
77123               )(graph);
77124               entity = graph.entity(entity.id);
77125               preset = newPreset;
77126             } // Upgrade deprecated tags..
77127
77128
77129             if (_dataDeprecated) {
77130               var deprecatedTags = entity.deprecatedTags(_dataDeprecated);
77131
77132               if (deprecatedTags.length) {
77133                 deprecatedTags.forEach(function (tag) {
77134                   graph = actionUpgradeTags(entity.id, tag.old, tag.replace)(graph);
77135                 });
77136                 entity = graph.entity(entity.id);
77137               }
77138             } // Add missing addTags from the detected preset
77139
77140
77141             var newTags = Object.assign({}, entity.tags); // shallow copy
77142
77143             if (preset.tags !== preset.addTags) {
77144               Object.keys(preset.addTags).forEach(function (k) {
77145                 if (!newTags[k]) {
77146                   if (preset.addTags[k] === '*') {
77147                     newTags[k] = 'yes';
77148                   } else {
77149                     newTags[k] = preset.addTags[k];
77150                   }
77151                 }
77152               });
77153             } // Attempt to match a canonical record in the name-suggestion-index.
77154
77155
77156             var nsi = services.nsi;
77157             var waitingForNsi = false;
77158             var nsiResult;
77159
77160             if (nsi) {
77161               waitingForNsi = nsi.status() === 'loading';
77162
77163               if (!waitingForNsi) {
77164                 var loc = entity.extent(graph).center();
77165                 nsiResult = nsi.upgradeTags(newTags, loc);
77166
77167                 if (nsiResult) {
77168                   newTags = nsiResult.newTags;
77169                   subtype = 'noncanonical_brand';
77170                 }
77171               }
77172             }
77173
77174             var issues = [];
77175             issues.provisional = _waitingForDeprecated || waitingForNsi; // determine diff
77176
77177             var tagDiff = utilTagDiff(oldTags, newTags);
77178             if (!tagDiff.length) return issues;
77179             var isOnlyAddingTags = tagDiff.every(function (d) {
77180               return d.type === '+';
77181             });
77182             var prefix = '';
77183
77184             if (nsiResult) {
77185               prefix = 'noncanonical_brand.';
77186             } else if (subtype === 'deprecated_tags' && isOnlyAddingTags) {
77187               subtype = 'incomplete_tags';
77188               prefix = 'incomplete.';
77189             } // don't allow autofixing brand tags
77190
77191
77192             var autoArgs = subtype !== 'noncanonical_brand' ? [doUpgrade, _t('issues.fix.upgrade_tags.annotation')] : null;
77193             issues.push(new validationIssue({
77194               type: type,
77195               subtype: subtype,
77196               severity: 'warning',
77197               message: showMessage,
77198               reference: showReference,
77199               entityIds: [entity.id],
77200               hash: utilHashcode(JSON.stringify(tagDiff)),
77201               dynamicFixes: function dynamicFixes() {
77202                 var fixes = [new validationIssueFix({
77203                   autoArgs: autoArgs,
77204                   title: _t.html('issues.fix.upgrade_tags.title'),
77205                   onClick: function onClick(context) {
77206                     context.perform(doUpgrade, _t('issues.fix.upgrade_tags.annotation'));
77207                   }
77208                 })];
77209                 var item = nsiResult && nsiResult.matched;
77210
77211                 if (item) {
77212                   fixes.push(new validationIssueFix({
77213                     title: _t.html('issues.fix.tag_as_not.title', {
77214                       name: item.displayName
77215                     }),
77216                     onClick: function onClick(context) {
77217                       context.perform(addNotTag, _t('issues.fix.tag_as_not.annotation'));
77218                     }
77219                   }));
77220                 }
77221
77222                 return fixes;
77223               }
77224             }));
77225             return issues;
77226
77227             function doUpgrade(graph) {
77228               var currEntity = graph.hasEntity(entity.id);
77229               if (!currEntity) return graph;
77230               var newTags = Object.assign({}, currEntity.tags); // shallow copy
77231
77232               tagDiff.forEach(function (diff) {
77233                 if (diff.type === '-') {
77234                   delete newTags[diff.key];
77235                 } else if (diff.type === '+') {
77236                   newTags[diff.key] = diff.newVal;
77237                 }
77238               });
77239               return actionChangeTags(currEntity.id, newTags)(graph);
77240             }
77241
77242             function addNotTag(graph) {
77243               var currEntity = graph.hasEntity(entity.id);
77244               if (!currEntity) return graph;
77245               var item = nsiResult && nsiResult.matched;
77246               if (!item) return graph;
77247               var newTags = Object.assign({}, currEntity.tags); // shallow copy
77248
77249               var wd = item.mainTag; // e.g. `brand:wikidata`
77250
77251               var notwd = "not:".concat(wd); // e.g. `not:brand:wikidata`
77252
77253               var qid = item.tags[wd];
77254               newTags[notwd] = qid;
77255
77256               if (newTags[wd] === qid) {
77257                 // if `brand:wikidata` was set to that qid
77258                 var wp = item.mainTag.replace('wikidata', 'wikipedia');
77259                 delete newTags[wd]; // remove `brand:wikidata`
77260
77261                 delete newTags[wp]; // remove `brand:wikipedia`
77262               }
77263
77264               return actionChangeTags(currEntity.id, newTags)(graph);
77265             }
77266
77267             function showMessage(context) {
77268               var currEntity = context.hasEntity(entity.id);
77269               if (!currEntity) return '';
77270               var messageID = "issues.outdated_tags.".concat(prefix, "message");
77271
77272               if (subtype === 'noncanonical_brand' && isOnlyAddingTags) {
77273                 messageID += '_incomplete';
77274               }
77275
77276               return _t.html(messageID, {
77277                 feature: utilDisplayLabel(currEntity, context.graph(), true
77278                 /* verbose */
77279                 )
77280               });
77281             }
77282
77283             function showReference(selection) {
77284               var enter = selection.selectAll('.issue-reference').data([0]).enter();
77285               enter.append('div').attr('class', 'issue-reference').call(_t.append("issues.outdated_tags.".concat(prefix, "reference")));
77286               enter.append('strong').call(_t.append('issues.suggested'));
77287               enter.append('table').attr('class', 'tagDiff-table').selectAll('.tagDiff-row').data(tagDiff).enter().append('tr').attr('class', 'tagDiff-row').append('td').attr('class', function (d) {
77288                 var klass = d.type === '+' ? 'add' : 'remove';
77289                 return "tagDiff-cell tagDiff-cell-".concat(klass);
77290               }).html(function (d) {
77291                 return d.display;
77292               });
77293             }
77294           }
77295
77296           function oldMultipolygonIssues(entity, graph) {
77297             var multipolygon, outerWay;
77298
77299             if (entity.type === 'relation') {
77300               outerWay = osmOldMultipolygonOuterMemberOfRelation(entity, graph);
77301               multipolygon = entity;
77302             } else if (entity.type === 'way') {
77303               multipolygon = osmIsOldMultipolygonOuterMember(entity, graph);
77304               outerWay = entity;
77305             } else {
77306               return [];
77307             }
77308
77309             if (!multipolygon || !outerWay) return [];
77310             return [new validationIssue({
77311               type: type,
77312               subtype: 'old_multipolygon',
77313               severity: 'warning',
77314               message: showMessage,
77315               reference: showReference,
77316               entityIds: [outerWay.id, multipolygon.id],
77317               dynamicFixes: function dynamicFixes() {
77318                 return [new validationIssueFix({
77319                   autoArgs: [doUpgrade, _t('issues.fix.move_tags.annotation')],
77320                   title: _t.html('issues.fix.move_tags.title'),
77321                   onClick: function onClick(context) {
77322                     context.perform(doUpgrade, _t('issues.fix.move_tags.annotation'));
77323                   }
77324                 })];
77325               }
77326             })];
77327
77328             function doUpgrade(graph) {
77329               var currMultipolygon = graph.hasEntity(multipolygon.id);
77330               var currOuterWay = graph.hasEntity(outerWay.id);
77331               if (!currMultipolygon || !currOuterWay) return graph;
77332               currMultipolygon = currMultipolygon.mergeTags(currOuterWay.tags);
77333               graph = graph.replace(currMultipolygon);
77334               return actionChangeTags(currOuterWay.id, {})(graph);
77335             }
77336
77337             function showMessage(context) {
77338               var currMultipolygon = context.hasEntity(multipolygon.id);
77339               if (!currMultipolygon) return '';
77340               return _t.html('issues.old_multipolygon.message', {
77341                 multipolygon: utilDisplayLabel(currMultipolygon, context.graph(), true
77342                 /* verbose */
77343                 )
77344               });
77345             }
77346
77347             function showReference(selection) {
77348               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.old_multipolygon.reference'));
77349             }
77350           }
77351
77352           var validation = function checkOutdatedTags(entity, graph) {
77353             var issues = oldMultipolygonIssues(entity, graph);
77354             if (!issues.length) issues = oldTagIssues(entity, graph);
77355             return issues;
77356           };
77357
77358           validation.type = type;
77359           return validation;
77360         }
77361
77362         function validationPrivateData() {
77363           var type = 'private_data'; // assume that some buildings are private
77364
77365           var privateBuildingValues = {
77366             detached: true,
77367             farm: true,
77368             house: true,
77369             houseboat: true,
77370             residential: true,
77371             semidetached_house: true,
77372             static_caravan: true
77373           }; // but they might be public if they have one of these other tags
77374
77375           var publicKeys = {
77376             amenity: true,
77377             craft: true,
77378             historic: true,
77379             leisure: true,
77380             office: true,
77381             shop: true,
77382             tourism: true
77383           }; // these tags may contain personally identifying info
77384
77385           var personalTags = {
77386             'contact:email': true,
77387             'contact:fax': true,
77388             'contact:phone': true,
77389             email: true,
77390             fax: true,
77391             phone: true
77392           };
77393
77394           var validation = function checkPrivateData(entity) {
77395             var tags = entity.tags;
77396             if (!tags.building || !privateBuildingValues[tags.building]) return [];
77397             var keepTags = {};
77398
77399             for (var k in tags) {
77400               if (publicKeys[k]) return []; // probably a public feature
77401
77402               if (!personalTags[k]) {
77403                 keepTags[k] = tags[k];
77404               }
77405             }
77406
77407             var tagDiff = utilTagDiff(tags, keepTags);
77408             if (!tagDiff.length) return [];
77409             var fixID = tagDiff.length === 1 ? 'remove_tag' : 'remove_tags';
77410             return [new validationIssue({
77411               type: type,
77412               severity: 'warning',
77413               message: showMessage,
77414               reference: showReference,
77415               entityIds: [entity.id],
77416               dynamicFixes: function dynamicFixes() {
77417                 return [new validationIssueFix({
77418                   icon: 'iD-operation-delete',
77419                   title: _t.html('issues.fix.' + fixID + '.title'),
77420                   onClick: function onClick(context) {
77421                     context.perform(doUpgrade, _t('issues.fix.upgrade_tags.annotation'));
77422                   }
77423                 })];
77424               }
77425             })];
77426
77427             function doUpgrade(graph) {
77428               var currEntity = graph.hasEntity(entity.id);
77429               if (!currEntity) return graph;
77430               var newTags = Object.assign({}, currEntity.tags); // shallow copy
77431
77432               tagDiff.forEach(function (diff) {
77433                 if (diff.type === '-') {
77434                   delete newTags[diff.key];
77435                 } else if (diff.type === '+') {
77436                   newTags[diff.key] = diff.newVal;
77437                 }
77438               });
77439               return actionChangeTags(currEntity.id, newTags)(graph);
77440             }
77441
77442             function showMessage(context) {
77443               var currEntity = context.hasEntity(this.entityIds[0]);
77444               if (!currEntity) return '';
77445               return _t.html('issues.private_data.contact.message', {
77446                 feature: utilDisplayLabel(currEntity, context.graph())
77447               });
77448             }
77449
77450             function showReference(selection) {
77451               var enter = selection.selectAll('.issue-reference').data([0]).enter();
77452               enter.append('div').attr('class', 'issue-reference').call(_t.append('issues.private_data.reference'));
77453               enter.append('strong').call(_t.append('issues.suggested'));
77454               enter.append('table').attr('class', 'tagDiff-table').selectAll('.tagDiff-row').data(tagDiff).enter().append('tr').attr('class', 'tagDiff-row').append('td').attr('class', function (d) {
77455                 var klass = d.type === '+' ? 'add' : 'remove';
77456                 return 'tagDiff-cell tagDiff-cell-' + klass;
77457               }).html(function (d) {
77458                 return d.display;
77459               });
77460             }
77461           };
77462
77463           validation.type = type;
77464           return validation;
77465         }
77466
77467         function validationSuspiciousName() {
77468           var type = 'suspicious_name';
77469           var keysToTestForGenericValues = ['aerialway', 'aeroway', 'amenity', 'building', 'craft', 'highway', 'leisure', 'railway', 'man_made', 'office', 'shop', 'tourism', 'waterway'];
77470           var _waitingForNsi = false; // Attempt to match a generic record in the name-suggestion-index.
77471
77472           function isGenericMatchInNsi(tags) {
77473             var nsi = services.nsi;
77474
77475             if (nsi) {
77476               _waitingForNsi = nsi.status() === 'loading';
77477
77478               if (!_waitingForNsi) {
77479                 return nsi.isGenericName(tags);
77480               }
77481             }
77482
77483             return false;
77484           } // Test if the name is just the key or tag value (e.g. "park")
77485
77486
77487           function nameMatchesRawTag(lowercaseName, tags) {
77488             for (var i = 0; i < keysToTestForGenericValues.length; i++) {
77489               var key = keysToTestForGenericValues[i];
77490               var val = tags[key];
77491
77492               if (val) {
77493                 val = val.toLowerCase();
77494
77495                 if (key === lowercaseName || val === lowercaseName || key.replace(/\_/g, ' ') === lowercaseName || val.replace(/\_/g, ' ') === lowercaseName) {
77496                   return true;
77497                 }
77498               }
77499             }
77500
77501             return false;
77502           }
77503
77504           function isGenericName(name, tags) {
77505             name = name.toLowerCase();
77506             return nameMatchesRawTag(name, tags) || isGenericMatchInNsi(tags);
77507           }
77508
77509           function makeGenericNameIssue(entityId, nameKey, genericName, langCode) {
77510             return new validationIssue({
77511               type: type,
77512               subtype: 'generic_name',
77513               severity: 'warning',
77514               message: function message(context) {
77515                 var entity = context.hasEntity(this.entityIds[0]);
77516                 if (!entity) return '';
77517                 var preset = _mainPresetIndex.match(entity, context.graph());
77518                 var langName = langCode && _mainLocalizer.languageName(langCode);
77519                 return _t.html('issues.generic_name.message' + (langName ? '_language' : ''), {
77520                   feature: preset.name(),
77521                   name: genericName,
77522                   language: langName
77523                 });
77524               },
77525               reference: showReference,
77526               entityIds: [entityId],
77527               hash: "".concat(nameKey, "=").concat(genericName),
77528               dynamicFixes: function dynamicFixes() {
77529                 return [new validationIssueFix({
77530                   icon: 'iD-operation-delete',
77531                   title: _t.html('issues.fix.remove_the_name.title'),
77532                   onClick: function onClick(context) {
77533                     var entityId = this.issue.entityIds[0];
77534                     var entity = context.entity(entityId);
77535                     var tags = Object.assign({}, entity.tags); // shallow copy
77536
77537                     delete tags[nameKey];
77538                     context.perform(actionChangeTags(entityId, tags), _t('issues.fix.remove_generic_name.annotation'));
77539                   }
77540                 })];
77541               }
77542             });
77543
77544             function showReference(selection) {
77545               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.generic_name.reference'));
77546             }
77547           }
77548
77549           function makeIncorrectNameIssue(entityId, nameKey, incorrectName, langCode) {
77550             return new validationIssue({
77551               type: type,
77552               subtype: 'not_name',
77553               severity: 'warning',
77554               message: function message(context) {
77555                 var entity = context.hasEntity(this.entityIds[0]);
77556                 if (!entity) return '';
77557                 var preset = _mainPresetIndex.match(entity, context.graph());
77558                 var langName = langCode && _mainLocalizer.languageName(langCode);
77559                 return _t.html('issues.incorrect_name.message' + (langName ? '_language' : ''), {
77560                   feature: preset.name(),
77561                   name: incorrectName,
77562                   language: langName
77563                 });
77564               },
77565               reference: showReference,
77566               entityIds: [entityId],
77567               hash: "".concat(nameKey, "=").concat(incorrectName),
77568               dynamicFixes: function dynamicFixes() {
77569                 return [new validationIssueFix({
77570                   icon: 'iD-operation-delete',
77571                   title: _t.html('issues.fix.remove_the_name.title'),
77572                   onClick: function onClick(context) {
77573                     var entityId = this.issue.entityIds[0];
77574                     var entity = context.entity(entityId);
77575                     var tags = Object.assign({}, entity.tags); // shallow copy
77576
77577                     delete tags[nameKey];
77578                     context.perform(actionChangeTags(entityId, tags), _t('issues.fix.remove_mistaken_name.annotation'));
77579                   }
77580                 })];
77581               }
77582             });
77583
77584             function showReference(selection) {
77585               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.generic_name.reference'));
77586             }
77587           }
77588
77589           var validation = function checkGenericName(entity) {
77590             var tags = entity.tags; // a generic name is allowed if it's a known brand or entity
77591
77592             var hasWikidata = !!tags.wikidata || !!tags['brand:wikidata'] || !!tags['operator:wikidata'];
77593             if (hasWikidata) return [];
77594             var issues = [];
77595             var notNames = (tags['not:name'] || '').split(';');
77596
77597             for (var key in tags) {
77598               var m = key.match(/^name(?:(?::)([a-zA-Z_-]+))?$/);
77599               if (!m) continue;
77600               var langCode = m.length >= 2 ? m[1] : null;
77601               var value = tags[key];
77602
77603               if (notNames.length) {
77604                 for (var i in notNames) {
77605                   var notName = notNames[i];
77606
77607                   if (notName && value === notName) {
77608                     issues.push(makeIncorrectNameIssue(entity.id, key, value, langCode));
77609                     continue;
77610                   }
77611                 }
77612               }
77613
77614               if (isGenericName(value, tags)) {
77615                 issues.provisional = _waitingForNsi; // retry later if we are waiting on NSI to finish loading
77616
77617                 issues.push(makeGenericNameIssue(entity.id, key, value, langCode));
77618               }
77619             }
77620
77621             return issues;
77622           };
77623
77624           validation.type = type;
77625           return validation;
77626         }
77627
77628         function validationUnsquareWay(context) {
77629           var type = 'unsquare_way';
77630           var DEFAULT_DEG_THRESHOLD = 5; // see also issues.js
77631           // use looser epsilon for detection to reduce warnings of buildings that are essentially square already
77632
77633           var epsilon = 0.05;
77634           var nodeThreshold = 10;
77635
77636           function isBuilding(entity, graph) {
77637             if (entity.type !== 'way' || entity.geometry(graph) !== 'area') return false;
77638             return entity.tags.building && entity.tags.building !== 'no';
77639           }
77640
77641           var validation = function checkUnsquareWay(entity, graph) {
77642             if (!isBuilding(entity, graph)) return []; // don't flag ways marked as physically unsquare
77643
77644             if (entity.tags.nonsquare === 'yes') return [];
77645             var isClosed = entity.isClosed();
77646             if (!isClosed) return []; // this building has bigger problems
77647             // don't flag ways with lots of nodes since they are likely detail-mapped
77648
77649             var nodes = graph.childNodes(entity).slice(); // shallow copy
77650
77651             if (nodes.length > nodeThreshold + 1) return []; // +1 because closing node appears twice
77652             // ignore if not all nodes are fully downloaded
77653
77654             var osm = services.osm;
77655             if (!osm || nodes.some(function (node) {
77656               return !osm.isDataLoaded(node.loc);
77657             })) return []; // don't flag connected ways to avoid unresolvable unsquare loops
77658
77659             var hasConnectedSquarableWays = nodes.some(function (node) {
77660               return graph.parentWays(node).some(function (way) {
77661                 if (way.id === entity.id) return false;
77662                 if (isBuilding(way, graph)) return true;
77663                 return graph.parentRelations(way).some(function (parentRelation) {
77664                   return parentRelation.isMultipolygon() && parentRelation.tags.building && parentRelation.tags.building !== 'no';
77665                 });
77666               });
77667             });
77668             if (hasConnectedSquarableWays) return []; // user-configurable square threshold
77669
77670             var storedDegreeThreshold = corePreferences('validate-square-degrees');
77671             var degreeThreshold = isNaN(storedDegreeThreshold) ? DEFAULT_DEG_THRESHOLD : parseFloat(storedDegreeThreshold);
77672             var points = nodes.map(function (node) {
77673               return context.projection(node.loc);
77674             });
77675             if (!geoOrthoCanOrthogonalize(points, isClosed, epsilon, degreeThreshold, true)) return [];
77676             var autoArgs; // don't allow autosquaring features linked to wikidata
77677
77678             if (!entity.tags.wikidata) {
77679               // use same degree threshold as for detection
77680               var autoAction = actionOrthogonalize(entity.id, context.projection, undefined, degreeThreshold);
77681               autoAction.transitionable = false; // when autofixing, do it instantly
77682
77683               autoArgs = [autoAction, _t('operations.orthogonalize.annotation.feature', {
77684                 n: 1
77685               })];
77686             }
77687
77688             return [new validationIssue({
77689               type: type,
77690               subtype: 'building',
77691               severity: 'warning',
77692               message: function message(context) {
77693                 var entity = context.hasEntity(this.entityIds[0]);
77694                 return entity ? _t.html('issues.unsquare_way.message', {
77695                   feature: utilDisplayLabel(entity, context.graph())
77696                 }) : '';
77697               },
77698               reference: showReference,
77699               entityIds: [entity.id],
77700               hash: degreeThreshold,
77701               dynamicFixes: function dynamicFixes() {
77702                 return [new validationIssueFix({
77703                   icon: 'iD-operation-orthogonalize',
77704                   title: _t.html('issues.fix.square_feature.title'),
77705                   autoArgs: autoArgs,
77706                   onClick: function onClick(context, completionHandler) {
77707                     var entityId = this.issue.entityIds[0]; // use same degree threshold as for detection
77708
77709                     context.perform(actionOrthogonalize(entityId, context.projection, undefined, degreeThreshold), _t('operations.orthogonalize.annotation.feature', {
77710                       n: 1
77711                     })); // run after the squaring transition (currently 150ms)
77712
77713                     window.setTimeout(function () {
77714                       completionHandler();
77715                     }, 175);
77716                   }
77717                 })
77718                 /*
77719                 new validationIssueFix({
77720                     title: t.html('issues.fix.tag_as_unsquare.title'),
77721                     onClick: function(context) {
77722                         var entityId = this.issue.entityIds[0];
77723                         var entity = context.entity(entityId);
77724                         var tags = Object.assign({}, entity.tags);  // shallow copy
77725                         tags.nonsquare = 'yes';
77726                         context.perform(
77727                             actionChangeTags(entityId, tags),
77728                             t('issues.fix.tag_as_unsquare.annotation')
77729                         );
77730                     }
77731                 })
77732                 */
77733                 ];
77734               }
77735             })];
77736
77737             function showReference(selection) {
77738               selection.selectAll('.issue-reference').data([0]).enter().append('div').attr('class', 'issue-reference').call(_t.append('issues.unsquare_way.buildings.reference'));
77739             }
77740           };
77741
77742           validation.type = type;
77743           return validation;
77744         }
77745
77746         var Validations = /*#__PURE__*/Object.freeze({
77747                 __proto__: null,
77748                 validationAlmostJunction: validationAlmostJunction,
77749                 validationCloseNodes: validationCloseNodes,
77750                 validationCrossingWays: validationCrossingWays,
77751                 validationDisconnectedWay: validationDisconnectedWay,
77752                 validationFormatting: validationFormatting,
77753                 validationHelpRequest: validationHelpRequest,
77754                 validationImpossibleOneway: validationImpossibleOneway,
77755                 validationIncompatibleSource: validationIncompatibleSource,
77756                 validationMaprules: validationMaprules,
77757                 validationMismatchedGeometry: validationMismatchedGeometry,
77758                 validationMissingRole: validationMissingRole,
77759                 validationMissingTag: validationMissingTag,
77760                 validationOutdatedTags: validationOutdatedTags,
77761                 validationPrivateData: validationPrivateData,
77762                 validationSuspiciousName: validationSuspiciousName,
77763                 validationUnsquareWay: validationUnsquareWay
77764         });
77765
77766         function coreValidator(context) {
77767           var _this = this;
77768
77769           var dispatch = dispatch$8('validated', 'focusedIssue');
77770           var validator = utilRebind({}, dispatch, 'on');
77771           var _rules = {};
77772           var _disabledRules = {};
77773
77774           var _ignoredIssueIDs = new Set();
77775
77776           var _resolvedIssueIDs = new Set();
77777
77778           var _baseCache = validationCache('base'); // issues before any user edits
77779
77780
77781           var _headCache = validationCache('head'); // issues after all user edits
77782
77783
77784           var _completeDiff = {}; // complete diff base -> head of what the user changed
77785
77786           var _headIsCurrent = false;
77787
77788           var _deferredRIC = new Set(); // Set( RequestIdleCallback handles )
77789
77790
77791           var _deferredST = new Set(); // Set( SetTimeout handles )
77792
77793
77794           var _headPromise; // Promise fulfilled when validation is performed up to headGraph snapshot
77795
77796
77797           var RETRY = 5000; // wait 5sec before revalidating provisional entities
77798           // Allow validation severity to be overridden by url queryparams...
77799           // See: https://github.com/openstreetmap/iD/pull/8243
77800           //
77801           // Each param should contain a urlencoded comma separated list of
77802           // `type/subtype` rules.  `*` may be used as a wildcard..
77803           // Examples:
77804           //  `validationError=disconnected_way/*`
77805           //  `validationError=disconnected_way/highway`
77806           //  `validationError=crossing_ways/bridge*`
77807           //  `validationError=crossing_ways/bridge*,crossing_ways/tunnel*`
77808
77809           var _errorOverrides = parseHashParam(context.initialHashParams.validationError);
77810
77811           var _warningOverrides = parseHashParam(context.initialHashParams.validationWarning);
77812
77813           var _disableOverrides = parseHashParam(context.initialHashParams.validationDisable); // `parseHashParam()`   (private)
77814           // Checks hash parameters for severity overrides
77815           // Arguments
77816           //   `param` - a url hash parameter (`validationError`, `validationWarning`, or `validationDisable`)
77817           // Returns
77818           //   Array of Objects like { type: RegExp, subtype: RegExp }
77819           //
77820
77821
77822           function parseHashParam(param) {
77823             var result = [];
77824             var rules = (param || '').split(',');
77825             rules.forEach(function (rule) {
77826               rule = rule.trim();
77827               var parts = rule.split('/', 2); // "type/subtype"
77828
77829               var type = parts[0];
77830               var subtype = parts[1] || '*';
77831               if (!type || !subtype) return;
77832               result.push({
77833                 type: makeRegExp(type),
77834                 subtype: makeRegExp(subtype)
77835               });
77836             });
77837             return result;
77838
77839             function makeRegExp(str) {
77840               var escaped = str.replace(/[-\/\\^$+?.()|[\]{}]/g, '\\$&') // escape all reserved chars except for the '*'
77841               .replace(/\*/g, '.*'); // treat a '*' like '.*'
77842
77843               return new RegExp('^' + escaped + '$');
77844             }
77845           } // `init()`
77846           // Initialize the validator, called once on iD startup
77847           //
77848
77849
77850           validator.init = function () {
77851             Object.values(Validations).forEach(function (validation) {
77852               if (typeof validation !== 'function') return;
77853               var fn = validation(context);
77854               var key = fn.type;
77855               _rules[key] = fn;
77856             });
77857             var disabledRules = corePreferences('validate-disabledRules');
77858
77859             if (disabledRules) {
77860               disabledRules.split(',').forEach(function (k) {
77861                 return _disabledRules[k] = true;
77862               });
77863             }
77864           }; // `reset()`   (private)
77865           // Cancels deferred work and resets all caches
77866           //
77867           // Arguments
77868           //   `resetIgnored` - `true` to clear the list of user-ignored issues
77869           //
77870
77871
77872           function reset(resetIgnored) {
77873             // cancel deferred work
77874             _deferredRIC.forEach(window.cancelIdleCallback);
77875
77876             _deferredRIC.clear();
77877
77878             _deferredST.forEach(window.clearTimeout);
77879
77880             _deferredST.clear(); // empty queues and resolve any pending promise
77881
77882
77883             _baseCache.queue = [];
77884             _headCache.queue = [];
77885             processQueue(_headCache);
77886             processQueue(_baseCache); // clear caches
77887
77888             if (resetIgnored) _ignoredIssueIDs.clear();
77889
77890             _resolvedIssueIDs.clear();
77891
77892             _baseCache = validationCache('base');
77893             _headCache = validationCache('head');
77894             _completeDiff = {};
77895             _headIsCurrent = false;
77896           } // `reset()`
77897           // clear caches, called whenever iD resets after a save or switches sources
77898           // (clears out the _ignoredIssueIDs set also)
77899           //
77900
77901
77902           validator.reset = function () {
77903             reset(true);
77904           }; // `resetIgnoredIssues()`
77905           // clears out the _ignoredIssueIDs Set
77906           //
77907
77908
77909           validator.resetIgnoredIssues = function () {
77910             _ignoredIssueIDs.clear();
77911
77912             dispatch.call('validated'); // redraw UI
77913           }; // `revalidateUnsquare()`
77914           // Called whenever the user changes the unsquare threshold
77915           // It reruns just the "unsquare_way" validation on all buildings.
77916           //
77917
77918
77919           validator.revalidateUnsquare = function () {
77920             revalidateUnsquare(_headCache);
77921             revalidateUnsquare(_baseCache);
77922             dispatch.call('validated');
77923           };
77924
77925           function revalidateUnsquare(cache) {
77926             var checkUnsquareWay = _rules.unsquare_way;
77927             if (!cache.graph || typeof checkUnsquareWay !== 'function') return; // uncache existing
77928
77929             cache.uncacheIssuesOfType('unsquare_way');
77930             var buildings = context.history().tree().intersects(geoExtent([-180, -90], [180, 90]), cache.graph) // everywhere
77931             .filter(function (entity) {
77932               return entity.type === 'way' && entity.tags.building && entity.tags.building !== 'no';
77933             }); // rerun for all buildings
77934
77935             buildings.forEach(function (entity) {
77936               var detected = checkUnsquareWay(entity, cache.graph);
77937               if (!detected.length) return;
77938               cache.cacheIssues(detected);
77939             });
77940           } // `getIssues()`
77941           // Gets all issues that match the given options
77942           // This is called by many other places
77943           //
77944           // Arguments
77945           //   `options` Object like:
77946           //   {
77947           //     what: 'all',                  // 'all' or 'edited'
77948           //     where: 'all',                 // 'all' or 'visible'
77949           //     includeIgnored: false,        // true, false, or 'only'
77950           //     includeDisabledRules: false   // true, false, or 'only'
77951           //   }
77952           //
77953           // Returns
77954           //   An Array containing the issues
77955           //
77956
77957
77958           validator.getIssues = function (options) {
77959             var opts = Object.assign({
77960               what: 'all',
77961               where: 'all',
77962               includeIgnored: false,
77963               includeDisabledRules: false
77964             }, options);
77965             var view = context.map().extent();
77966             var seen = new Set();
77967             var results = []; // collect head issues - present in the user edits
77968
77969             if (_headCache.graph && _headCache.graph !== _baseCache.graph) {
77970               Object.values(_headCache.issuesByIssueID).forEach(function (issue) {
77971                 // In the head cache, only count features that the user is responsible for - #8632
77972                 // For example, a user can undo some work and an issue will still present in the
77973                 // head graph, but we don't want to credit the user for causing that issue.
77974                 var userModified = (issue.entityIds || []).some(function (id) {
77975                   return _completeDiff.hasOwnProperty(id);
77976                 });
77977                 if (opts.what === 'edited' && !userModified) return; // present in head but user didn't touch it
77978
77979                 if (!filter(issue)) return;
77980                 seen.add(issue.id);
77981                 results.push(issue);
77982               });
77983             } // collect base issues - present before user edits
77984
77985
77986             if (opts.what === 'all') {
77987               Object.values(_baseCache.issuesByIssueID).forEach(function (issue) {
77988                 if (!filter(issue)) return;
77989                 seen.add(issue.id);
77990                 results.push(issue);
77991               });
77992             }
77993
77994             return results; // Filter the issue set to include only what the calling code wants to see.
77995             // Note that we use `context.graph()`/`context.hasEntity()` here, not `cache.graph`,
77996             // because that is the graph that the calling code will be using.
77997
77998             function filter(issue) {
77999               if (!issue) return false;
78000               if (seen.has(issue.id)) return false;
78001               if (_resolvedIssueIDs.has(issue.id)) return false;
78002               if (opts.includeDisabledRules === 'only' && !_disabledRules[issue.type]) return false;
78003               if (!opts.includeDisabledRules && _disabledRules[issue.type]) return false;
78004               if (opts.includeIgnored === 'only' && !_ignoredIssueIDs.has(issue.id)) return false;
78005               if (!opts.includeIgnored && _ignoredIssueIDs.has(issue.id)) return false; // This issue may involve an entity that doesn't exist in context.graph()
78006               // This can happen because validation is async and rendering the issue lists is async.
78007
78008               if ((issue.entityIds || []).some(function (id) {
78009                 return !context.hasEntity(id);
78010               })) return false;
78011
78012               if (opts.where === 'visible') {
78013                 var extent = issue.extent(context.graph());
78014                 if (!view.intersects(extent)) return false;
78015               }
78016
78017               return true;
78018             }
78019           }; // `getResolvedIssues()`
78020           // Gets the issues that have been fixed by the user.
78021           //
78022           // Resolved issues are tracked in the `_resolvedIssueIDs` Set,
78023           // and they should all be issues that exist in the _baseCache.
78024           //
78025           // Returns
78026           //   An Array containing the issues
78027           //
78028
78029
78030           validator.getResolvedIssues = function () {
78031             return Array.from(_resolvedIssueIDs).map(function (issueID) {
78032               return _baseCache.issuesByIssueID[issueID];
78033             }).filter(Boolean);
78034           }; // `focusIssue()`
78035           // Adjusts the map to focus on the given issue.
78036           // (requires the issue to have a reasonable extent defined)
78037           //
78038           // Arguments
78039           //   `issue` - the issue to focus on
78040           //
78041
78042
78043           validator.focusIssue = function (issue) {
78044             // Note that we use `context.graph()`/`context.hasEntity()` here, not `cache.graph`,
78045             // because that is the graph that the calling code will be using.
78046             var graph = context.graph();
78047             var selectID;
78048             var focusCenter; // Try to focus the map at the center of the issue..
78049
78050             var issueExtent = issue.extent(graph);
78051
78052             if (issueExtent) {
78053               focusCenter = issueExtent.center();
78054             } // Try to select the first entity in the issue..
78055
78056
78057             if (issue.entityIds && issue.entityIds.length) {
78058               selectID = issue.entityIds[0]; // If a relation, focus on one of its members instead.
78059               // Otherwise we might be focusing on a part of map where the relation is not visible.
78060
78061               if (selectID && selectID.charAt(0) === 'r') {
78062                 // relation
78063                 var ids = utilEntityAndDeepMemberIDs([selectID], graph);
78064                 var nodeID = ids.find(function (id) {
78065                   return id.charAt(0) === 'n' && graph.hasEntity(id);
78066                 });
78067
78068                 if (!nodeID) {
78069                   // relation has no downloaded nodes to focus on
78070                   var wayID = ids.find(function (id) {
78071                     return id.charAt(0) === 'w' && graph.hasEntity(id);
78072                   });
78073
78074                   if (wayID) {
78075                     nodeID = graph.entity(wayID).first(); // focus on the first node of this way
78076                   }
78077                 }
78078
78079                 if (nodeID) {
78080                   focusCenter = graph.entity(nodeID).loc;
78081                 }
78082               }
78083             }
78084
78085             if (focusCenter) {
78086               // Adjust the view
78087               var setZoom = Math.max(context.map().zoom(), 19);
78088               context.map().unobscuredCenterZoomEase(focusCenter, setZoom);
78089             }
78090
78091             if (selectID) {
78092               // Enter select mode
78093               window.setTimeout(function () {
78094                 context.enter(modeSelect(context, [selectID]));
78095                 dispatch.call('focusedIssue', _this, issue);
78096               }, 250); // after ease
78097             }
78098           }; // `getIssuesBySeverity()`
78099           // Gets the issues then groups them by error/warning
78100           // (This just calls getIssues, then puts issues in groups)
78101           //
78102           // Arguments
78103           //   `options` - (see `getIssues`)
78104           // Returns
78105           //   Object result like:
78106           //   {
78107           //     error:    Array of errors,
78108           //     warning:  Array of warnings
78109           //   }
78110           //
78111
78112
78113           validator.getIssuesBySeverity = function (options) {
78114             var groups = utilArrayGroupBy(validator.getIssues(options), 'severity');
78115             groups.error = groups.error || [];
78116             groups.warning = groups.warning || [];
78117             return groups;
78118           }; // `getEntityIssues()`
78119           // Gets the issues that the given entity IDs have in common, matching the given options
78120           // (This just calls getIssues, then filters for the given entity IDs)
78121           // The issues are sorted for relevance
78122           //
78123           // Arguments
78124           //   `entityIDs` - Array or Set of entityIDs to get issues for
78125           //   `options` - (see `getIssues`)
78126           // Returns
78127           //   An Array containing the issues
78128           //
78129
78130
78131           validator.getSharedEntityIssues = function (entityIDs, options) {
78132             var orderedIssueTypes = [// Show some issue types in a particular order:
78133             'missing_tag', 'missing_role', // - missing data first
78134             'outdated_tags', 'mismatched_geometry', // - identity issues
78135             'crossing_ways', 'almost_junction', // - geometry issues where fixing them might solve connectivity issues
78136             'disconnected_way', 'impossible_oneway' // - finally connectivity issues
78137             ];
78138             var allIssues = validator.getIssues(options);
78139             var forEntityIDs = new Set(entityIDs);
78140             return allIssues.filter(function (issue) {
78141               return (issue.entityIds || []).some(function (entityID) {
78142                 return forEntityIDs.has(entityID);
78143               });
78144             }).sort(function (issue1, issue2) {
78145               if (issue1.type === issue2.type) {
78146                 // issues of the same type, sort deterministically
78147                 return issue1.id < issue2.id ? -1 : 1;
78148               }
78149
78150               var index1 = orderedIssueTypes.indexOf(issue1.type);
78151               var index2 = orderedIssueTypes.indexOf(issue2.type);
78152
78153               if (index1 !== -1 && index2 !== -1) {
78154                 // both issue types have explicit sort orders
78155                 return index1 - index2;
78156               } else if (index1 === -1 && index2 === -1) {
78157                 // neither issue type has an explicit sort order, sort by type
78158                 return issue1.type < issue2.type ? -1 : 1;
78159               } else {
78160                 // order explicit types before everything else
78161                 return index1 !== -1 ? -1 : 1;
78162               }
78163             });
78164           }; // `getEntityIssues()`
78165           // Get an array of detected issues for the given entityID.
78166           // (This just calls getSharedEntityIssues for a single entity)
78167           //
78168           // Arguments
78169           //   `entityID` - the entity ID to get the issues for
78170           //   `options` - (see `getIssues`)
78171           // Returns
78172           //   An Array containing the issues
78173           //
78174
78175
78176           validator.getEntityIssues = function (entityID, options) {
78177             return validator.getSharedEntityIssues([entityID], options);
78178           }; // `getRuleKeys()`
78179           //
78180           // Returns
78181           //   An Array containing the rule keys
78182           //
78183
78184
78185           validator.getRuleKeys = function () {
78186             return Object.keys(_rules);
78187           }; // `isRuleEnabled()`
78188           //
78189           // Arguments
78190           //   `key` - the rule to check (e.g. 'crossing_ways')
78191           // Returns
78192           //   `true`/`false`
78193           //
78194
78195
78196           validator.isRuleEnabled = function (key) {
78197             return !_disabledRules[key];
78198           }; // `toggleRule()`
78199           // Toggles a single validation rule,
78200           // then reruns the validation so that the user sees something happen in the UI
78201           //
78202           // Arguments
78203           //   `key` - the rule to toggle (e.g. 'crossing_ways')
78204           //
78205
78206
78207           validator.toggleRule = function (key) {
78208             if (_disabledRules[key]) {
78209               delete _disabledRules[key];
78210             } else {
78211               _disabledRules[key] = true;
78212             }
78213
78214             corePreferences('validate-disabledRules', Object.keys(_disabledRules).join(','));
78215             validator.validate();
78216           }; // `disableRules()`
78217           // Disables given validation rules,
78218           // then reruns the validation so that the user sees something happen in the UI
78219           //
78220           // Arguments
78221           //   `keys` - Array or Set containing rule keys to disable
78222           //
78223
78224
78225           validator.disableRules = function (keys) {
78226             _disabledRules = {};
78227             keys.forEach(function (k) {
78228               return _disabledRules[k] = true;
78229             });
78230             corePreferences('validate-disabledRules', Object.keys(_disabledRules).join(','));
78231             validator.validate();
78232           }; // `ignoreIssue()`
78233           // Don't show the given issue in lists
78234           //
78235           // Arguments
78236           //   `issueID` - the issueID
78237           //
78238
78239
78240           validator.ignoreIssue = function (issueID) {
78241             _ignoredIssueIDs.add(issueID);
78242           }; // `validate()`
78243           // Validates anything that has changed in the head graph since the last time it was run.
78244           // (head graph contains user's edits)
78245           //
78246           // Returns
78247           //   A Promise fulfilled when the validation has completed and then dispatches a `validated` event.
78248           //   This may take time but happen in the background during browser idle time.
78249           //
78250
78251
78252           validator.validate = function () {
78253             // Make sure the caches have graphs assigned to them.
78254             // (we don't do this in `reset` because context is still resetting things and `history.base()` is unstable then)
78255             var baseGraph = context.history().base();
78256             if (!_headCache.graph) _headCache.graph = baseGraph;
78257             if (!_baseCache.graph) _baseCache.graph = baseGraph;
78258             var prevGraph = _headCache.graph;
78259             var currGraph = context.graph();
78260
78261             if (currGraph === prevGraph) {
78262               // _headCache.graph is current - we are caught up
78263               _headIsCurrent = true;
78264               dispatch.call('validated');
78265               return Promise.resolve();
78266             }
78267
78268             if (_headPromise) {
78269               // Validation already in process, but we aren't caught up to current
78270               _headIsCurrent = false; // We will need to catch up after the validation promise fulfills
78271
78272               return _headPromise;
78273             } // If we get here, its time to start validating stuff.
78274
78275
78276             _headCache.graph = currGraph; // take snapshot
78277
78278             _completeDiff = context.history().difference().complete();
78279             var incrementalDiff = coreDifference(prevGraph, currGraph);
78280             var entityIDs = Object.keys(incrementalDiff.complete());
78281             entityIDs = _headCache.withAllRelatedEntities(entityIDs); // expand set
78282
78283             if (!entityIDs.size) {
78284               dispatch.call('validated');
78285               return Promise.resolve();
78286             }
78287
78288             _headPromise = validateEntitiesAsync(entityIDs, _headCache).then(function () {
78289               return updateResolvedIssues(entityIDs);
78290             }).then(function () {
78291               return dispatch.call('validated');
78292             })["catch"](function () {
78293               /* ignore */
78294             }).then(function () {
78295               _headPromise = null;
78296
78297               if (!_headIsCurrent) {
78298                 validator.validate(); // run it again to catch up to current graph
78299               }
78300             });
78301             return _headPromise;
78302           }; // register event handlers:
78303           // WHEN TO RUN VALIDATION:
78304           // When history changes:
78305
78306
78307           context.history().on('restore.validator', validator.validate) // on restore saved history
78308           .on('undone.validator', validator.validate) // on undo
78309           .on('redone.validator', validator.validate) // on redo
78310           .on('reset.validator', function () {
78311             // on history reset - happens after save, or enter/exit walkthrough
78312             reset(false); // cached issues aren't valid any longer if the history has been reset
78313
78314             validator.validate();
78315           }); // but not on 'change' (e.g. while drawing)
78316           // When user changes editing modes (to catch recent changes e.g. drawing)
78317
78318           context.on('exit.validator', validator.validate); // When merging fetched data, validate base graph:
78319
78320           context.history().on('merge.validator', function (entities) {
78321             if (!entities) return; // Make sure the caches have graphs assigned to them.
78322             // (we don't do this in `reset` because context is still resetting things and `history.base()` is unstable then)
78323
78324             var baseGraph = context.history().base();
78325             if (!_headCache.graph) _headCache.graph = baseGraph;
78326             if (!_baseCache.graph) _baseCache.graph = baseGraph;
78327             var entityIDs = entities.map(function (entity) {
78328               return entity.id;
78329             });
78330             entityIDs = _baseCache.withAllRelatedEntities(entityIDs); // expand set
78331
78332             validateEntitiesAsync(entityIDs, _baseCache);
78333           }); // `validateEntity()`   (private)
78334           // Runs all validation rules on a single entity.
78335           // Some things to note:
78336           //  - Graph is passed in from whenever the validation was started.  Validators shouldn't use
78337           //   `context.graph()` because this all happens async, and the graph might have changed
78338           //   (for example, nodes getting deleted before the validation can run)
78339           //  - Validator functions may still be waiting on something and return a "provisional" result.
78340           //    In this situation, we will schedule to revalidate the entity sometime later.
78341           //
78342           // Arguments
78343           //   `entity` - The entity
78344           //   `graph` - graph containing the entity
78345           //
78346           // Returns
78347           //   Object result like:
78348           //   {
78349           //     issues:       Array of detected issues
78350           //     provisional:  `true` if provisional result, `false` if final result
78351           //   }
78352           //
78353
78354           function validateEntity(entity, graph) {
78355             var result = {
78356               issues: [],
78357               provisional: false
78358             };
78359             Object.keys(_rules).forEach(runValidation); // run all rules
78360
78361             return result; // runs validation and appends resulting issues
78362
78363             function runValidation(key) {
78364               var fn = _rules[key];
78365
78366               if (typeof fn !== 'function') {
78367                 console.error('no such validation rule = ' + key); // eslint-disable-line no-console
78368
78369                 return;
78370               }
78371
78372               var detected = fn(entity, graph);
78373
78374               if (detected.provisional) {
78375                 // this validation should be run again later
78376                 result.provisional = true;
78377               }
78378
78379               detected = detected.filter(applySeverityOverrides);
78380               result.issues = result.issues.concat(detected); // If there are any override rules that match the issue type/subtype,
78381               // adjust severity (or disable it) and keep/discard as quickly as possible.
78382
78383               function applySeverityOverrides(issue) {
78384                 var type = issue.type;
78385                 var subtype = issue.subtype || '';
78386                 var i;
78387
78388                 for (i = 0; i < _errorOverrides.length; i++) {
78389                   if (_errorOverrides[i].type.test(type) && _errorOverrides[i].subtype.test(subtype)) {
78390                     issue.severity = 'error';
78391                     return true;
78392                   }
78393                 }
78394
78395                 for (i = 0; i < _warningOverrides.length; i++) {
78396                   if (_warningOverrides[i].type.test(type) && _warningOverrides[i].subtype.test(subtype)) {
78397                     issue.severity = 'warning';
78398                     return true;
78399                   }
78400                 }
78401
78402                 for (i = 0; i < _disableOverrides.length; i++) {
78403                   if (_disableOverrides[i].type.test(type) && _disableOverrides[i].subtype.test(subtype)) {
78404                     return false;
78405                   }
78406                 }
78407
78408                 return true;
78409               }
78410             }
78411           } // `updateResolvedIssues()`   (private)
78412           // Determine if any issues were resolved for the given entities.
78413           // This is called by `validate()` after validation of the head graph
78414           //
78415           // Give the user credit for fixing an issue if:
78416           // - the issue is in the base cache
78417           // - the issue is not in the head cache
78418           // - the user did something to one of the entities involved in the issue
78419           //
78420           // Arguments
78421           //   `entityIDs` - Array or Set containing entity IDs.
78422           //
78423
78424
78425           function updateResolvedIssues(entityIDs) {
78426             entityIDs.forEach(function (entityID) {
78427               var baseIssues = _baseCache.issuesByEntityID[entityID];
78428               if (!baseIssues) return;
78429               baseIssues.forEach(function (issueID) {
78430                 // Check if the user did something to one of the entities involved in this issue.
78431                 // (This issue could involve multiple entities, e.g. disconnected routable features)
78432                 var issue = _baseCache.issuesByIssueID[issueID];
78433                 var userModified = (issue.entityIds || []).some(function (id) {
78434                   return _completeDiff.hasOwnProperty(id);
78435                 });
78436
78437                 if (userModified && !_headCache.issuesByIssueID[issueID]) {
78438                   // issue seems fixed
78439                   _resolvedIssueIDs.add(issueID);
78440                 } else {
78441                   // issue still not resolved
78442                   _resolvedIssueIDs["delete"](issueID); // (did undo, or possibly fixed and then re-caused the issue)
78443
78444                 }
78445               });
78446             });
78447           } // `validateEntitiesAsync()`   (private)
78448           // Schedule validation for many entities.
78449           //
78450           // Arguments
78451           //   `entityIDs` - Array or Set containing entityIDs.
78452           //   `graph` - the graph to validate that contains those entities
78453           //   `cache` - the cache to store results in (_headCache or _baseCache)
78454           //
78455           // Returns
78456           //   A Promise fulfilled when the validation has completed.
78457           //   This may take time but happen in the background during browser idle time.
78458           //
78459
78460
78461           function validateEntitiesAsync(entityIDs, cache) {
78462             // Enqueue the work
78463             var jobs = Array.from(entityIDs).map(function (entityID) {
78464               if (cache.queuedEntityIDs.has(entityID)) return null; // queued already
78465
78466               cache.queuedEntityIDs.add(entityID); // Clear caches for existing issues related to this entity
78467
78468               cache.uncacheEntityID(entityID);
78469               return function () {
78470                 cache.queuedEntityIDs["delete"](entityID);
78471                 var graph = cache.graph;
78472                 if (!graph) return; // was reset?
78473
78474                 var entity = graph.hasEntity(entityID); // Sanity check: don't validate deleted entities
78475
78476                 if (!entity) return; // detect new issues and update caches
78477
78478                 var result = validateEntity(entity, graph);
78479
78480                 if (result.provisional) {
78481                   // provisional result
78482                   cache.provisionalEntityIDs.add(entityID); // we'll need to revalidate this entity again later
78483                 }
78484
78485                 cache.cacheIssues(result.issues); // update cache
78486               };
78487             }).filter(Boolean); // Perform the work in chunks.
78488             // Because this will happen during idle callbacks, we want to choose a chunk size
78489             // that won't make the browser stutter too badly.
78490
78491             cache.queue = cache.queue.concat(utilArrayChunk(jobs, 100)); // Perform the work
78492
78493             if (cache.queuePromise) return cache.queuePromise;
78494             cache.queuePromise = processQueue(cache).then(function () {
78495               return revalidateProvisionalEntities(cache);
78496             })["catch"](function () {
78497               /* ignore */
78498             })["finally"](function () {
78499               return cache.queuePromise = null;
78500             });
78501             return cache.queuePromise;
78502           } // `revalidateProvisionalEntities()`   (private)
78503           // Sometimes a validator will return a "provisional" result.
78504           // In this situation, we'll need to revalidate the entity later.
78505           // This function waits a delay, then places them back into the validation queue.
78506           //
78507           // Arguments
78508           //   `cache` - The cache (_headCache or _baseCache)
78509           //
78510
78511
78512           function revalidateProvisionalEntities(cache) {
78513             if (!cache.provisionalEntityIDs.size) return; // nothing to do
78514
78515             var handle = window.setTimeout(function () {
78516               _deferredST["delete"](handle);
78517
78518               if (!cache.provisionalEntityIDs.size) return; // nothing to do
78519
78520               validateEntitiesAsync(Array.from(cache.provisionalEntityIDs), cache);
78521             }, RETRY);
78522
78523             _deferredST.add(handle);
78524           } // `processQueue(queue)`   (private)
78525           // Process the next chunk of deferred validation work
78526           //
78527           // Arguments
78528           //   `cache` - The cache (_headCache or _baseCache)
78529           //
78530           // Returns
78531           //   A Promise fulfilled when the validation has completed.
78532           //   This may take time but happen in the background during browser idle time.
78533           //
78534
78535
78536           function processQueue(cache) {
78537             // console.log(`${cache.which} queue length ${cache.queue.length}`);
78538             if (!cache.queue.length) return Promise.resolve(); // we're done
78539
78540             var chunk = cache.queue.pop();
78541             return new Promise(function (resolvePromise) {
78542               var handle = window.requestIdleCallback(function () {
78543                 _deferredRIC["delete"](handle); // const t0 = performance.now();
78544
78545
78546                 chunk.forEach(function (job) {
78547                   return job();
78548                 }); // const t1 = performance.now();
78549                 // console.log('chunk processed in ' + (t1 - t0) + ' ms');
78550
78551                 resolvePromise();
78552               });
78553
78554               _deferredRIC.add(handle);
78555             }).then(function () {
78556               // dispatch an event sometimes to redraw various UI things
78557               if (cache.queue.length % 25 === 0) dispatch.call('validated');
78558             }).then(function () {
78559               return processQueue(cache);
78560             });
78561           }
78562
78563           return validator;
78564         } // `validationCache()`   (private)
78565         // Creates a cache to store validation state
78566         // We create 2 of these:
78567         //   `_baseCache` for validation on the base graph (unedited)
78568         //   `_headCache` for validation on the head graph (user edits applied)
78569         //
78570         // Arguments
78571         //   `which` - just a String 'base' or 'head' to keep track of it
78572         //
78573
78574         function validationCache(which) {
78575           var cache = {
78576             which: which,
78577             graph: null,
78578             queue: [],
78579             queuePromise: null,
78580             queuedEntityIDs: new Set(),
78581             provisionalEntityIDs: new Set(),
78582             issuesByIssueID: {},
78583             // issue.id -> issue
78584             issuesByEntityID: {} // entity.id -> Set(issue.id)
78585
78586           };
78587
78588           cache.cacheIssue = function (issue) {
78589             (issue.entityIds || []).forEach(function (entityID) {
78590               if (!cache.issuesByEntityID[entityID]) {
78591                 cache.issuesByEntityID[entityID] = new Set();
78592               }
78593
78594               cache.issuesByEntityID[entityID].add(issue.id);
78595             });
78596             cache.issuesByIssueID[issue.id] = issue;
78597           };
78598
78599           cache.uncacheIssue = function (issue) {
78600             (issue.entityIds || []).forEach(function (entityID) {
78601               if (cache.issuesByEntityID[entityID]) {
78602                 cache.issuesByEntityID[entityID]["delete"](issue.id);
78603               }
78604             });
78605             delete cache.issuesByIssueID[issue.id];
78606           };
78607
78608           cache.cacheIssues = function (issues) {
78609             issues.forEach(cache.cacheIssue);
78610           };
78611
78612           cache.uncacheIssues = function (issues) {
78613             issues.forEach(cache.uncacheIssue);
78614           };
78615
78616           cache.uncacheIssuesOfType = function (type) {
78617             var issuesOfType = Object.values(cache.issuesByIssueID).filter(function (issue) {
78618               return issue.type === type;
78619             });
78620             cache.uncacheIssues(issuesOfType);
78621           }; // Remove a single entity and all its related issues from the caches
78622
78623
78624           cache.uncacheEntityID = function (entityID) {
78625             var entityIssueIDs = cache.issuesByEntityID[entityID];
78626
78627             if (entityIssueIDs) {
78628               entityIssueIDs.forEach(function (issueID) {
78629                 var issue = cache.issuesByIssueID[issueID];
78630
78631                 if (issue) {
78632                   cache.uncacheIssue(issue);
78633                 } else {
78634                   // shouldn't happen, clean up
78635                   delete cache.issuesByIssueID[issueID];
78636                 }
78637               });
78638             }
78639
78640             delete cache.issuesByEntityID[entityID];
78641             cache.provisionalEntityIDs["delete"](entityID);
78642           }; // Return the expandeded set of entityIDs related to issues for the given entityIDs
78643           //
78644           // Arguments
78645           //   `entityIDs` - Array or Set containing entityIDs.
78646           //
78647
78648
78649           cache.withAllRelatedEntities = function (entityIDs) {
78650             var result = new Set();
78651             (entityIDs || []).forEach(function (entityID) {
78652               result.add(entityID); // include self
78653
78654               var entityIssueIDs = cache.issuesByEntityID[entityID];
78655
78656               if (entityIssueIDs) {
78657                 entityIssueIDs.forEach(function (issueID) {
78658                   var issue = cache.issuesByIssueID[issueID];
78659
78660                   if (issue) {
78661                     (issue.entityIds || []).forEach(function (relatedID) {
78662                       return result.add(relatedID);
78663                     });
78664                   } else {
78665                     // shouldn't happen, clean up
78666                     delete cache.issuesByIssueID[issueID];
78667                   }
78668                 });
78669               }
78670             });
78671             return result;
78672           };
78673
78674           return cache;
78675         }
78676
78677         function coreUploader(context) {
78678           var dispatch = dispatch$8( // Start and end events are dispatched exactly once each per legitimate outside call to `save`
78679           'saveStarted', // dispatched as soon as a call to `save` has been deemed legitimate
78680           'saveEnded', // dispatched after the result event has been dispatched
78681           'willAttemptUpload', // dispatched before the actual upload call occurs, if it will
78682           'progressChanged', // Each save results in one of these outcomes:
78683           'resultNoChanges', // upload wasn't attempted since there were no edits
78684           'resultErrors', // upload failed due to errors
78685           'resultConflicts', // upload failed due to data conflicts
78686           'resultSuccess' // upload completed without errors
78687           );
78688           var _isSaving = false;
78689           var _conflicts = [];
78690           var _errors = [];
78691
78692           var _origChanges;
78693
78694           var _discardTags = {};
78695           _mainFileFetcher.get('discarded').then(function (d) {
78696             _discardTags = d;
78697           })["catch"](function () {
78698             /* ignore */
78699           });
78700           var uploader = utilRebind({}, dispatch, 'on');
78701
78702           uploader.isSaving = function () {
78703             return _isSaving;
78704           };
78705
78706           uploader.save = function (changeset, tryAgain, checkConflicts) {
78707             // Guard against accidentally entering save code twice - #4641
78708             if (_isSaving && !tryAgain) {
78709               return;
78710             }
78711
78712             var osm = context.connection();
78713             if (!osm) return; // If user somehow got logged out mid-save, try to reauthenticate..
78714             // This can happen if they were logged in from before, but the tokens are no longer valid.
78715
78716             if (!osm.authenticated()) {
78717               osm.authenticate(function (err) {
78718                 if (!err) {
78719                   uploader.save(changeset, tryAgain, checkConflicts); // continue where we left off..
78720                 }
78721               });
78722               return;
78723             }
78724
78725             if (!_isSaving) {
78726               _isSaving = true;
78727               dispatch.call('saveStarted', this);
78728             }
78729
78730             var history = context.history();
78731             _conflicts = [];
78732             _errors = []; // Store original changes, in case user wants to download them as an .osc file
78733
78734             _origChanges = history.changes(actionDiscardTags(history.difference(), _discardTags)); // First time, `history.perform` a no-op action.
78735             // Any conflict resolutions will be done as `history.replace`
78736             // Remember to pop this later if needed
78737
78738             if (!tryAgain) {
78739               history.perform(actionNoop());
78740             } // Attempt a fast upload.. If there are conflicts, re-enter with `checkConflicts = true`
78741
78742
78743             if (!checkConflicts) {
78744               upload(changeset); // Do the full (slow) conflict check..
78745             } else {
78746               performFullConflictCheck(changeset);
78747             }
78748           };
78749
78750           function performFullConflictCheck(changeset) {
78751             var osm = context.connection();
78752             if (!osm) return;
78753             var history = context.history();
78754             var localGraph = context.graph();
78755             var remoteGraph = coreGraph(history.base(), true);
78756             var summary = history.difference().summary();
78757             var _toCheck = [];
78758
78759             for (var i = 0; i < summary.length; i++) {
78760               var item = summary[i];
78761
78762               if (item.changeType === 'modified') {
78763                 _toCheck.push(item.entity.id);
78764               }
78765             }
78766
78767             var _toLoad = withChildNodes(_toCheck, localGraph);
78768
78769             var _loaded = {};
78770             var _toLoadCount = 0;
78771             var _toLoadTotal = _toLoad.length;
78772
78773             if (_toCheck.length) {
78774               dispatch.call('progressChanged', this, _toLoadCount, _toLoadTotal);
78775
78776               _toLoad.forEach(function (id) {
78777                 _loaded[id] = false;
78778               });
78779
78780               osm.loadMultiple(_toLoad, loaded);
78781             } else {
78782               upload(changeset);
78783             }
78784
78785             return;
78786
78787             function withChildNodes(ids, graph) {
78788               var s = new Set(ids);
78789               ids.forEach(function (id) {
78790                 var entity = graph.entity(id);
78791                 if (entity.type !== 'way') return;
78792                 graph.childNodes(entity).forEach(function (child) {
78793                   if (child.version !== undefined) {
78794                     s.add(child.id);
78795                   }
78796                 });
78797               });
78798               return Array.from(s);
78799             } // Reload modified entities into an alternate graph and check for conflicts..
78800
78801
78802             function loaded(err, result) {
78803               if (_errors.length) return;
78804
78805               if (err) {
78806                 _errors.push({
78807                   msg: err.message || err.responseText,
78808                   details: [_t('save.status_code', {
78809                     code: err.status
78810                   })]
78811                 });
78812
78813                 didResultInErrors();
78814               } else {
78815                 var loadMore = [];
78816                 result.data.forEach(function (entity) {
78817                   remoteGraph.replace(entity);
78818                   _loaded[entity.id] = true;
78819                   _toLoad = _toLoad.filter(function (val) {
78820                     return val !== entity.id;
78821                   });
78822                   if (!entity.visible) return; // Because loadMultiple doesn't download /full like loadEntity,
78823                   // need to also load children that aren't already being checked..
78824
78825                   var i, id;
78826
78827                   if (entity.type === 'way') {
78828                     for (i = 0; i < entity.nodes.length; i++) {
78829                       id = entity.nodes[i];
78830
78831                       if (_loaded[id] === undefined) {
78832                         _loaded[id] = false;
78833                         loadMore.push(id);
78834                       }
78835                     }
78836                   } else if (entity.type === 'relation' && entity.isMultipolygon()) {
78837                     for (i = 0; i < entity.members.length; i++) {
78838                       id = entity.members[i].id;
78839
78840                       if (_loaded[id] === undefined) {
78841                         _loaded[id] = false;
78842                         loadMore.push(id);
78843                       }
78844                     }
78845                   }
78846                 });
78847                 _toLoadCount += result.data.length;
78848                 _toLoadTotal += loadMore.length;
78849                 dispatch.call('progressChanged', this, _toLoadCount, _toLoadTotal);
78850
78851                 if (loadMore.length) {
78852                   _toLoad.push.apply(_toLoad, loadMore);
78853
78854                   osm.loadMultiple(loadMore, loaded);
78855                 }
78856
78857                 if (!_toLoad.length) {
78858                   detectConflicts();
78859                   upload(changeset);
78860                 }
78861               }
78862             }
78863
78864             function detectConflicts() {
78865               function choice(id, text, _action) {
78866                 return {
78867                   id: id,
78868                   text: text,
78869                   action: function action() {
78870                     history.replace(_action);
78871                   }
78872                 };
78873               }
78874
78875               function formatUser(d) {
78876                 return '<a href="' + osm.userURL(d) + '" target="_blank">' + escape$4(d) + '</a>';
78877               }
78878
78879               function entityName(entity) {
78880                 return utilDisplayName(entity) || utilDisplayType(entity.id) + ' ' + entity.id;
78881               }
78882
78883               function sameVersions(local, remote) {
78884                 if (local.version !== remote.version) return false;
78885
78886                 if (local.type === 'way') {
78887                   var children = utilArrayUnion(local.nodes, remote.nodes);
78888
78889                   for (var i = 0; i < children.length; i++) {
78890                     var a = localGraph.hasEntity(children[i]);
78891                     var b = remoteGraph.hasEntity(children[i]);
78892                     if (a && b && a.version !== b.version) return false;
78893                   }
78894                 }
78895
78896                 return true;
78897               }
78898
78899               _toCheck.forEach(function (id) {
78900                 var local = localGraph.entity(id);
78901                 var remote = remoteGraph.entity(id);
78902                 if (sameVersions(local, remote)) return;
78903                 var merge = actionMergeRemoteChanges(id, localGraph, remoteGraph, _discardTags, formatUser);
78904                 history.replace(merge);
78905                 var mergeConflicts = merge.conflicts();
78906                 if (!mergeConflicts.length) return; // merged safely
78907
78908                 var forceLocal = actionMergeRemoteChanges(id, localGraph, remoteGraph, _discardTags).withOption('force_local');
78909                 var forceRemote = actionMergeRemoteChanges(id, localGraph, remoteGraph, _discardTags).withOption('force_remote');
78910                 var keepMine = _t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore'));
78911                 var keepTheirs = _t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
78912
78913                 _conflicts.push({
78914                   id: id,
78915                   name: entityName(local),
78916                   details: mergeConflicts,
78917                   chosen: 1,
78918                   choices: [choice(id, keepMine, forceLocal), choice(id, keepTheirs, forceRemote)]
78919                 });
78920               });
78921             }
78922           }
78923
78924           function upload(changeset) {
78925             var osm = context.connection();
78926
78927             if (!osm) {
78928               _errors.push({
78929                 msg: 'No OSM Service'
78930               });
78931             }
78932
78933             if (_conflicts.length) {
78934               didResultInConflicts(changeset);
78935             } else if (_errors.length) {
78936               didResultInErrors();
78937             } else {
78938               var history = context.history();
78939               var changes = history.changes(actionDiscardTags(history.difference(), _discardTags));
78940
78941               if (changes.modified.length || changes.created.length || changes.deleted.length) {
78942                 dispatch.call('willAttemptUpload', this);
78943                 osm.putChangeset(changeset, changes, uploadCallback);
78944               } else {
78945                 // changes were insignificant or reverted by user
78946                 didResultInNoChanges();
78947               }
78948             }
78949           }
78950
78951           function uploadCallback(err, changeset) {
78952             if (err) {
78953               if (err.status === 409) {
78954                 // 409 Conflict
78955                 uploader.save(changeset, true, true); // tryAgain = true, checkConflicts = true
78956               } else {
78957                 _errors.push({
78958                   msg: err.message || err.responseText,
78959                   details: [_t('save.status_code', {
78960                     code: err.status
78961                   })]
78962                 });
78963
78964                 didResultInErrors();
78965               }
78966             } else {
78967               didResultInSuccess(changeset);
78968             }
78969           }
78970
78971           function didResultInNoChanges() {
78972             dispatch.call('resultNoChanges', this);
78973             endSave();
78974             context.flush(); // reset iD
78975           }
78976
78977           function didResultInErrors() {
78978             context.history().pop();
78979             dispatch.call('resultErrors', this, _errors);
78980             endSave();
78981           }
78982
78983           function didResultInConflicts(changeset) {
78984             _conflicts.sort(function (a, b) {
78985               return b.id.localeCompare(a.id);
78986             });
78987
78988             dispatch.call('resultConflicts', this, changeset, _conflicts, _origChanges);
78989             endSave();
78990           }
78991
78992           function didResultInSuccess(changeset) {
78993             // delete the edit stack cached to local storage
78994             context.history().clearSaved();
78995             dispatch.call('resultSuccess', this, changeset); // Add delay to allow for postgres replication #1646 #2678
78996
78997             window.setTimeout(function () {
78998               endSave();
78999               context.flush(); // reset iD
79000             }, 2500);
79001           }
79002
79003           function endSave() {
79004             _isSaving = false;
79005             dispatch.call('saveEnded', this);
79006           }
79007
79008           uploader.cancelConflictResolution = function () {
79009             context.history().pop();
79010           };
79011
79012           uploader.processResolvedConflicts = function (changeset) {
79013             var history = context.history();
79014
79015             for (var i = 0; i < _conflicts.length; i++) {
79016               if (_conflicts[i].chosen === 1) {
79017                 // user chose "use theirs"
79018                 var entity = context.hasEntity(_conflicts[i].id);
79019
79020                 if (entity && entity.type === 'way') {
79021                   var children = utilArrayUniq(entity.nodes);
79022
79023                   for (var j = 0; j < children.length; j++) {
79024                     history.replace(actionRevert(children[j]));
79025                   }
79026                 }
79027
79028                 history.replace(actionRevert(_conflicts[i].id));
79029               }
79030             }
79031
79032             uploader.save(changeset, true, false); // tryAgain = true, checkConflicts = false
79033           };
79034
79035           uploader.reset = function () {};
79036
79037           return uploader;
79038         }
79039
79040         var $$2 = _export;
79041         var fails = fails$V;
79042         var expm1 = mathExpm1;
79043
79044         var abs = Math.abs;
79045         var exp = Math.exp;
79046         var E = Math.E;
79047
79048         var FORCED = fails(function () {
79049           // eslint-disable-next-line es/no-math-sinh -- required for testing
79050           return Math.sinh(-2e-17) != -2e-17;
79051         });
79052
79053         // `Math.sinh` method
79054         // https://tc39.es/ecma262/#sec-math.sinh
79055         // V8 near Chromium 38 has a problem with very small numbers
79056         $$2({ target: 'Math', stat: true, forced: FORCED }, {
79057           sinh: function sinh(x) {
79058             return abs(x = +x) < 1 ? (expm1(x) - expm1(-x)) / 2 : (exp(x - 1) - exp(-x - 1)) * (E / 2);
79059           }
79060         });
79061
79062         var isRetina = window.devicePixelRatio && window.devicePixelRatio >= 2; // listen for DPI change, e.g. when dragging a browser window from a retina to non-retina screen
79063
79064         window.matchMedia("\n        (-webkit-min-device-pixel-ratio: 2), /* Safari */\n        (min-resolution: 2dppx),             /* standard */\n        (min-resolution: 192dpi)             /* fallback */\n    ").addListener(function () {
79065           isRetina = window.devicePixelRatio && window.devicePixelRatio >= 2;
79066         });
79067
79068         function localeDateString(s) {
79069           if (!s) return null;
79070           var options = {
79071             day: 'numeric',
79072             month: 'short',
79073             year: 'numeric'
79074           };
79075           var d = new Date(s);
79076           if (isNaN(d.getTime())) return null;
79077           return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
79078         }
79079
79080         function vintageRange(vintage) {
79081           var s;
79082
79083           if (vintage.start || vintage.end) {
79084             s = vintage.start || '?';
79085
79086             if (vintage.start !== vintage.end) {
79087               s += ' - ' + (vintage.end || '?');
79088             }
79089           }
79090
79091           return s;
79092         }
79093
79094         function rendererBackgroundSource(data) {
79095           var source = Object.assign({}, data); // shallow copy
79096
79097           var _offset = [0, 0];
79098           var _name = source.name;
79099           var _description = source.description;
79100
79101           var _best = !!source.best;
79102
79103           var _template = source.encrypted ? utilAesDecrypt(source.template) : source.template;
79104
79105           source.tileSize = data.tileSize || 256;
79106           source.zoomExtent = data.zoomExtent || [0, 22];
79107           source.overzoom = data.overzoom !== false;
79108
79109           source.offset = function (val) {
79110             if (!arguments.length) return _offset;
79111             _offset = val;
79112             return source;
79113           };
79114
79115           source.nudge = function (val, zoomlevel) {
79116             _offset[0] += val[0] / Math.pow(2, zoomlevel);
79117             _offset[1] += val[1] / Math.pow(2, zoomlevel);
79118             return source;
79119           };
79120
79121           source.name = function () {
79122             var id_safe = source.id.replace(/\./g, '<TX_DOT>');
79123             return _t('imagery.' + id_safe + '.name', {
79124               "default": lodash.exports.escape(_name)
79125             });
79126           };
79127
79128           source.label = function () {
79129             var id_safe = source.id.replace(/\./g, '<TX_DOT>');
79130             return _t.html('imagery.' + id_safe + '.name', {
79131               "default": lodash.exports.escape(_name)
79132             });
79133           };
79134
79135           source.description = function () {
79136             var id_safe = source.id.replace(/\./g, '<TX_DOT>');
79137             return _t.html('imagery.' + id_safe + '.description', {
79138               "default": lodash.exports.escape(_description)
79139             });
79140           };
79141
79142           source.best = function () {
79143             return _best;
79144           };
79145
79146           source.area = function () {
79147             if (!data.polygon) return Number.MAX_VALUE; // worldwide
79148
79149             var area = d3_geoArea({
79150               type: 'MultiPolygon',
79151               coordinates: [data.polygon]
79152             });
79153             return isNaN(area) ? 0 : area;
79154           };
79155
79156           source.imageryUsed = function () {
79157             return _name || source.id;
79158           };
79159
79160           source.template = function (val) {
79161             if (!arguments.length) return _template;
79162
79163             if (source.id === 'custom' || source.id === 'Bing') {
79164               _template = val;
79165             }
79166
79167             return source;
79168           };
79169
79170           source.url = function (coord) {
79171             var result = _template;
79172             if (result === '') return result; // source 'none'
79173             // Guess a type based on the tokens present in the template
79174             // (This is for 'custom' source, where we don't know)
79175
79176             if (!source.type || source.id === 'custom') {
79177               if (/SERVICE=WMS|\{(proj|wkid|bbox)\}/.test(_template)) {
79178                 source.type = 'wms';
79179                 source.projection = 'EPSG:3857'; // guess
79180               } else if (/\{(x|y)\}/.test(_template)) {
79181                 source.type = 'tms';
79182               } else if (/\{u\}/.test(_template)) {
79183                 source.type = 'bing';
79184               }
79185             }
79186
79187             if (source.type === 'wms') {
79188               var tileToProjectedCoords = function tileToProjectedCoords(x, y, z) {
79189                 //polyfill for IE11, PhantomJS
79190                 var sinh = Math.sinh || function (x) {
79191                   var y = Math.exp(x);
79192                   return (y - 1 / y) / 2;
79193                 };
79194
79195                 var zoomSize = Math.pow(2, z);
79196                 var lon = x / zoomSize * Math.PI * 2 - Math.PI;
79197                 var lat = Math.atan(sinh(Math.PI * (1 - 2 * y / zoomSize)));
79198
79199                 switch (source.projection) {
79200                   case 'EPSG:4326':
79201                     return {
79202                       x: lon * 180 / Math.PI,
79203                       y: lat * 180 / Math.PI
79204                     };
79205
79206                   default:
79207                     // EPSG:3857 and synonyms
79208                     var mercCoords = mercatorRaw(lon, lat);
79209                     return {
79210                       x: 20037508.34 / Math.PI * mercCoords[0],
79211                       y: 20037508.34 / Math.PI * mercCoords[1]
79212                     };
79213                 }
79214               };
79215
79216               var tileSize = source.tileSize;
79217               var projection = source.projection;
79218               var minXmaxY = tileToProjectedCoords(coord[0], coord[1], coord[2]);
79219               var maxXminY = tileToProjectedCoords(coord[0] + 1, coord[1] + 1, coord[2]);
79220               result = result.replace(/\{(\w+)\}/g, function (token, key) {
79221                 switch (key) {
79222                   case 'width':
79223                   case 'height':
79224                     return tileSize;
79225
79226                   case 'proj':
79227                     return projection;
79228
79229                   case 'wkid':
79230                     return projection.replace(/^EPSG:/, '');
79231
79232                   case 'bbox':
79233                     // WMS 1.3 flips x/y for some coordinate systems including EPSG:4326 - #7557
79234                     if (projection === 'EPSG:4326' && // The CRS parameter implies version 1.3 (prior versions use SRS)
79235                     /VERSION=1.3|CRS={proj}/.test(source.template().toUpperCase())) {
79236                       return maxXminY.y + ',' + minXmaxY.x + ',' + minXmaxY.y + ',' + maxXminY.x;
79237                     } else {
79238                       return minXmaxY.x + ',' + maxXminY.y + ',' + maxXminY.x + ',' + minXmaxY.y;
79239                     }
79240
79241                   case 'w':
79242                     return minXmaxY.x;
79243
79244                   case 's':
79245                     return maxXminY.y;
79246
79247                   case 'n':
79248                     return maxXminY.x;
79249
79250                   case 'e':
79251                     return minXmaxY.y;
79252
79253                   default:
79254                     return token;
79255                 }
79256               });
79257             } else if (source.type === 'tms') {
79258               result = result.replace('{x}', coord[0]).replace('{y}', coord[1]) // TMS-flipped y coordinate
79259               .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1).replace(/\{z(oom)?\}/, coord[2]) // only fetch retina tiles for retina screens
79260               .replace(/\{@2x\}|\{r\}/, isRetina ? '@2x' : '');
79261             } else if (source.type === 'bing') {
79262               result = result.replace('{u}', function () {
79263                 var u = '';
79264
79265                 for (var zoom = coord[2]; zoom > 0; zoom--) {
79266                   var b = 0;
79267                   var mask = 1 << zoom - 1;
79268                   if ((coord[0] & mask) !== 0) b++;
79269                   if ((coord[1] & mask) !== 0) b += 2;
79270                   u += b.toString();
79271                 }
79272
79273                 return u;
79274               });
79275             } // these apply to any type..
79276
79277
79278             result = result.replace(/\{switch:([^}]+)\}/, function (s, r) {
79279               var subdomains = r.split(',');
79280               return subdomains[(coord[0] + coord[1]) % subdomains.length];
79281             });
79282             return result;
79283           };
79284
79285           source.validZoom = function (z) {
79286             return source.zoomExtent[0] <= z && (source.overzoom || source.zoomExtent[1] > z);
79287           };
79288
79289           source.isLocatorOverlay = function () {
79290             return source.id === 'mapbox_locator_overlay';
79291           };
79292           /* hides a source from the list, but leaves it available for use */
79293
79294
79295           source.isHidden = function () {
79296             return source.id === 'DigitalGlobe-Premium-vintage' || source.id === 'DigitalGlobe-Standard-vintage';
79297           };
79298
79299           source.copyrightNotices = function () {};
79300
79301           source.getMetadata = function (center, tileCoord, callback) {
79302             var vintage = {
79303               start: localeDateString(source.startDate),
79304               end: localeDateString(source.endDate)
79305             };
79306             vintage.range = vintageRange(vintage);
79307             var metadata = {
79308               vintage: vintage
79309             };
79310             callback(null, metadata);
79311           };
79312
79313           return source;
79314         }
79315
79316         rendererBackgroundSource.Bing = function (data, dispatch) {
79317           // https://docs.microsoft.com/en-us/bingmaps/rest-services/imagery/get-imagery-metadata
79318           // https://docs.microsoft.com/en-us/bingmaps/rest-services/directly-accessing-the-bing-maps-tiles
79319           //fallback url template
79320           data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&n=z';
79321           var bing = rendererBackgroundSource(data); //var key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU'; // P2, JOSM, etc
79322
79323           var key = 'Ak5oTE46TUbjRp08OFVcGpkARErDobfpuyNKa-W2mQ8wbt1K1KL8p1bIRwWwcF-Q'; // iD
79324
79325           /*
79326           missing tile image strictness param (n=)
79327           •   n=f -> (Fail) returns a 404
79328           •   n=z -> (Empty) returns a 200 with 0 bytes (no content)
79329           •   n=t -> (Transparent) returns a 200 with a transparent (png) tile
79330           */
79331
79332           var strictParam = 'n';
79333           var url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&uriScheme=https&key=' + key;
79334           var cache = {};
79335           var inflight = {};
79336           var providers = [];
79337           d3_json(url).then(function (json) {
79338             var imageryResource = json.resourceSets[0].resources[0]; //retrieve and prepare up to date imagery template
79339
79340             var template = imageryResource.imageUrl; //https://ecn.{subdomain}.tiles.virtualearth.net/tiles/a{quadkey}.jpeg?g=10339
79341
79342             var subDomains = imageryResource.imageUrlSubdomains; //["t0, t1, t2, t3"]
79343
79344             var subDomainNumbers = subDomains.map(function (subDomain) {
79345               return subDomain.substring(1);
79346             }).join(',');
79347             template = template.replace('{subdomain}', "t{switch:".concat(subDomainNumbers, "}")).replace('{quadkey}', '{u}');
79348
79349             if (!new URLSearchParams(template).has(strictParam)) {
79350               template += "&".concat(strictParam, "=z");
79351             }
79352
79353             bing.template(template);
79354             providers = imageryResource.imageryProviders.map(function (provider) {
79355               return {
79356                 attribution: provider.attribution,
79357                 areas: provider.coverageAreas.map(function (area) {
79358                   return {
79359                     zoom: [area.zoomMin, area.zoomMax],
79360                     extent: geoExtent([area.bbox[1], area.bbox[0]], [area.bbox[3], area.bbox[2]])
79361                   };
79362                 })
79363               };
79364             });
79365             dispatch.call('change');
79366           })["catch"](function () {
79367             /* ignore */
79368           });
79369
79370           bing.copyrightNotices = function (zoom, extent) {
79371             zoom = Math.min(zoom, 21);
79372             return providers.filter(function (provider) {
79373               return provider.areas.some(function (area) {
79374                 return extent.intersects(area.extent) && area.zoom[0] <= zoom && area.zoom[1] >= zoom;
79375               });
79376             }).map(function (provider) {
79377               return provider.attribution;
79378             }).join(', ');
79379           };
79380
79381           bing.getMetadata = function (center, tileCoord, callback) {
79382             var tileID = tileCoord.slice(0, 3).join('/');
79383             var zoom = Math.min(tileCoord[2], 21);
79384             var centerPoint = center[1] + ',' + center[0]; // lat,lng
79385
79386             var url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/' + centerPoint + '?zl=' + zoom + '&key=' + key;
79387             if (inflight[tileID]) return;
79388
79389             if (!cache[tileID]) {
79390               cache[tileID] = {};
79391             }
79392
79393             if (cache[tileID] && cache[tileID].metadata) {
79394               return callback(null, cache[tileID].metadata);
79395             }
79396
79397             inflight[tileID] = true;
79398             d3_json(url).then(function (result) {
79399               delete inflight[tileID];
79400
79401               if (!result) {
79402                 throw new Error('Unknown Error');
79403               }
79404
79405               var vintage = {
79406                 start: localeDateString(result.resourceSets[0].resources[0].vintageStart),
79407                 end: localeDateString(result.resourceSets[0].resources[0].vintageEnd)
79408               };
79409               vintage.range = vintageRange(vintage);
79410               var metadata = {
79411                 vintage: vintage
79412               };
79413               cache[tileID].metadata = metadata;
79414               if (callback) callback(null, metadata);
79415             })["catch"](function (err) {
79416               delete inflight[tileID];
79417               if (callback) callback(err.message);
79418             });
79419           };
79420
79421           bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
79422           return bing;
79423         };
79424
79425         rendererBackgroundSource.Esri = function (data) {
79426           // in addition to using the tilemap at zoom level 20, overzoom real tiles - #4327 (deprecated technique, but it works)
79427           if (data.template.match(/blankTile/) === null) {
79428             data.template = data.template + '?blankTile=false';
79429           }
79430
79431           var esri = rendererBackgroundSource(data);
79432           var cache = {};
79433           var inflight = {};
79434
79435           var _prevCenter; // use a tilemap service to set maximum zoom for esri tiles dynamically
79436           // https://developers.arcgis.com/documentation/tiled-elevation-service/
79437
79438
79439           esri.fetchTilemap = function (center) {
79440             // skip if we have already fetched a tilemap within 5km
79441             if (_prevCenter && geoSphericalDistance(center, _prevCenter) < 5000) return;
79442             _prevCenter = center; // tiles are available globally to zoom level 19, afterward they may or may not be present
79443
79444             var z = 20; // first generate a random url using the template
79445
79446             var dummyUrl = esri.url([1, 2, 3]); // calculate url z/y/x from the lat/long of the center of the map
79447
79448             var x = Math.floor((center[0] + 180) / 360 * Math.pow(2, z));
79449             var y = Math.floor((1 - Math.log(Math.tan(center[1] * Math.PI / 180) + 1 / Math.cos(center[1] * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, z)); // fetch an 8x8 grid to leverage cache
79450
79451             var tilemapUrl = dummyUrl.replace(/tile\/[0-9]+\/[0-9]+\/[0-9]+\?blankTile=false/, 'tilemap') + '/' + z + '/' + y + '/' + x + '/8/8'; // make the request and introspect the response from the tilemap server
79452
79453             d3_json(tilemapUrl).then(function (tilemap) {
79454               if (!tilemap) {
79455                 throw new Error('Unknown Error');
79456               }
79457
79458               var hasTiles = true;
79459
79460               for (var i = 0; i < tilemap.data.length; i++) {
79461                 // 0 means an individual tile in the grid doesn't exist
79462                 if (!tilemap.data[i]) {
79463                   hasTiles = false;
79464                   break;
79465                 }
79466               } // if any tiles are missing at level 20 we restrict maxZoom to 19
79467
79468
79469               esri.zoomExtent[1] = hasTiles ? 22 : 19;
79470             })["catch"](function () {
79471               /* ignore */
79472             });
79473           };
79474
79475           esri.getMetadata = function (center, tileCoord, callback) {
79476             if (esri.id !== 'EsriWorldImagery') {
79477               // rest endpoint is not available for ESRI's "clarity" imagery
79478               return callback(null, {});
79479             }
79480
79481             var tileID = tileCoord.slice(0, 3).join('/');
79482             var zoom = Math.min(tileCoord[2], esri.zoomExtent[1]);
79483             var centerPoint = center[0] + ',' + center[1]; // long, lat (as it should be)
79484
79485             var unknown = _t('info_panels.background.unknown');
79486             var vintage = {};
79487             var metadata = {};
79488             if (inflight[tileID]) return; // build up query using the layer appropriate to the current zoom
79489
79490             var url = 'https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/4/query';
79491             url += '?returnGeometry=false&geometry=' + centerPoint + '&inSR=4326&geometryType=esriGeometryPoint&outFields=*&f=json';
79492
79493             if (!cache[tileID]) {
79494               cache[tileID] = {};
79495             }
79496
79497             if (cache[tileID] && cache[tileID].metadata) {
79498               return callback(null, cache[tileID].metadata);
79499             }
79500
79501             inflight[tileID] = true;
79502             d3_json(url).then(function (result) {
79503               delete inflight[tileID];
79504               result = result.features.map(function (f) {
79505                 return f.attributes;
79506               }).filter(function (a) {
79507                 return a.MinMapLevel <= zoom && a.MaxMapLevel >= zoom;
79508               })[0];
79509
79510               if (!result) {
79511                 throw new Error('Unknown Error');
79512               } else if (result.features && result.features.length < 1) {
79513                 throw new Error('No Results');
79514               } else if (result.error && result.error.message) {
79515                 throw new Error(result.error.message);
79516               } // pass through the discrete capture date from metadata
79517
79518
79519               var captureDate = localeDateString(result.SRC_DATE2);
79520               vintage = {
79521                 start: captureDate,
79522                 end: captureDate,
79523                 range: captureDate
79524               };
79525               metadata = {
79526                 vintage: vintage,
79527                 source: clean(result.NICE_NAME),
79528                 description: clean(result.NICE_DESC),
79529                 resolution: clean(+parseFloat(result.SRC_RES).toFixed(4)),
79530                 accuracy: clean(+parseFloat(result.SRC_ACC).toFixed(4))
79531               }; // append units - meters
79532
79533               if (isFinite(metadata.resolution)) {
79534                 metadata.resolution += ' m';
79535               }
79536
79537               if (isFinite(metadata.accuracy)) {
79538                 metadata.accuracy += ' m';
79539               }
79540
79541               cache[tileID].metadata = metadata;
79542               if (callback) callback(null, metadata);
79543             })["catch"](function (err) {
79544               delete inflight[tileID];
79545               if (callback) callback(err.message);
79546             });
79547
79548             function clean(val) {
79549               return String(val).trim() || unknown;
79550             }
79551           };
79552
79553           return esri;
79554         };
79555
79556         rendererBackgroundSource.None = function () {
79557           var source = rendererBackgroundSource({
79558             id: 'none',
79559             template: ''
79560           });
79561
79562           source.name = function () {
79563             return _t('background.none');
79564           };
79565
79566           source.label = function () {
79567             return _t.html('background.none');
79568           };
79569
79570           source.imageryUsed = function () {
79571             return null;
79572           };
79573
79574           source.area = function () {
79575             return -1; // sources in background pane are sorted by area
79576           };
79577
79578           return source;
79579         };
79580
79581         rendererBackgroundSource.Custom = function (template) {
79582           var source = rendererBackgroundSource({
79583             id: 'custom',
79584             template: template
79585           });
79586
79587           source.name = function () {
79588             return _t('background.custom');
79589           };
79590
79591           source.label = function () {
79592             return _t.html('background.custom');
79593           };
79594
79595           source.imageryUsed = function () {
79596             // sanitize personal connection tokens - #6801
79597             var cleaned = source.template(); // from query string parameters
79598
79599             if (cleaned.indexOf('?') !== -1) {
79600               var parts = cleaned.split('?', 2);
79601               var qs = utilStringQs(parts[1]);
79602               ['access_token', 'connectId', 'token'].forEach(function (param) {
79603                 if (qs[param]) {
79604                   qs[param] = '{apikey}';
79605                 }
79606               });
79607               cleaned = parts[0] + '?' + utilQsString(qs, true); // true = soft encode
79608             } // from wms/wmts api path parameters
79609
79610
79611             cleaned = cleaned.replace(/token\/(\w+)/, 'token/{apikey}');
79612             return 'Custom (' + cleaned + ' )';
79613           };
79614
79615           source.area = function () {
79616             return -2; // sources in background pane are sorted by area
79617           };
79618
79619           return source;
79620         };
79621
79622         function rendererTileLayer(context) {
79623           var transformProp = utilPrefixCSSProperty('Transform');
79624           var tiler = utilTiler();
79625           var _tileSize = 256;
79626
79627           var _projection;
79628
79629           var _cache = {};
79630
79631           var _tileOrigin;
79632
79633           var _zoom;
79634
79635           var _source;
79636
79637           function tileSizeAtZoom(d, z) {
79638             var EPSILON = 0.002; // close seams
79639
79640             return _tileSize * Math.pow(2, z - d[2]) / _tileSize + EPSILON;
79641           }
79642
79643           function atZoom(t, distance) {
79644             var power = Math.pow(2, distance);
79645             return [Math.floor(t[0] * power), Math.floor(t[1] * power), t[2] + distance];
79646           }
79647
79648           function lookUp(d) {
79649             for (var up = -1; up > -d[2]; up--) {
79650               var tile = atZoom(d, up);
79651
79652               if (_cache[_source.url(tile)] !== false) {
79653                 return tile;
79654               }
79655             }
79656           }
79657
79658           function uniqueBy(a, n) {
79659             var o = [];
79660             var seen = {};
79661
79662             for (var i = 0; i < a.length; i++) {
79663               if (seen[a[i][n]] === undefined) {
79664                 o.push(a[i]);
79665                 seen[a[i][n]] = true;
79666               }
79667             }
79668
79669             return o;
79670           }
79671
79672           function addSource(d) {
79673             d.push(_source.url(d));
79674             return d;
79675           } // Update tiles based on current state of `projection`.
79676
79677
79678           function background(selection) {
79679             _zoom = geoScaleToZoom(_projection.scale(), _tileSize);
79680             var pixelOffset;
79681
79682             if (_source) {
79683               pixelOffset = [_source.offset()[0] * Math.pow(2, _zoom), _source.offset()[1] * Math.pow(2, _zoom)];
79684             } else {
79685               pixelOffset = [0, 0];
79686             }
79687
79688             var translate = [_projection.translate()[0] + pixelOffset[0], _projection.translate()[1] + pixelOffset[1]];
79689             tiler.scale(_projection.scale() * 2 * Math.PI).translate(translate);
79690             _tileOrigin = [_projection.scale() * Math.PI - translate[0], _projection.scale() * Math.PI - translate[1]];
79691             render(selection);
79692           } // Derive the tiles onscreen, remove those offscreen and position them.
79693           // Important that this part not depend on `_projection` because it's
79694           // rentered when tiles load/error (see #644).
79695
79696
79697           function render(selection) {
79698             if (!_source) return;
79699             var requests = [];
79700             var showDebug = context.getDebug('tile') && !_source.overlay;
79701
79702             if (_source.validZoom(_zoom)) {
79703               tiler.skipNullIsland(!!_source.overlay);
79704               tiler().forEach(function (d) {
79705                 addSource(d);
79706                 if (d[3] === '') return;
79707                 if (typeof d[3] !== 'string') return; // Workaround for #2295
79708
79709                 requests.push(d);
79710
79711                 if (_cache[d[3]] === false && lookUp(d)) {
79712                   requests.push(addSource(lookUp(d)));
79713                 }
79714               });
79715               requests = uniqueBy(requests, 3).filter(function (r) {
79716                 // don't re-request tiles which have failed in the past
79717                 return _cache[r[3]] !== false;
79718               });
79719             }
79720
79721             function load(d3_event, d) {
79722               _cache[d[3]] = true;
79723               select(this).on('error', null).on('load', null).classed('tile-loaded', true);
79724               render(selection);
79725             }
79726
79727             function error(d3_event, d) {
79728               _cache[d[3]] = false;
79729               select(this).on('error', null).on('load', null).remove();
79730               render(selection);
79731             }
79732
79733             function imageTransform(d) {
79734               var ts = _tileSize * Math.pow(2, _zoom - d[2]);
79735
79736               var scale = tileSizeAtZoom(d, _zoom);
79737               return 'translate(' + (d[0] * ts - _tileOrigin[0]) + 'px,' + (d[1] * ts - _tileOrigin[1]) + 'px) ' + 'scale(' + scale + ',' + scale + ')';
79738             }
79739
79740             function tileCenter(d) {
79741               var ts = _tileSize * Math.pow(2, _zoom - d[2]);
79742
79743               return [d[0] * ts - _tileOrigin[0] + ts / 2, d[1] * ts - _tileOrigin[1] + ts / 2];
79744             }
79745
79746             function debugTransform(d) {
79747               var coord = tileCenter(d);
79748               return 'translate(' + coord[0] + 'px,' + coord[1] + 'px)';
79749             } // Pick a representative tile near the center of the viewport
79750             // (This is useful for sampling the imagery vintage)
79751
79752
79753             var dims = tiler.size();
79754             var mapCenter = [dims[0] / 2, dims[1] / 2];
79755             var minDist = Math.max(dims[0], dims[1]);
79756             var nearCenter;
79757             requests.forEach(function (d) {
79758               var c = tileCenter(d);
79759               var dist = geoVecLength(c, mapCenter);
79760
79761               if (dist < minDist) {
79762                 minDist = dist;
79763                 nearCenter = d;
79764               }
79765             });
79766             var image = selection.selectAll('img').data(requests, function (d) {
79767               return d[3];
79768             });
79769             image.exit().style(transformProp, imageTransform).classed('tile-removing', true).classed('tile-center', false).each(function () {
79770               var tile = select(this);
79771               window.setTimeout(function () {
79772                 if (tile.classed('tile-removing')) {
79773                   tile.remove();
79774                 }
79775               }, 300);
79776             });
79777             image.enter().append('img').attr('class', 'tile').attr('alt', '').attr('draggable', 'false').style('width', _tileSize + 'px').style('height', _tileSize + 'px').attr('src', function (d) {
79778               return d[3];
79779             }).on('error', error).on('load', load).merge(image).style(transformProp, imageTransform).classed('tile-debug', showDebug).classed('tile-removing', false).classed('tile-center', function (d) {
79780               return d === nearCenter;
79781             });
79782             var debug = selection.selectAll('.tile-label-debug').data(showDebug ? requests : [], function (d) {
79783               return d[3];
79784             });
79785             debug.exit().remove();
79786
79787             if (showDebug) {
79788               var debugEnter = debug.enter().append('div').attr('class', 'tile-label-debug');
79789               debugEnter.append('div').attr('class', 'tile-label-debug-coord');
79790               debugEnter.append('div').attr('class', 'tile-label-debug-vintage');
79791               debug = debug.merge(debugEnter);
79792               debug.style(transformProp, debugTransform);
79793               debug.selectAll('.tile-label-debug-coord').text(function (d) {
79794                 return d[2] + ' / ' + d[0] + ' / ' + d[1];
79795               });
79796               debug.selectAll('.tile-label-debug-vintage').each(function (d) {
79797                 var span = select(this);
79798                 var center = context.projection.invert(tileCenter(d));
79799
79800                 _source.getMetadata(center, d, function (err, result) {
79801                   if (result && result.vintage && result.vintage.range) {
79802                     span.text(result.vintage.range);
79803                   } else {
79804                     span.html(_t.html('info_panels.background.vintage') + ': ' + _t.html('info_panels.background.unknown'));
79805                   }
79806                 });
79807               });
79808             }
79809           }
79810
79811           background.projection = function (val) {
79812             if (!arguments.length) return _projection;
79813             _projection = val;
79814             return background;
79815           };
79816
79817           background.dimensions = function (val) {
79818             if (!arguments.length) return tiler.size();
79819             tiler.size(val);
79820             return background;
79821           };
79822
79823           background.source = function (val) {
79824             if (!arguments.length) return _source;
79825             _source = val;
79826             _tileSize = _source.tileSize;
79827             _cache = {};
79828             tiler.tileSize(_source.tileSize).zoomExtent(_source.zoomExtent);
79829             return background;
79830           };
79831
79832           return background;
79833         }
79834
79835         var _imageryIndex = null;
79836         function rendererBackground(context) {
79837           var dispatch = dispatch$8('change');
79838           var detected = utilDetect();
79839           var baseLayer = rendererTileLayer(context).projection(context.projection);
79840           var _checkedBlocklists = [];
79841           var _isValid = true;
79842           var _overlayLayers = [];
79843           var _brightness = 1;
79844           var _contrast = 1;
79845           var _saturation = 1;
79846           var _sharpness = 1;
79847
79848           function ensureImageryIndex() {
79849             return _mainFileFetcher.get('imagery').then(function (sources) {
79850               if (_imageryIndex) return _imageryIndex;
79851               _imageryIndex = {
79852                 imagery: sources,
79853                 features: {}
79854               }; // use which-polygon to support efficient index and querying for imagery
79855
79856               var features = sources.map(function (source) {
79857                 if (!source.polygon) return null; // workaround for editor-layer-index weirdness..
79858                 // Add an extra array nest to each element in `source.polygon`
79859                 // so the rings are not treated as a bunch of holes:
79860                 // what we have: [ [[outer],[hole],[hole]] ]
79861                 // what we want: [ [[outer]],[[outer]],[[outer]] ]
79862
79863                 var rings = source.polygon.map(function (ring) {
79864                   return [ring];
79865                 });
79866                 var feature = {
79867                   type: 'Feature',
79868                   properties: {
79869                     id: source.id
79870                   },
79871                   geometry: {
79872                     type: 'MultiPolygon',
79873                     coordinates: rings
79874                   }
79875                 };
79876                 _imageryIndex.features[source.id] = feature;
79877                 return feature;
79878               }).filter(Boolean);
79879               _imageryIndex.query = whichPolygon_1({
79880                 type: 'FeatureCollection',
79881                 features: features
79882               }); // Instantiate `rendererBackgroundSource` objects for each source
79883
79884               _imageryIndex.backgrounds = sources.map(function (source) {
79885                 if (source.type === 'bing') {
79886                   return rendererBackgroundSource.Bing(source, dispatch);
79887                 } else if (/^EsriWorldImagery/.test(source.id)) {
79888                   return rendererBackgroundSource.Esri(source);
79889                 } else {
79890                   return rendererBackgroundSource(source);
79891                 }
79892               }); // Add 'None'
79893
79894               _imageryIndex.backgrounds.unshift(rendererBackgroundSource.None()); // Add 'Custom'
79895
79896
79897               var template = corePreferences('background-custom-template') || '';
79898               var custom = rendererBackgroundSource.Custom(template);
79899
79900               _imageryIndex.backgrounds.unshift(custom);
79901
79902               return _imageryIndex;
79903             });
79904           }
79905
79906           function background(selection) {
79907             var currSource = baseLayer.source(); // If we are displaying an Esri basemap at high zoom,
79908             // check its tilemap to see how high the zoom can go
79909
79910             if (context.map().zoom() > 18) {
79911               if (currSource && /^EsriWorldImagery/.test(currSource.id)) {
79912                 var center = context.map().center();
79913                 currSource.fetchTilemap(center);
79914               }
79915             } // Is the imagery valid here? - #4827
79916
79917
79918             var sources = background.sources(context.map().extent());
79919             var wasValid = _isValid;
79920             _isValid = !!sources.filter(function (d) {
79921               return d === currSource;
79922             }).length;
79923
79924             if (wasValid !== _isValid) {
79925               // change in valid status
79926               background.updateImagery();
79927             }
79928
79929             var baseFilter = '';
79930
79931             if (detected.cssfilters) {
79932               if (_brightness !== 1) {
79933                 baseFilter += " brightness(".concat(_brightness, ")");
79934               }
79935
79936               if (_contrast !== 1) {
79937                 baseFilter += " contrast(".concat(_contrast, ")");
79938               }
79939
79940               if (_saturation !== 1) {
79941                 baseFilter += " saturate(".concat(_saturation, ")");
79942               }
79943
79944               if (_sharpness < 1) {
79945                 // gaussian blur
79946                 var blur = d3_interpolateNumber(0.5, 5)(1 - _sharpness);
79947                 baseFilter += " blur(".concat(blur, "px)");
79948               }
79949             }
79950
79951             var base = selection.selectAll('.layer-background').data([0]);
79952             base = base.enter().insert('div', '.layer-data').attr('class', 'layer layer-background').merge(base);
79953
79954             if (detected.cssfilters) {
79955               base.style('filter', baseFilter || null);
79956             } else {
79957               base.style('opacity', _brightness);
79958             }
79959
79960             var imagery = base.selectAll('.layer-imagery').data([0]);
79961             imagery.enter().append('div').attr('class', 'layer layer-imagery').merge(imagery).call(baseLayer);
79962             var maskFilter = '';
79963             var mixBlendMode = '';
79964
79965             if (detected.cssfilters && _sharpness > 1) {
79966               // apply unsharp mask
79967               mixBlendMode = 'overlay';
79968               maskFilter = 'saturate(0) blur(3px) invert(1)';
79969               var contrast = _sharpness - 1;
79970               maskFilter += " contrast(".concat(contrast, ")");
79971               var brightness = d3_interpolateNumber(1, 0.85)(_sharpness - 1);
79972               maskFilter += " brightness(".concat(brightness, ")");
79973             }
79974
79975             var mask = base.selectAll('.layer-unsharp-mask').data(detected.cssfilters && _sharpness > 1 ? [0] : []);
79976             mask.exit().remove();
79977             mask.enter().append('div').attr('class', 'layer layer-mask layer-unsharp-mask').merge(mask).call(baseLayer).style('filter', maskFilter || null).style('mix-blend-mode', mixBlendMode || null);
79978             var overlays = selection.selectAll('.layer-overlay').data(_overlayLayers, function (d) {
79979               return d.source().name();
79980             });
79981             overlays.exit().remove();
79982             overlays.enter().insert('div', '.layer-data').attr('class', 'layer layer-overlay').merge(overlays).each(function (layer, i, nodes) {
79983               return select(nodes[i]).call(layer);
79984             });
79985           }
79986
79987           background.updateImagery = function () {
79988             var currSource = baseLayer.source();
79989             if (context.inIntro() || !currSource) return;
79990
79991             var o = _overlayLayers.filter(function (d) {
79992               return !d.source().isLocatorOverlay() && !d.source().isHidden();
79993             }).map(function (d) {
79994               return d.source().id;
79995             }).join(',');
79996
79997             var meters = geoOffsetToMeters(currSource.offset());
79998             var EPSILON = 0.01;
79999             var x = +meters[0].toFixed(2);
80000             var y = +meters[1].toFixed(2);
80001             var hash = utilStringQs(window.location.hash);
80002             var id = currSource.id;
80003
80004             if (id === 'custom') {
80005               id = "custom:".concat(currSource.template());
80006             }
80007
80008             if (id) {
80009               hash.background = id;
80010             } else {
80011               delete hash.background;
80012             }
80013
80014             if (o) {
80015               hash.overlays = o;
80016             } else {
80017               delete hash.overlays;
80018             }
80019
80020             if (Math.abs(x) > EPSILON || Math.abs(y) > EPSILON) {
80021               hash.offset = "".concat(x, ",").concat(y);
80022             } else {
80023               delete hash.offset;
80024             }
80025
80026             if (!window.mocha) {
80027               window.location.replace('#' + utilQsString(hash, true));
80028             }
80029
80030             var imageryUsed = [];
80031             var photoOverlaysUsed = [];
80032             var currUsed = currSource.imageryUsed();
80033
80034             if (currUsed && _isValid) {
80035               imageryUsed.push(currUsed);
80036             }
80037
80038             _overlayLayers.filter(function (d) {
80039               return !d.source().isLocatorOverlay() && !d.source().isHidden();
80040             }).forEach(function (d) {
80041               return imageryUsed.push(d.source().imageryUsed());
80042             });
80043
80044             var dataLayer = context.layers().layer('data');
80045
80046             if (dataLayer && dataLayer.enabled() && dataLayer.hasData()) {
80047               imageryUsed.push(dataLayer.getSrc());
80048             }
80049
80050             var photoOverlayLayers = {
80051               streetside: 'Bing Streetside',
80052               mapillary: 'Mapillary Images',
80053               'mapillary-map-features': 'Mapillary Map Features',
80054               'mapillary-signs': 'Mapillary Signs',
80055               kartaview: 'KartaView Images'
80056             };
80057
80058             for (var layerID in photoOverlayLayers) {
80059               var layer = context.layers().layer(layerID);
80060
80061               if (layer && layer.enabled()) {
80062                 photoOverlaysUsed.push(layerID);
80063                 imageryUsed.push(photoOverlayLayers[layerID]);
80064               }
80065             }
80066
80067             context.history().imageryUsed(imageryUsed);
80068             context.history().photoOverlaysUsed(photoOverlaysUsed);
80069           };
80070
80071           background.sources = function (extent, zoom, includeCurrent) {
80072             if (!_imageryIndex) return []; // called before init()?
80073
80074             var visible = {};
80075             (_imageryIndex.query.bbox(extent.rectangle(), true) || []).forEach(function (d) {
80076               return visible[d.id] = true;
80077             });
80078             var currSource = baseLayer.source(); // Recheck blocked sources only if we detect new blocklists pulled from the OSM API.
80079
80080             var osm = context.connection();
80081             var blocklists = osm && osm.imageryBlocklists() || [];
80082             var blocklistChanged = blocklists.length !== _checkedBlocklists.length || blocklists.some(function (regex, index) {
80083               return String(regex) !== _checkedBlocklists[index];
80084             });
80085
80086             if (blocklistChanged) {
80087               _imageryIndex.backgrounds.forEach(function (source) {
80088                 source.isBlocked = blocklists.some(function (regex) {
80089                   return regex.test(source.template());
80090                 });
80091               });
80092
80093               _checkedBlocklists = blocklists.map(function (regex) {
80094                 return String(regex);
80095               });
80096             }
80097
80098             return _imageryIndex.backgrounds.filter(function (source) {
80099               if (includeCurrent && currSource === source) return true; // optionally always include the current imagery
80100
80101               if (source.isBlocked) return false; // even bundled sources may be blocked - #7905
80102
80103               if (!source.polygon) return true; // always include imagery with worldwide coverage
80104
80105               if (zoom && zoom < 6) return false; // optionally exclude local imagery at low zooms
80106
80107               return visible[source.id]; // include imagery visible in given extent
80108             });
80109           };
80110
80111           background.dimensions = function (val) {
80112             if (!val) return;
80113             baseLayer.dimensions(val);
80114
80115             _overlayLayers.forEach(function (layer) {
80116               return layer.dimensions(val);
80117             });
80118           };
80119
80120           background.baseLayerSource = function (d) {
80121             if (!arguments.length) return baseLayer.source(); // test source against OSM imagery blocklists..
80122
80123             var osm = context.connection();
80124             if (!osm) return background;
80125             var blocklists = osm.imageryBlocklists();
80126             var template = d.template();
80127             var fail = false;
80128             var tested = 0;
80129             var regex;
80130
80131             for (var i = 0; i < blocklists.length; i++) {
80132               regex = blocklists[i];
80133               fail = regex.test(template);
80134               tested++;
80135               if (fail) break;
80136             } // ensure at least one test was run.
80137
80138
80139             if (!tested) {
80140               regex = /.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/;
80141               fail = regex.test(template);
80142             }
80143
80144             baseLayer.source(!fail ? d : background.findSource('none'));
80145             dispatch.call('change');
80146             background.updateImagery();
80147             return background;
80148           };
80149
80150           background.findSource = function (id) {
80151             if (!id || !_imageryIndex) return null; // called before init()?
80152
80153             return _imageryIndex.backgrounds.find(function (d) {
80154               return d.id && d.id === id;
80155             });
80156           };
80157
80158           background.bing = function () {
80159             background.baseLayerSource(background.findSource('Bing'));
80160           };
80161
80162           background.showsLayer = function (d) {
80163             var currSource = baseLayer.source();
80164             if (!d || !currSource) return false;
80165             return d.id === currSource.id || _overlayLayers.some(function (layer) {
80166               return d.id === layer.source().id;
80167             });
80168           };
80169
80170           background.overlayLayerSources = function () {
80171             return _overlayLayers.map(function (layer) {
80172               return layer.source();
80173             });
80174           };
80175
80176           background.toggleOverlayLayer = function (d) {
80177             var layer;
80178
80179             for (var i = 0; i < _overlayLayers.length; i++) {
80180               layer = _overlayLayers[i];
80181
80182               if (layer.source() === d) {
80183                 _overlayLayers.splice(i, 1);
80184
80185                 dispatch.call('change');
80186                 background.updateImagery();
80187                 return;
80188               }
80189             }
80190
80191             layer = rendererTileLayer(context).source(d).projection(context.projection).dimensions(baseLayer.dimensions());
80192
80193             _overlayLayers.push(layer);
80194
80195             dispatch.call('change');
80196             background.updateImagery();
80197           };
80198
80199           background.nudge = function (d, zoom) {
80200             var currSource = baseLayer.source();
80201
80202             if (currSource) {
80203               currSource.nudge(d, zoom);
80204               dispatch.call('change');
80205               background.updateImagery();
80206             }
80207
80208             return background;
80209           };
80210
80211           background.offset = function (d) {
80212             var currSource = baseLayer.source();
80213
80214             if (!arguments.length) {
80215               return currSource && currSource.offset() || [0, 0];
80216             }
80217
80218             if (currSource) {
80219               currSource.offset(d);
80220               dispatch.call('change');
80221               background.updateImagery();
80222             }
80223
80224             return background;
80225           };
80226
80227           background.brightness = function (d) {
80228             if (!arguments.length) return _brightness;
80229             _brightness = d;
80230             if (context.mode()) dispatch.call('change');
80231             return background;
80232           };
80233
80234           background.contrast = function (d) {
80235             if (!arguments.length) return _contrast;
80236             _contrast = d;
80237             if (context.mode()) dispatch.call('change');
80238             return background;
80239           };
80240
80241           background.saturation = function (d) {
80242             if (!arguments.length) return _saturation;
80243             _saturation = d;
80244             if (context.mode()) dispatch.call('change');
80245             return background;
80246           };
80247
80248           background.sharpness = function (d) {
80249             if (!arguments.length) return _sharpness;
80250             _sharpness = d;
80251             if (context.mode()) dispatch.call('change');
80252             return background;
80253           };
80254
80255           var _loadPromise;
80256
80257           background.ensureLoaded = function () {
80258             if (_loadPromise) return _loadPromise;
80259
80260             function parseMapParams(qmap) {
80261               if (!qmap) return false;
80262               var params = qmap.split('/').map(Number);
80263               if (params.length < 3 || params.some(isNaN)) return false;
80264               return geoExtent([params[2], params[1]]); // lon,lat
80265             }
80266
80267             var hash = utilStringQs(window.location.hash);
80268             var requested = hash.background || hash.layer;
80269             var extent = parseMapParams(hash.map);
80270             return _loadPromise = ensureImageryIndex().then(function (imageryIndex) {
80271               var first = imageryIndex.backgrounds.length && imageryIndex.backgrounds[0];
80272               var best;
80273
80274               if (!requested && extent) {
80275                 best = background.sources(extent).find(function (s) {
80276                   return s.best();
80277                 });
80278               } // Decide which background layer to display
80279
80280
80281               if (requested && requested.indexOf('custom:') === 0) {
80282                 var template = requested.replace(/^custom:/, '');
80283                 var custom = background.findSource('custom');
80284                 background.baseLayerSource(custom.template(template));
80285                 corePreferences('background-custom-template', template);
80286               } else {
80287                 background.baseLayerSource(background.findSource(requested) || best || background.findSource(corePreferences('background-last-used')) || background.findSource('Bing') || first || background.findSource('none'));
80288               }
80289
80290               var locator = imageryIndex.backgrounds.find(function (d) {
80291                 return d.overlay && d["default"];
80292               });
80293
80294               if (locator) {
80295                 background.toggleOverlayLayer(locator);
80296               }
80297
80298               var overlays = (hash.overlays || '').split(',');
80299               overlays.forEach(function (overlay) {
80300                 overlay = background.findSource(overlay);
80301
80302                 if (overlay) {
80303                   background.toggleOverlayLayer(overlay);
80304                 }
80305               });
80306
80307               if (hash.gpx) {
80308                 var gpx = context.layers().layer('data');
80309
80310                 if (gpx) {
80311                   gpx.url(hash.gpx, '.gpx');
80312                 }
80313               }
80314
80315               if (hash.offset) {
80316                 var offset = hash.offset.replace(/;/g, ',').split(',').map(function (n) {
80317                   return !isNaN(n) && n;
80318                 });
80319
80320                 if (offset.length === 2) {
80321                   background.offset(geoMetersToOffset(offset));
80322                 }
80323               }
80324             })["catch"](function () {
80325               /* ignore */
80326             });
80327           };
80328
80329           return utilRebind(background, dispatch, 'on');
80330         }
80331
80332         function rendererFeatures(context) {
80333           var dispatch = dispatch$8('change', 'redraw');
80334           var features = utilRebind({}, dispatch, 'on');
80335
80336           var _deferred = new Set();
80337
80338           var traffic_roads = {
80339             'motorway': true,
80340             'motorway_link': true,
80341             'trunk': true,
80342             'trunk_link': true,
80343             'primary': true,
80344             'primary_link': true,
80345             'secondary': true,
80346             'secondary_link': true,
80347             'tertiary': true,
80348             'tertiary_link': true,
80349             'residential': true,
80350             'unclassified': true,
80351             'living_street': true
80352           };
80353           var service_roads = {
80354             'service': true,
80355             'road': true,
80356             'track': true
80357           };
80358           var paths = {
80359             'path': true,
80360             'footway': true,
80361             'cycleway': true,
80362             'bridleway': true,
80363             'steps': true,
80364             'pedestrian': true
80365           };
80366           var past_futures = {
80367             'proposed': true,
80368             'construction': true,
80369             'abandoned': true,
80370             'dismantled': true,
80371             'disused': true,
80372             'razed': true,
80373             'demolished': true,
80374             'obliterated': true
80375           };
80376           var _cullFactor = 1;
80377           var _cache = {};
80378           var _rules = {};
80379           var _stats = {};
80380           var _keys = [];
80381           var _hidden = [];
80382           var _forceVisible = {};
80383
80384           function update() {
80385             if (!window.mocha) {
80386               var hash = utilStringQs(window.location.hash);
80387               var disabled = features.disabled();
80388
80389               if (disabled.length) {
80390                 hash.disable_features = disabled.join(',');
80391               } else {
80392                 delete hash.disable_features;
80393               }
80394
80395               window.location.replace('#' + utilQsString(hash, true));
80396               corePreferences('disabled-features', disabled.join(','));
80397             }
80398
80399             _hidden = features.hidden();
80400             dispatch.call('change');
80401             dispatch.call('redraw');
80402           }
80403
80404           function defineRule(k, filter, max) {
80405             var isEnabled = true;
80406
80407             _keys.push(k);
80408
80409             _rules[k] = {
80410               filter: filter,
80411               enabled: isEnabled,
80412               // whether the user wants it enabled..
80413               count: 0,
80414               currentMax: max || Infinity,
80415               defaultMax: max || Infinity,
80416               enable: function enable() {
80417                 this.enabled = true;
80418                 this.currentMax = this.defaultMax;
80419               },
80420               disable: function disable() {
80421                 this.enabled = false;
80422                 this.currentMax = 0;
80423               },
80424               hidden: function hidden() {
80425                 return this.count === 0 && !this.enabled || this.count > this.currentMax * _cullFactor;
80426               },
80427               autoHidden: function autoHidden() {
80428                 return this.hidden() && this.currentMax > 0;
80429               }
80430             };
80431           }
80432
80433           defineRule('points', function isPoint(tags, geometry) {
80434             return geometry === 'point';
80435           }, 200);
80436           defineRule('traffic_roads', function isTrafficRoad(tags) {
80437             return traffic_roads[tags.highway];
80438           });
80439           defineRule('service_roads', function isServiceRoad(tags) {
80440             return service_roads[tags.highway];
80441           });
80442           defineRule('paths', function isPath(tags) {
80443             return paths[tags.highway];
80444           });
80445           defineRule('buildings', function isBuilding(tags) {
80446             return !!tags.building && tags.building !== 'no' || tags.parking === 'multi-storey' || tags.parking === 'sheds' || tags.parking === 'carports' || tags.parking === 'garage_boxes';
80447           }, 250);
80448           defineRule('building_parts', function isBuildingPart(tags) {
80449             return tags['building:part'];
80450           });
80451           defineRule('indoor', function isIndoor(tags) {
80452             return tags.indoor;
80453           });
80454           defineRule('landuse', function isLanduse(tags, geometry) {
80455             return geometry === 'area' && !_rules.buildings.filter(tags) && !_rules.building_parts.filter(tags) && !_rules.indoor.filter(tags) && !_rules.water.filter(tags) && !_rules.pistes.filter(tags);
80456           });
80457           defineRule('boundaries', function isBoundary(tags) {
80458             return !!tags.boundary && !(traffic_roads[tags.highway] || service_roads[tags.highway] || paths[tags.highway] || tags.waterway || tags.railway || tags.landuse || tags.natural || tags.building || tags.power);
80459           });
80460           defineRule('water', function isWater(tags) {
80461             return !!tags.waterway || tags.natural === 'water' || tags.natural === 'coastline' || tags.natural === 'bay' || tags.landuse === 'pond' || tags.landuse === 'basin' || tags.landuse === 'reservoir' || tags.landuse === 'salt_pond';
80462           });
80463           defineRule('rail', function isRail(tags) {
80464             return (!!tags.railway || tags.landuse === 'railway') && !(traffic_roads[tags.highway] || service_roads[tags.highway] || paths[tags.highway]);
80465           });
80466           defineRule('pistes', function isPiste(tags) {
80467             return tags['piste:type'];
80468           });
80469           defineRule('aerialways', function isPiste(tags) {
80470             return tags.aerialway && tags.aerialway !== 'yes' && tags.aerialway !== 'station';
80471           });
80472           defineRule('power', function isPower(tags) {
80473             return !!tags.power;
80474           }); // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
80475
80476           defineRule('past_future', function isPastFuture(tags) {
80477             if (traffic_roads[tags.highway] || service_roads[tags.highway] || paths[tags.highway]) {
80478               return false;
80479             }
80480
80481             var strings = Object.keys(tags);
80482
80483             for (var i = 0; i < strings.length; i++) {
80484               var s = strings[i];
80485
80486               if (past_futures[s] || past_futures[tags[s]]) {
80487                 return true;
80488               }
80489             }
80490
80491             return false;
80492           }); // Lines or areas that don't match another feature filter.
80493           // IMPORTANT: The 'others' feature must be the last one defined,
80494           //   so that code in getMatches can skip this test if `hasMatch = true`
80495
80496           defineRule('others', function isOther(tags, geometry) {
80497             return geometry === 'line' || geometry === 'area';
80498           });
80499
80500           features.features = function () {
80501             return _rules;
80502           };
80503
80504           features.keys = function () {
80505             return _keys;
80506           };
80507
80508           features.enabled = function (k) {
80509             if (!arguments.length) {
80510               return _keys.filter(function (k) {
80511                 return _rules[k].enabled;
80512               });
80513             }
80514
80515             return _rules[k] && _rules[k].enabled;
80516           };
80517
80518           features.disabled = function (k) {
80519             if (!arguments.length) {
80520               return _keys.filter(function (k) {
80521                 return !_rules[k].enabled;
80522               });
80523             }
80524
80525             return _rules[k] && !_rules[k].enabled;
80526           };
80527
80528           features.hidden = function (k) {
80529             if (!arguments.length) {
80530               return _keys.filter(function (k) {
80531                 return _rules[k].hidden();
80532               });
80533             }
80534
80535             return _rules[k] && _rules[k].hidden();
80536           };
80537
80538           features.autoHidden = function (k) {
80539             if (!arguments.length) {
80540               return _keys.filter(function (k) {
80541                 return _rules[k].autoHidden();
80542               });
80543             }
80544
80545             return _rules[k] && _rules[k].autoHidden();
80546           };
80547
80548           features.enable = function (k) {
80549             if (_rules[k] && !_rules[k].enabled) {
80550               _rules[k].enable();
80551
80552               update();
80553             }
80554           };
80555
80556           features.enableAll = function () {
80557             var didEnable = false;
80558
80559             for (var k in _rules) {
80560               if (!_rules[k].enabled) {
80561                 didEnable = true;
80562
80563                 _rules[k].enable();
80564               }
80565             }
80566
80567             if (didEnable) update();
80568           };
80569
80570           features.disable = function (k) {
80571             if (_rules[k] && _rules[k].enabled) {
80572               _rules[k].disable();
80573
80574               update();
80575             }
80576           };
80577
80578           features.disableAll = function () {
80579             var didDisable = false;
80580
80581             for (var k in _rules) {
80582               if (_rules[k].enabled) {
80583                 didDisable = true;
80584
80585                 _rules[k].disable();
80586               }
80587             }
80588
80589             if (didDisable) update();
80590           };
80591
80592           features.toggle = function (k) {
80593             if (_rules[k]) {
80594               (function (f) {
80595                 return f.enabled ? f.disable() : f.enable();
80596               })(_rules[k]);
80597
80598               update();
80599             }
80600           };
80601
80602           features.resetStats = function () {
80603             for (var i = 0; i < _keys.length; i++) {
80604               _rules[_keys[i]].count = 0;
80605             }
80606
80607             dispatch.call('change');
80608           };
80609
80610           features.gatherStats = function (d, resolver, dimensions) {
80611             var needsRedraw = false;
80612             var types = utilArrayGroupBy(d, 'type');
80613             var entities = [].concat(types.relation || [], types.way || [], types.node || []);
80614             var currHidden, geometry, matches, i, j;
80615
80616             for (i = 0; i < _keys.length; i++) {
80617               _rules[_keys[i]].count = 0;
80618             } // adjust the threshold for point/building culling based on viewport size..
80619             // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
80620
80621
80622             _cullFactor = dimensions[0] * dimensions[1] / 1000000;
80623
80624             for (i = 0; i < entities.length; i++) {
80625               geometry = entities[i].geometry(resolver);
80626               matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
80627
80628               for (j = 0; j < matches.length; j++) {
80629                 _rules[matches[j]].count++;
80630               }
80631             }
80632
80633             currHidden = features.hidden();
80634
80635             if (currHidden !== _hidden) {
80636               _hidden = currHidden;
80637               needsRedraw = true;
80638               dispatch.call('change');
80639             }
80640
80641             return needsRedraw;
80642           };
80643
80644           features.stats = function () {
80645             for (var i = 0; i < _keys.length; i++) {
80646               _stats[_keys[i]] = _rules[_keys[i]].count;
80647             }
80648
80649             return _stats;
80650           };
80651
80652           features.clear = function (d) {
80653             for (var i = 0; i < d.length; i++) {
80654               features.clearEntity(d[i]);
80655             }
80656           };
80657
80658           features.clearEntity = function (entity) {
80659             delete _cache[osmEntity.key(entity)];
80660           };
80661
80662           features.reset = function () {
80663             Array.from(_deferred).forEach(function (handle) {
80664               window.cancelIdleCallback(handle);
80665
80666               _deferred["delete"](handle);
80667             });
80668             _cache = {};
80669           }; // only certain relations are worth checking
80670
80671
80672           function relationShouldBeChecked(relation) {
80673             // multipolygon features have `area` geometry and aren't checked here
80674             return relation.tags.type === 'boundary';
80675           }
80676
80677           features.getMatches = function (entity, resolver, geometry) {
80678             if (geometry === 'vertex' || geometry === 'relation' && !relationShouldBeChecked(entity)) return {};
80679             var ent = osmEntity.key(entity);
80680
80681             if (!_cache[ent]) {
80682               _cache[ent] = {};
80683             }
80684
80685             if (!_cache[ent].matches) {
80686               var matches = {};
80687               var hasMatch = false;
80688
80689               for (var i = 0; i < _keys.length; i++) {
80690                 if (_keys[i] === 'others') {
80691                   if (hasMatch) continue; // If an entity...
80692                   //   1. is a way that hasn't matched other 'interesting' feature rules,
80693
80694                   if (entity.type === 'way') {
80695                     var parents = features.getParents(entity, resolver, geometry); //   2a. belongs only to a single multipolygon relation
80696
80697                     if (parents.length === 1 && parents[0].isMultipolygon() || // 2b. or belongs only to boundary relations
80698                     parents.length > 0 && parents.every(function (parent) {
80699                       return parent.tags.type === 'boundary';
80700                     })) {
80701                       // ...then match whatever feature rules the parent relation has matched.
80702                       // see #2548, #2887
80703                       //
80704                       // IMPORTANT:
80705                       // For this to work, getMatches must be called on relations before ways.
80706                       //
80707                       var pkey = osmEntity.key(parents[0]);
80708
80709                       if (_cache[pkey] && _cache[pkey].matches) {
80710                         matches = Object.assign({}, _cache[pkey].matches); // shallow copy
80711
80712                         continue;
80713                       }
80714                     }
80715                   }
80716                 }
80717
80718                 if (_rules[_keys[i]].filter(entity.tags, geometry)) {
80719                   matches[_keys[i]] = hasMatch = true;
80720                 }
80721               }
80722
80723               _cache[ent].matches = matches;
80724             }
80725
80726             return _cache[ent].matches;
80727           };
80728
80729           features.getParents = function (entity, resolver, geometry) {
80730             if (geometry === 'point') return [];
80731             var ent = osmEntity.key(entity);
80732
80733             if (!_cache[ent]) {
80734               _cache[ent] = {};
80735             }
80736
80737             if (!_cache[ent].parents) {
80738               var parents = [];
80739
80740               if (geometry === 'vertex') {
80741                 parents = resolver.parentWays(entity);
80742               } else {
80743                 // 'line', 'area', 'relation'
80744                 parents = resolver.parentRelations(entity);
80745               }
80746
80747               _cache[ent].parents = parents;
80748             }
80749
80750             return _cache[ent].parents;
80751           };
80752
80753           features.isHiddenPreset = function (preset, geometry) {
80754             if (!_hidden.length) return false;
80755             if (!preset.tags) return false;
80756             var test = preset.setTags({}, geometry);
80757
80758             for (var key in _rules) {
80759               if (_rules[key].filter(test, geometry)) {
80760                 if (_hidden.indexOf(key) !== -1) {
80761                   return key;
80762                 }
80763
80764                 return false;
80765               }
80766             }
80767
80768             return false;
80769           };
80770
80771           features.isHiddenFeature = function (entity, resolver, geometry) {
80772             if (!_hidden.length) return false;
80773             if (!entity.version) return false;
80774             if (_forceVisible[entity.id]) return false;
80775             var matches = Object.keys(features.getMatches(entity, resolver, geometry));
80776             return matches.length && matches.every(function (k) {
80777               return features.hidden(k);
80778             });
80779           };
80780
80781           features.isHiddenChild = function (entity, resolver, geometry) {
80782             if (!_hidden.length) return false;
80783             if (!entity.version || geometry === 'point') return false;
80784             if (_forceVisible[entity.id]) return false;
80785             var parents = features.getParents(entity, resolver, geometry);
80786             if (!parents.length) return false;
80787
80788             for (var i = 0; i < parents.length; i++) {
80789               if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
80790                 return false;
80791               }
80792             }
80793
80794             return true;
80795           };
80796
80797           features.hasHiddenConnections = function (entity, resolver) {
80798             if (!_hidden.length) return false;
80799             var childNodes, connections;
80800
80801             if (entity.type === 'midpoint') {
80802               childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
80803               connections = [];
80804             } else {
80805               childNodes = entity.nodes ? resolver.childNodes(entity) : [];
80806               connections = features.getParents(entity, resolver, entity.geometry(resolver));
80807             } // gather ways connected to child nodes..
80808
80809
80810             connections = childNodes.reduce(function (result, e) {
80811               return resolver.isShared(e) ? utilArrayUnion(result, resolver.parentWays(e)) : result;
80812             }, connections);
80813             return connections.some(function (e) {
80814               return features.isHidden(e, resolver, e.geometry(resolver));
80815             });
80816           };
80817
80818           features.isHidden = function (entity, resolver, geometry) {
80819             if (!_hidden.length) return false;
80820             if (!entity.version) return false;
80821             var fn = geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature;
80822             return fn(entity, resolver, geometry);
80823           };
80824
80825           features.filter = function (d, resolver) {
80826             if (!_hidden.length) return d;
80827             var result = [];
80828
80829             for (var i = 0; i < d.length; i++) {
80830               var entity = d[i];
80831
80832               if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
80833                 result.push(entity);
80834               }
80835             }
80836
80837             return result;
80838           };
80839
80840           features.forceVisible = function (entityIDs) {
80841             if (!arguments.length) return Object.keys(_forceVisible);
80842             _forceVisible = {};
80843
80844             for (var i = 0; i < entityIDs.length; i++) {
80845               _forceVisible[entityIDs[i]] = true;
80846               var entity = context.hasEntity(entityIDs[i]);
80847
80848               if (entity && entity.type === 'relation') {
80849                 // also show relation members (one level deep)
80850                 for (var j in entity.members) {
80851                   _forceVisible[entity.members[j].id] = true;
80852                 }
80853               }
80854             }
80855
80856             return features;
80857           };
80858
80859           features.init = function () {
80860             var storage = corePreferences('disabled-features');
80861
80862             if (storage) {
80863               var storageDisabled = storage.replace(/;/g, ',').split(',');
80864               storageDisabled.forEach(features.disable);
80865             }
80866
80867             var hash = utilStringQs(window.location.hash);
80868
80869             if (hash.disable_features) {
80870               var hashDisabled = hash.disable_features.replace(/;/g, ',').split(',');
80871               hashDisabled.forEach(features.disable);
80872             }
80873           }; // warm up the feature matching cache upon merging fetched data
80874
80875
80876           context.history().on('merge.features', function (newEntities) {
80877             if (!newEntities) return;
80878             var handle = window.requestIdleCallback(function () {
80879               var graph = context.graph();
80880               var types = utilArrayGroupBy(newEntities, 'type'); // ensure that getMatches is called on relations before ways
80881
80882               var entities = [].concat(types.relation || [], types.way || [], types.node || []);
80883
80884               for (var i = 0; i < entities.length; i++) {
80885                 var geometry = entities[i].geometry(graph);
80886                 features.getMatches(entities[i], graph, geometry);
80887               }
80888             });
80889
80890             _deferred.add(handle);
80891           });
80892           return features;
80893         }
80894
80895         //
80896         // - the activeID - nope
80897         // - 1 away (adjacent) to the activeID - yes (vertices will be merged)
80898         // - 2 away from the activeID - nope (would create a self intersecting segment)
80899         // - all others on a linear way - yes
80900         // - all others on a closed way - nope (would create a self intersecting polygon)
80901         //
80902         // returns
80903         // 0 = active vertex - no touch/connect
80904         // 1 = passive vertex - yes touch/connect
80905         // 2 = adjacent vertex - yes but pay attention segmenting a line here
80906         //
80907
80908         function svgPassiveVertex(node, graph, activeID) {
80909           if (!activeID) return 1;
80910           if (activeID === node.id) return 0;
80911           var parents = graph.parentWays(node);
80912           var i, j, nodes, isClosed, ix1, ix2, ix3, ix4, max;
80913
80914           for (i = 0; i < parents.length; i++) {
80915             nodes = parents[i].nodes;
80916             isClosed = parents[i].isClosed();
80917
80918             for (j = 0; j < nodes.length; j++) {
80919               // find this vertex, look nearby
80920               if (nodes[j] === node.id) {
80921                 ix1 = j - 2;
80922                 ix2 = j - 1;
80923                 ix3 = j + 1;
80924                 ix4 = j + 2;
80925
80926                 if (isClosed) {
80927                   // wraparound if needed
80928                   max = nodes.length - 1;
80929                   if (ix1 < 0) ix1 = max + ix1;
80930                   if (ix2 < 0) ix2 = max + ix2;
80931                   if (ix3 > max) ix3 = ix3 - max;
80932                   if (ix4 > max) ix4 = ix4 - max;
80933                 }
80934
80935                 if (nodes[ix1] === activeID) return 0; // no - prevent self intersect
80936                 else if (nodes[ix2] === activeID) return 2; // ok - adjacent
80937                 else if (nodes[ix3] === activeID) return 2; // ok - adjacent
80938                 else if (nodes[ix4] === activeID) return 0; // no - prevent self intersect
80939                 else if (isClosed && nodes.indexOf(activeID) !== -1) return 0; // no - prevent self intersect
80940               }
80941             }
80942           }
80943
80944           return 1; // ok
80945         }
80946         function svgMarkerSegments(projection, graph, dt, shouldReverse, bothDirections) {
80947           return function (entity) {
80948             var i = 0;
80949             var offset = dt;
80950             var segments = [];
80951             var clip = d3_geoIdentity().clipExtent(projection.clipExtent()).stream;
80952             var coordinates = graph.childNodes(entity).map(function (n) {
80953               return n.loc;
80954             });
80955             var a, b;
80956
80957             if (shouldReverse(entity)) {
80958               coordinates.reverse();
80959             }
80960
80961             d3_geoStream({
80962               type: 'LineString',
80963               coordinates: coordinates
80964             }, projection.stream(clip({
80965               lineStart: function lineStart() {},
80966               lineEnd: function lineEnd() {
80967                 a = null;
80968               },
80969               point: function point(x, y) {
80970                 b = [x, y];
80971
80972                 if (a) {
80973                   var span = geoVecLength(a, b) - offset;
80974
80975                   if (span >= 0) {
80976                     var heading = geoVecAngle(a, b);
80977                     var dx = dt * Math.cos(heading);
80978                     var dy = dt * Math.sin(heading);
80979                     var p = [a[0] + offset * Math.cos(heading), a[1] + offset * Math.sin(heading)]; // gather coordinates
80980
80981                     var coord = [a, p];
80982
80983                     for (span -= dt; span >= 0; span -= dt) {
80984                       p = geoVecAdd(p, [dx, dy]);
80985                       coord.push(p);
80986                     }
80987
80988                     coord.push(b); // generate svg paths
80989
80990                     var segment = '';
80991                     var j;
80992
80993                     for (j = 0; j < coord.length; j++) {
80994                       segment += (j === 0 ? 'M' : 'L') + coord[j][0] + ',' + coord[j][1];
80995                     }
80996
80997                     segments.push({
80998                       id: entity.id,
80999                       index: i++,
81000                       d: segment
81001                     });
81002
81003                     if (bothDirections(entity)) {
81004                       segment = '';
81005
81006                       for (j = coord.length - 1; j >= 0; j--) {
81007                         segment += (j === coord.length - 1 ? 'M' : 'L') + coord[j][0] + ',' + coord[j][1];
81008                       }
81009
81010                       segments.push({
81011                         id: entity.id,
81012                         index: i++,
81013                         d: segment
81014                       });
81015                     }
81016                   }
81017
81018                   offset = -span;
81019                 }
81020
81021                 a = b;
81022               }
81023             })));
81024             return segments;
81025           };
81026         }
81027         function svgPath(projection, graph, isArea) {
81028           // Explanation of magic numbers:
81029           // "padding" here allows space for strokes to extend beyond the viewport,
81030           // so that the stroke isn't drawn along the edge of the viewport when
81031           // the shape is clipped.
81032           //
81033           // When drawing lines, pad viewport by 5px.
81034           // When drawing areas, pad viewport by 65px in each direction to allow
81035           // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
81036           var cache = {};
81037           var padding = isArea ? 65 : 5;
81038           var viewport = projection.clipExtent();
81039           var paddedExtent = [[viewport[0][0] - padding, viewport[0][1] - padding], [viewport[1][0] + padding, viewport[1][1] + padding]];
81040           var clip = d3_geoIdentity().clipExtent(paddedExtent).stream;
81041           var project = projection.stream;
81042           var path = d3_geoPath().projection({
81043             stream: function stream(output) {
81044               return project(clip(output));
81045             }
81046           });
81047
81048           var svgpath = function svgpath(entity) {
81049             if (entity.id in cache) {
81050               return cache[entity.id];
81051             } else {
81052               return cache[entity.id] = path(entity.asGeoJSON(graph));
81053             }
81054           };
81055
81056           svgpath.geojson = function (d) {
81057             if (d.__featurehash__ !== undefined) {
81058               if (d.__featurehash__ in cache) {
81059                 return cache[d.__featurehash__];
81060               } else {
81061                 return cache[d.__featurehash__] = path(d);
81062               }
81063             } else {
81064               return path(d);
81065             }
81066           };
81067
81068           return svgpath;
81069         }
81070         function svgPointTransform(projection) {
81071           var svgpoint = function svgpoint(entity) {
81072             // http://jsperf.com/short-array-join
81073             var pt = projection(entity.loc);
81074             return 'translate(' + pt[0] + ',' + pt[1] + ')';
81075           };
81076
81077           svgpoint.geojson = function (d) {
81078             return svgpoint(d.properties.entity);
81079           };
81080
81081           return svgpoint;
81082         }
81083         function svgRelationMemberTags(graph) {
81084           return function (entity) {
81085             var tags = entity.tags;
81086             var shouldCopyMultipolygonTags = !entity.hasInterestingTags();
81087             graph.parentRelations(entity).forEach(function (relation) {
81088               var type = relation.tags.type;
81089
81090               if (type === 'multipolygon' && shouldCopyMultipolygonTags || type === 'boundary') {
81091                 tags = Object.assign({}, relation.tags, tags);
81092               }
81093             });
81094             return tags;
81095           };
81096         }
81097         function svgSegmentWay(way, graph, activeID) {
81098           // When there is no activeID, we can memoize this expensive computation
81099           if (activeID === undefined) {
81100             return graph["transient"](way, 'waySegments', getWaySegments);
81101           } else {
81102             return getWaySegments();
81103           }
81104
81105           function getWaySegments() {
81106             var isActiveWay = way.nodes.indexOf(activeID) !== -1;
81107             var features = {
81108               passive: [],
81109               active: []
81110             };
81111             var start = {};
81112             var end = {};
81113             var node, type;
81114
81115             for (var i = 0; i < way.nodes.length; i++) {
81116               node = graph.entity(way.nodes[i]);
81117               type = svgPassiveVertex(node, graph, activeID);
81118               end = {
81119                 node: node,
81120                 type: type
81121               };
81122
81123               if (start.type !== undefined) {
81124                 if (start.node.id === activeID || end.node.id === activeID) ; else if (isActiveWay && (start.type === 2 || end.type === 2)) {
81125                   // one adjacent vertex
81126                   pushActive(start, end, i);
81127                 } else if (start.type === 0 && end.type === 0) {
81128                   // both active vertices
81129                   pushActive(start, end, i);
81130                 } else {
81131                   pushPassive(start, end, i);
81132                 }
81133               }
81134
81135               start = end;
81136             }
81137
81138             return features;
81139
81140             function pushActive(start, end, index) {
81141               features.active.push({
81142                 type: 'Feature',
81143                 id: way.id + '-' + index + '-nope',
81144                 properties: {
81145                   nope: true,
81146                   target: true,
81147                   entity: way,
81148                   nodes: [start.node, end.node],
81149                   index: index
81150                 },
81151                 geometry: {
81152                   type: 'LineString',
81153                   coordinates: [start.node.loc, end.node.loc]
81154                 }
81155               });
81156             }
81157
81158             function pushPassive(start, end, index) {
81159               features.passive.push({
81160                 type: 'Feature',
81161                 id: way.id + '-' + index,
81162                 properties: {
81163                   target: true,
81164                   entity: way,
81165                   nodes: [start.node, end.node],
81166                   index: index
81167                 },
81168                 geometry: {
81169                   type: 'LineString',
81170                   coordinates: [start.node.loc, end.node.loc]
81171                 }
81172               });
81173             }
81174           }
81175         }
81176
81177         function svgTagClasses() {
81178           var primaries = ['building', 'highway', 'railway', 'waterway', 'aeroway', 'aerialway', 'piste:type', 'boundary', 'power', 'amenity', 'natural', 'landuse', 'leisure', 'military', 'place', 'man_made', 'route', 'attraction', 'building:part', 'indoor'];
81179           var statuses = [// nonexistent, might be built
81180           'proposed', 'planned', // under maintentance or between groundbreaking and opening
81181           'construction', // existent but not functional
81182           'disused', // dilapidated to nonexistent
81183           'abandoned', // nonexistent, still may appear in imagery
81184           'dismantled', 'razed', 'demolished', 'obliterated', // existent occasionally, e.g. stormwater drainage basin
81185           'intermittent'];
81186           var secondaries = ['oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier', 'surface', 'tracktype', 'footway', 'crossing', 'service', 'sport', 'public_transport', 'location', 'parking', 'golf', 'type', 'leisure', 'man_made', 'indoor', 'construction', 'proposed'];
81187
81188           var _tags = function _tags(entity) {
81189             return entity.tags;
81190           };
81191
81192           var tagClasses = function tagClasses(selection) {
81193             selection.each(function tagClassesEach(entity) {
81194               var value = this.className;
81195
81196               if (value.baseVal !== undefined) {
81197                 value = value.baseVal;
81198               }
81199
81200               var t = _tags(entity);
81201
81202               var computed = tagClasses.getClassesString(t, value);
81203
81204               if (computed !== value) {
81205                 select(this).attr('class', computed);
81206               }
81207             });
81208           };
81209
81210           tagClasses.getClassesString = function (t, value) {
81211             var primary, status;
81212             var i, j, k, v; // in some situations we want to render perimeter strokes a certain way
81213
81214             var overrideGeometry;
81215
81216             if (/\bstroke\b/.test(value)) {
81217               if (!!t.barrier && t.barrier !== 'no') {
81218                 overrideGeometry = 'line';
81219               }
81220             } // preserve base classes (nothing with `tag-`)
81221
81222
81223             var classes = value.trim().split(/\s+/).filter(function (klass) {
81224               return klass.length && !/^tag-/.test(klass);
81225             }).map(function (klass) {
81226               // special overrides for some perimeter strokes
81227               return klass === 'line' || klass === 'area' ? overrideGeometry || klass : klass;
81228             }); // pick at most one primary classification tag..
81229
81230             for (i = 0; i < primaries.length; i++) {
81231               k = primaries[i];
81232               v = t[k];
81233               if (!v || v === 'no') continue;
81234
81235               if (k === 'piste:type') {
81236                 // avoid a ':' in the class name
81237                 k = 'piste';
81238               } else if (k === 'building:part') {
81239                 // avoid a ':' in the class name
81240                 k = 'building_part';
81241               }
81242
81243               primary = k;
81244
81245               if (statuses.indexOf(v) !== -1) {
81246                 // e.g. `railway=abandoned`
81247                 status = v;
81248                 classes.push('tag-' + k);
81249               } else {
81250                 classes.push('tag-' + k);
81251                 classes.push('tag-' + k + '-' + v);
81252               }
81253
81254               break;
81255             }
81256
81257             if (!primary) {
81258               for (i = 0; i < statuses.length; i++) {
81259                 for (j = 0; j < primaries.length; j++) {
81260                   k = statuses[i] + ':' + primaries[j]; // e.g. `demolished:building=yes`
81261
81262                   v = t[k];
81263                   if (!v || v === 'no') continue;
81264                   status = statuses[i];
81265                   break;
81266                 }
81267               }
81268             } // add at most one status tag, only if relates to primary tag..
81269
81270
81271             if (!status) {
81272               for (i = 0; i < statuses.length; i++) {
81273                 k = statuses[i];
81274                 v = t[k];
81275                 if (!v || v === 'no') continue;
81276
81277                 if (v === 'yes') {
81278                   // e.g. `railway=rail + abandoned=yes`
81279                   status = k;
81280                 } else if (primary && primary === v) {
81281                   // e.g. `railway=rail + abandoned=railway`
81282                   status = k;
81283                 } else if (!primary && primaries.indexOf(v) !== -1) {
81284                   // e.g. `abandoned=railway`
81285                   status = k;
81286                   primary = v;
81287                   classes.push('tag-' + v);
81288                 } // else ignore e.g.  `highway=path + abandoned=railway`
81289
81290
81291                 if (status) break;
81292               }
81293             }
81294
81295             if (status) {
81296               classes.push('tag-status');
81297               classes.push('tag-status-' + status);
81298             } // add any secondary tags
81299
81300
81301             for (i = 0; i < secondaries.length; i++) {
81302               k = secondaries[i];
81303               v = t[k];
81304               if (!v || v === 'no' || k === primary) continue;
81305               classes.push('tag-' + k);
81306               classes.push('tag-' + k + '-' + v);
81307             } // For highways, look for surface tagging..
81308
81309
81310             if (primary === 'highway' && !osmPathHighwayTagValues[t.highway] || primary === 'aeroway') {
81311               var surface = t.highway === 'track' ? 'unpaved' : 'paved';
81312
81313               for (k in t) {
81314                 v = t[k];
81315
81316                 if (k in osmPavedTags) {
81317                   surface = osmPavedTags[k][v] ? 'paved' : 'unpaved';
81318                 }
81319
81320                 if (k in osmSemipavedTags && !!osmSemipavedTags[k][v]) {
81321                   surface = 'semipaved';
81322                 }
81323               }
81324
81325               classes.push('tag-' + surface);
81326             } // If this is a wikidata-tagged item, add a class for that..
81327
81328
81329             var qid = t.wikidata || t['flag:wikidata'] || t['brand:wikidata'] || t['network:wikidata'] || t['operator:wikidata'];
81330
81331             if (qid) {
81332               classes.push('tag-wikidata');
81333             }
81334
81335             return classes.join(' ').trim();
81336           };
81337
81338           tagClasses.tags = function (val) {
81339             if (!arguments.length) return _tags;
81340             _tags = val;
81341             return tagClasses;
81342           };
81343
81344           return tagClasses;
81345         }
81346
81347         // Patterns only work in Firefox when set directly on element.
81348         // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
81349         var patterns = {
81350           // tag - pattern name
81351           // -or-
81352           // tag - value - pattern name
81353           // -or-
81354           // tag - value - rules (optional tag-values, pattern name)
81355           // (matches earlier rules first, so fallback should be last entry)
81356           amenity: {
81357             grave_yard: 'cemetery',
81358             fountain: 'water_standing'
81359           },
81360           landuse: {
81361             cemetery: [{
81362               religion: 'christian',
81363               pattern: 'cemetery_christian'
81364             }, {
81365               religion: 'buddhist',
81366               pattern: 'cemetery_buddhist'
81367             }, {
81368               religion: 'muslim',
81369               pattern: 'cemetery_muslim'
81370             }, {
81371               religion: 'jewish',
81372               pattern: 'cemetery_jewish'
81373             }, {
81374               pattern: 'cemetery'
81375             }],
81376             construction: 'construction',
81377             farmland: 'farmland',
81378             farmyard: 'farmyard',
81379             forest: [{
81380               leaf_type: 'broadleaved',
81381               pattern: 'forest_broadleaved'
81382             }, {
81383               leaf_type: 'needleleaved',
81384               pattern: 'forest_needleleaved'
81385             }, {
81386               leaf_type: 'leafless',
81387               pattern: 'forest_leafless'
81388             }, {
81389               pattern: 'forest'
81390             } // same as 'leaf_type:mixed'
81391             ],
81392             grave_yard: 'cemetery',
81393             grass: [{
81394               golf: 'green',
81395               pattern: 'golf_green'
81396             }, {
81397               pattern: 'grass'
81398             }],
81399             landfill: 'landfill',
81400             meadow: 'meadow',
81401             military: 'construction',
81402             orchard: 'orchard',
81403             quarry: 'quarry',
81404             vineyard: 'vineyard'
81405           },
81406           natural: {
81407             beach: 'beach',
81408             grassland: 'grass',
81409             sand: 'beach',
81410             scrub: 'scrub',
81411             water: [{
81412               water: 'pond',
81413               pattern: 'pond'
81414             }, {
81415               water: 'reservoir',
81416               pattern: 'water_standing'
81417             }, {
81418               pattern: 'waves'
81419             }],
81420             wetland: [{
81421               wetland: 'marsh',
81422               pattern: 'wetland_marsh'
81423             }, {
81424               wetland: 'swamp',
81425               pattern: 'wetland_swamp'
81426             }, {
81427               wetland: 'bog',
81428               pattern: 'wetland_bog'
81429             }, {
81430               wetland: 'reedbed',
81431               pattern: 'wetland_reedbed'
81432             }, {
81433               pattern: 'wetland'
81434             }],
81435             wood: [{
81436               leaf_type: 'broadleaved',
81437               pattern: 'forest_broadleaved'
81438             }, {
81439               leaf_type: 'needleleaved',
81440               pattern: 'forest_needleleaved'
81441             }, {
81442               leaf_type: 'leafless',
81443               pattern: 'forest_leafless'
81444             }, {
81445               pattern: 'forest'
81446             } // same as 'leaf_type:mixed'
81447             ]
81448           },
81449           traffic_calming: {
81450             island: [{
81451               surface: 'grass',
81452               pattern: 'grass'
81453             }],
81454             chicane: [{
81455               surface: 'grass',
81456               pattern: 'grass'
81457             }],
81458             choker: [{
81459               surface: 'grass',
81460               pattern: 'grass'
81461             }]
81462           }
81463         };
81464         function svgTagPattern(tags) {
81465           // Skip pattern filling if this is a building (buildings don't get patterns applied)
81466           if (tags.building && tags.building !== 'no') {
81467             return null;
81468           }
81469
81470           for (var tag in patterns) {
81471             var entityValue = tags[tag];
81472             if (!entityValue) continue;
81473
81474             if (typeof patterns[tag] === 'string') {
81475               // extra short syntax (just tag) - pattern name
81476               return 'pattern-' + patterns[tag];
81477             } else {
81478               var values = patterns[tag];
81479
81480               for (var value in values) {
81481                 if (entityValue !== value) continue;
81482                 var rules = values[value];
81483
81484                 if (typeof rules === 'string') {
81485                   // short syntax - pattern name
81486                   return 'pattern-' + rules;
81487                 } // long syntax - rule array
81488
81489
81490                 for (var ruleKey in rules) {
81491                   var rule = rules[ruleKey];
81492                   var pass = true;
81493
81494                   for (var criterion in rule) {
81495                     if (criterion !== 'pattern') {
81496                       // reserved for pattern name
81497                       // The only rule is a required tag-value pair
81498                       var v = tags[criterion];
81499
81500                       if (!v || v !== rule[criterion]) {
81501                         pass = false;
81502                         break;
81503                       }
81504                     }
81505                   }
81506
81507                   if (pass) {
81508                     return 'pattern-' + rule.pattern;
81509                   }
81510                 }
81511               }
81512             }
81513           }
81514
81515           return null;
81516         }
81517
81518         function svgAreas(projection, context) {
81519           function getPatternStyle(tags) {
81520             var imageID = svgTagPattern(tags);
81521
81522             if (imageID) {
81523               return 'url("#ideditor-' + imageID + '")';
81524             }
81525
81526             return '';
81527           }
81528
81529           function drawTargets(selection, graph, entities, filter) {
81530             var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
81531             var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor ';
81532             var getPath = svgPath(projection).geojson;
81533             var activeID = context.activeID();
81534             var base = context.history().base(); // The targets and nopes will be MultiLineString sub-segments of the ways
81535
81536             var data = {
81537               targets: [],
81538               nopes: []
81539             };
81540             entities.forEach(function (way) {
81541               var features = svgSegmentWay(way, graph, activeID);
81542               data.targets.push.apply(data.targets, features.passive);
81543               data.nopes.push.apply(data.nopes, features.active);
81544             }); // Targets allow hover and vertex snapping
81545
81546             var targetData = data.targets.filter(getPath);
81547             var targets = selection.selectAll('.area.target-allowed').filter(function (d) {
81548               return filter(d.properties.entity);
81549             }).data(targetData, function key(d) {
81550               return d.id;
81551             }); // exit
81552
81553             targets.exit().remove();
81554
81555             var segmentWasEdited = function segmentWasEdited(d) {
81556               var wayID = d.properties.entity.id; // if the whole line was edited, don't draw segment changes
81557
81558               if (!base.entities[wayID] || !fastDeepEqual(graph.entities[wayID].nodes, base.entities[wayID].nodes)) {
81559                 return false;
81560               }
81561
81562               return d.properties.nodes.some(function (n) {
81563                 return !base.entities[n.id] || !fastDeepEqual(graph.entities[n.id].loc, base.entities[n.id].loc);
81564               });
81565             }; // enter/update
81566
81567
81568             targets.enter().append('path').merge(targets).attr('d', getPath).attr('class', function (d) {
81569               return 'way area target target-allowed ' + targetClass + d.id;
81570             }).classed('segment-edited', segmentWasEdited); // NOPE
81571
81572             var nopeData = data.nopes.filter(getPath);
81573             var nopes = selection.selectAll('.area.target-nope').filter(function (d) {
81574               return filter(d.properties.entity);
81575             }).data(nopeData, function key(d) {
81576               return d.id;
81577             }); // exit
81578
81579             nopes.exit().remove(); // enter/update
81580
81581             nopes.enter().append('path').merge(nopes).attr('d', getPath).attr('class', function (d) {
81582               return 'way area target target-nope ' + nopeClass + d.id;
81583             }).classed('segment-edited', segmentWasEdited);
81584           }
81585
81586           function drawAreas(selection, graph, entities, filter) {
81587             var path = svgPath(projection, graph, true);
81588             var areas = {};
81589             var multipolygon;
81590             var base = context.history().base();
81591
81592             for (var i = 0; i < entities.length; i++) {
81593               var entity = entities[i];
81594               if (entity.geometry(graph) !== 'area') continue;
81595               multipolygon = osmIsOldMultipolygonOuterMember(entity, graph);
81596
81597               if (multipolygon) {
81598                 areas[multipolygon.id] = {
81599                   entity: multipolygon.mergeTags(entity.tags),
81600                   area: Math.abs(entity.area(graph))
81601                 };
81602               } else if (!areas[entity.id]) {
81603                 areas[entity.id] = {
81604                   entity: entity,
81605                   area: Math.abs(entity.area(graph))
81606                 };
81607               }
81608             }
81609
81610             var fills = Object.values(areas).filter(function hasPath(a) {
81611               return path(a.entity);
81612             });
81613             fills.sort(function areaSort(a, b) {
81614               return b.area - a.area;
81615             });
81616             fills = fills.map(function (a) {
81617               return a.entity;
81618             });
81619             var strokes = fills.filter(function (area) {
81620               return area.type === 'way';
81621             });
81622             var data = {
81623               clip: fills,
81624               shadow: strokes,
81625               stroke: strokes,
81626               fill: fills
81627             };
81628             var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath-osm').filter(filter).data(data.clip, osmEntity.key);
81629             clipPaths.exit().remove();
81630             var clipPathsEnter = clipPaths.enter().append('clipPath').attr('class', 'clipPath-osm').attr('id', function (entity) {
81631               return 'ideditor-' + entity.id + '-clippath';
81632             });
81633             clipPathsEnter.append('path');
81634             clipPaths.merge(clipPathsEnter).selectAll('path').attr('d', path);
81635             var drawLayer = selection.selectAll('.layer-osm.areas');
81636             var touchLayer = selection.selectAll('.layer-touch.areas'); // Draw areas..
81637
81638             var areagroup = drawLayer.selectAll('g.areagroup').data(['fill', 'shadow', 'stroke']);
81639             areagroup = areagroup.enter().append('g').attr('class', function (d) {
81640               return 'areagroup area-' + d;
81641             }).merge(areagroup);
81642             var paths = areagroup.selectAll('path').filter(filter).data(function (layer) {
81643               return data[layer];
81644             }, osmEntity.key);
81645             paths.exit().remove();
81646             var fillpaths = selection.selectAll('.area-fill path.area').nodes();
81647             var bisect = d3_bisector(function (node) {
81648               return -node.__data__.area(graph);
81649             }).left;
81650
81651             function sortedByArea(entity) {
81652               if (this._parent.__data__ === 'fill') {
81653                 return fillpaths[bisect(fillpaths, -entity.area(graph))];
81654               }
81655             }
81656
81657             paths = paths.enter().insert('path', sortedByArea).merge(paths).each(function (entity) {
81658               var layer = this.parentNode.__data__;
81659               this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
81660
81661               if (layer === 'fill') {
81662                 this.setAttribute('clip-path', 'url(#ideditor-' + entity.id + '-clippath)');
81663                 this.style.fill = this.style.stroke = getPatternStyle(entity.tags);
81664               }
81665             }).classed('added', function (d) {
81666               return !base.entities[d.id];
81667             }).classed('geometry-edited', function (d) {
81668               return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].nodes, base.entities[d.id].nodes);
81669             }).classed('retagged', function (d) {
81670               return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
81671             }).call(svgTagClasses()).attr('d', path); // Draw touch targets..
81672
81673             touchLayer.call(drawTargets, graph, data.stroke, filter);
81674           }
81675
81676           return drawAreas;
81677         }
81678
81679         var fastJsonStableStringify = function fastJsonStableStringify(data, opts) {
81680           if (!opts) opts = {};
81681           if (typeof opts === 'function') opts = {
81682             cmp: opts
81683           };
81684           var cycles = typeof opts.cycles === 'boolean' ? opts.cycles : false;
81685
81686           var cmp = opts.cmp && function (f) {
81687             return function (node) {
81688               return function (a, b) {
81689                 var aobj = {
81690                   key: a,
81691                   value: node[a]
81692                 };
81693                 var bobj = {
81694                   key: b,
81695                   value: node[b]
81696                 };
81697                 return f(aobj, bobj);
81698               };
81699             };
81700           }(opts.cmp);
81701
81702           var seen = [];
81703           return function stringify(node) {
81704             if (node && node.toJSON && typeof node.toJSON === 'function') {
81705               node = node.toJSON();
81706             }
81707
81708             if (node === undefined) return;
81709             if (typeof node == 'number') return isFinite(node) ? '' + node : 'null';
81710             if (_typeof(node) !== 'object') return JSON.stringify(node);
81711             var i, out;
81712
81713             if (Array.isArray(node)) {
81714               out = '[';
81715
81716               for (i = 0; i < node.length; i++) {
81717                 if (i) out += ',';
81718                 out += stringify(node[i]) || 'null';
81719               }
81720
81721               return out + ']';
81722             }
81723
81724             if (node === null) return 'null';
81725
81726             if (seen.indexOf(node) !== -1) {
81727               if (cycles) return JSON.stringify('__cycle__');
81728               throw new TypeError('Converting circular structure to JSON');
81729             }
81730
81731             var seenIndex = seen.push(node) - 1;
81732             var keys = Object.keys(node).sort(cmp && cmp(node));
81733             out = '';
81734
81735             for (i = 0; i < keys.length; i++) {
81736               var key = keys[i];
81737               var value = stringify(node[key]);
81738               if (!value) continue;
81739               if (out) out += ',';
81740               out += JSON.stringify(key) + ':' + value;
81741             }
81742
81743             seen.splice(seenIndex, 1);
81744             return '{' + out + '}';
81745           }(data);
81746         };
81747
81748         var $$1 = _export;
81749         var $entries = objectToArray.entries;
81750
81751         // `Object.entries` method
81752         // https://tc39.es/ecma262/#sec-object.entries
81753         $$1({ target: 'Object', stat: true }, {
81754           entries: function entries(O) {
81755             return $entries(O);
81756           }
81757         });
81758
81759         var _marked = /*#__PURE__*/regeneratorRuntime.mark(gpxGen),
81760             _marked3 = /*#__PURE__*/regeneratorRuntime.mark(kmlGen);
81761
81762         // cast array x into numbers
81763         // get the content of a text node, if any
81764         function nodeVal(x) {
81765           if (x && x.normalize) {
81766             x.normalize();
81767           }
81768
81769           return x && x.textContent || "";
81770         } // one Y child of X, if any, otherwise null
81771
81772
81773         function get1(x, y) {
81774           var n = x.getElementsByTagName(y);
81775           return n.length ? n[0] : null;
81776         }
81777
81778         function getLineStyle(extensions) {
81779           var style = {};
81780
81781           if (extensions) {
81782             var lineStyle = get1(extensions, "line");
81783
81784             if (lineStyle) {
81785               var color = nodeVal(get1(lineStyle, "color")),
81786                   opacity = parseFloat(nodeVal(get1(lineStyle, "opacity"))),
81787                   width = parseFloat(nodeVal(get1(lineStyle, "width")));
81788               if (color) style.stroke = color;
81789               if (!isNaN(opacity)) style["stroke-opacity"] = opacity; // GPX width is in mm, convert to px with 96 px per inch
81790
81791               if (!isNaN(width)) style["stroke-width"] = width * 96 / 25.4;
81792             }
81793           }
81794
81795           return style;
81796         } // get the contents of multiple text nodes, if present
81797
81798
81799         function getMulti(x, ys) {
81800           var o = {};
81801           var n;
81802           var k;
81803
81804           for (k = 0; k < ys.length; k++) {
81805             n = get1(x, ys[k]);
81806             if (n) o[ys[k]] = nodeVal(n);
81807           }
81808
81809           return o;
81810         }
81811
81812         function getProperties$1(node) {
81813           var prop = getMulti(node, ["name", "cmt", "desc", "type", "time", "keywords"]); // Parse additional data from our Garmin extension(s)
81814
81815           var extensions = node.getElementsByTagNameNS("http://www.garmin.com/xmlschemas/GpxExtensions/v3", "*");
81816
81817           for (var i = 0; i < extensions.length; i++) {
81818             var extension = extensions[i]; // Ignore nested extensions, like those on routepoints or trackpoints
81819
81820             if (extension.parentNode.parentNode === node) {
81821               prop[extension.tagName.replace(":", "_")] = nodeVal(extension);
81822             }
81823           }
81824
81825           var links = node.getElementsByTagName("link");
81826           if (links.length) prop.links = [];
81827
81828           for (var _i = 0; _i < links.length; _i++) {
81829             prop.links.push(Object.assign({
81830               href: links[_i].getAttribute("href")
81831             }, getMulti(links[_i], ["text", "type"])));
81832           }
81833
81834           return prop;
81835         }
81836
81837         function coordPair$1(x) {
81838           var ll = [parseFloat(x.getAttribute("lon")), parseFloat(x.getAttribute("lat"))];
81839           var ele = get1(x, "ele"); // handle namespaced attribute in browser
81840
81841           var heart = get1(x, "gpxtpx:hr") || get1(x, "hr");
81842           var time = get1(x, "time");
81843           var e;
81844
81845           if (ele) {
81846             e = parseFloat(nodeVal(ele));
81847
81848             if (!isNaN(e)) {
81849               ll.push(e);
81850             }
81851           }
81852
81853           var result = {
81854             coordinates: ll,
81855             time: time ? nodeVal(time) : null,
81856             extendedValues: []
81857           };
81858
81859           if (heart) {
81860             result.extendedValues.push(["heart", parseFloat(nodeVal(heart))]);
81861           }
81862
81863           var extensions = get1(x, "extensions");
81864
81865           if (extensions !== null) {
81866             for (var _i2 = 0, _arr = ["speed", "course", "hAcc", "vAcc"]; _i2 < _arr.length; _i2++) {
81867               var name = _arr[_i2];
81868               var v = parseFloat(nodeVal(get1(extensions, name)));
81869
81870               if (!isNaN(v)) {
81871                 result.extendedValues.push([name, v]);
81872               }
81873             }
81874           }
81875
81876           return result;
81877         }
81878
81879         function getRoute(node) {
81880           var line = getPoints$1(node, "rtept");
81881           if (!line) return;
81882           return {
81883             type: "Feature",
81884             properties: Object.assign(getProperties$1(node), getLineStyle(get1(node, "extensions")), {
81885               _gpxType: "rte"
81886             }),
81887             geometry: {
81888               type: "LineString",
81889               coordinates: line.line
81890             }
81891           };
81892         }
81893
81894         function getPoints$1(node, pointname) {
81895           var pts = node.getElementsByTagName(pointname);
81896           if (pts.length < 2) return; // Invalid line in GeoJSON
81897
81898           var line = [];
81899           var times = [];
81900           var extendedValues = {};
81901
81902           for (var i = 0; i < pts.length; i++) {
81903             var c = coordPair$1(pts[i]);
81904             line.push(c.coordinates);
81905             if (c.time) times.push(c.time);
81906
81907             for (var j = 0; j < c.extendedValues.length; j++) {
81908               var _c$extendedValues$j = _slicedToArray(c.extendedValues[j], 2),
81909                   name = _c$extendedValues$j[0],
81910                   val = _c$extendedValues$j[1];
81911
81912               var plural = name === "heart" ? name : name + "s";
81913
81914               if (!extendedValues[plural]) {
81915                 extendedValues[plural] = Array(pts.length).fill(null);
81916               }
81917
81918               extendedValues[plural][i] = val;
81919             }
81920           }
81921
81922           return {
81923             line: line,
81924             times: times,
81925             extendedValues: extendedValues
81926           };
81927         }
81928
81929         function getTrack(node) {
81930           var segments = node.getElementsByTagName("trkseg");
81931           var track = [];
81932           var times = [];
81933           var extractedLines = [];
81934
81935           for (var i = 0; i < segments.length; i++) {
81936             var line = getPoints$1(segments[i], "trkpt");
81937
81938             if (line) {
81939               extractedLines.push(line);
81940               if (line.times && line.times.length) times.push(line.times);
81941             }
81942           }
81943
81944           if (extractedLines.length === 0) return;
81945           var multi = extractedLines.length > 1;
81946           var properties = Object.assign(getProperties$1(node), getLineStyle(get1(node, "extensions")), {
81947             _gpxType: "trk"
81948           }, times.length ? {
81949             coordinateProperties: {
81950               times: multi ? times : times[0]
81951             }
81952           } : {});
81953
81954           for (var _i3 = 0; _i3 < extractedLines.length; _i3++) {
81955             var _line = extractedLines[_i3];
81956             track.push(_line.line);
81957
81958             for (var _i4 = 0, _Object$entries = Object.entries(_line.extendedValues); _i4 < _Object$entries.length; _i4++) {
81959               var _Object$entries$_i = _slicedToArray(_Object$entries[_i4], 2),
81960                   name = _Object$entries$_i[0],
81961                   val = _Object$entries$_i[1];
81962
81963               var props = properties;
81964
81965               if (name === "heart") {
81966                 if (!properties.coordinateProperties) {
81967                   properties.coordinateProperties = {};
81968                 }
81969
81970                 props = properties.coordinateProperties;
81971               }
81972
81973               if (multi) {
81974                 if (!props[name]) props[name] = extractedLines.map(function (line) {
81975                   return new Array(line.line.length).fill(null);
81976                 });
81977                 props[name][_i3] = val;
81978               } else {
81979                 props[name] = val;
81980               }
81981             }
81982           }
81983
81984           return {
81985             type: "Feature",
81986             properties: properties,
81987             geometry: multi ? {
81988               type: "MultiLineString",
81989               coordinates: track
81990             } : {
81991               type: "LineString",
81992               coordinates: track[0]
81993             }
81994           };
81995         }
81996
81997         function getPoint(node) {
81998           return {
81999             type: "Feature",
82000             properties: Object.assign(getProperties$1(node), getMulti(node, ["sym"])),
82001             geometry: {
82002               type: "Point",
82003               coordinates: coordPair$1(node).coordinates
82004             }
82005           };
82006         }
82007
82008         function gpxGen(doc) {
82009           var tracks, routes, waypoints, i, feature, _i5, _feature, _i6;
82010
82011           return regeneratorRuntime.wrap(function gpxGen$(_context) {
82012             while (1) {
82013               switch (_context.prev = _context.next) {
82014                 case 0:
82015                   tracks = doc.getElementsByTagName("trk");
82016                   routes = doc.getElementsByTagName("rte");
82017                   waypoints = doc.getElementsByTagName("wpt");
82018                   i = 0;
82019
82020                 case 4:
82021                   if (!(i < tracks.length)) {
82022                     _context.next = 12;
82023                     break;
82024                   }
82025
82026                   feature = getTrack(tracks[i]);
82027
82028                   if (!feature) {
82029                     _context.next = 9;
82030                     break;
82031                   }
82032
82033                   _context.next = 9;
82034                   return feature;
82035
82036                 case 9:
82037                   i++;
82038                   _context.next = 4;
82039                   break;
82040
82041                 case 12:
82042                   _i5 = 0;
82043
82044                 case 13:
82045                   if (!(_i5 < routes.length)) {
82046                     _context.next = 21;
82047                     break;
82048                   }
82049
82050                   _feature = getRoute(routes[_i5]);
82051
82052                   if (!_feature) {
82053                     _context.next = 18;
82054                     break;
82055                   }
82056
82057                   _context.next = 18;
82058                   return _feature;
82059
82060                 case 18:
82061                   _i5++;
82062                   _context.next = 13;
82063                   break;
82064
82065                 case 21:
82066                   _i6 = 0;
82067
82068                 case 22:
82069                   if (!(_i6 < waypoints.length)) {
82070                     _context.next = 28;
82071                     break;
82072                   }
82073
82074                   _context.next = 25;
82075                   return getPoint(waypoints[_i6]);
82076
82077                 case 25:
82078                   _i6++;
82079                   _context.next = 22;
82080                   break;
82081
82082                 case 28:
82083                 case "end":
82084                   return _context.stop();
82085               }
82086             }
82087           }, _marked);
82088         }
82089
82090         function gpx(doc) {
82091           return {
82092             type: "FeatureCollection",
82093             features: Array.from(gpxGen(doc))
82094           };
82095         }
82096
82097         var removeSpace = /\s*/g;
82098         var trimSpace = /^\s*|\s*$/g;
82099         var splitSpace = /\s+/; // generate a short, numeric hash of a string
82100
82101         function okhash(x) {
82102           if (!x || !x.length) return 0;
82103           var h = 0;
82104
82105           for (var i = 0; i < x.length; i++) {
82106             h = (h << 5) - h + x.charCodeAt(i) | 0;
82107           }
82108
82109           return h;
82110         } // get one coordinate from a coordinate array, if any
82111
82112
82113         function coord1(v) {
82114           return v.replace(removeSpace, "").split(",").map(parseFloat);
82115         } // get all coordinates from a coordinate array as [[],[]]
82116
82117
82118         function coord(v) {
82119           return v.replace(trimSpace, "").split(splitSpace).map(coord1);
82120         }
82121
82122         function xml2str(node) {
82123           if (node.xml !== undefined) return node.xml;
82124
82125           if (node.tagName) {
82126             var output = node.tagName;
82127
82128             for (var i = 0; i < node.attributes.length; i++) {
82129               output += node.attributes[i].name + node.attributes[i].value;
82130             }
82131
82132             for (var _i9 = 0; _i9 < node.childNodes.length; _i9++) {
82133               output += xml2str(node.childNodes[_i9]);
82134             }
82135
82136             return output;
82137           }
82138
82139           if (node.nodeName === "#text") {
82140             return (node.nodeValue || node.value || "").trim();
82141           }
82142
82143           if (node.nodeName === "#cdata-section") {
82144             return node.nodeValue;
82145           }
82146
82147           return "";
82148         }
82149
82150         var geotypes = ["Polygon", "LineString", "Point", "Track", "gx:Track"];
82151
82152         function kmlColor(properties, elem, prefix) {
82153           var v = nodeVal(get1(elem, "color")) || "";
82154           var colorProp = prefix == "stroke" || prefix === "fill" ? prefix : prefix + "-color";
82155
82156           if (v.substr(0, 1) === "#") {
82157             v = v.substr(1);
82158           }
82159
82160           if (v.length === 6 || v.length === 3) {
82161             properties[colorProp] = v;
82162           } else if (v.length === 8) {
82163             properties[prefix + "-opacity"] = parseInt(v.substr(0, 2), 16) / 255;
82164             properties[colorProp] = "#" + v.substr(6, 2) + v.substr(4, 2) + v.substr(2, 2);
82165           }
82166         }
82167
82168         function numericProperty(properties, elem, source, target) {
82169           var val = parseFloat(nodeVal(get1(elem, source)));
82170           if (!isNaN(val)) properties[target] = val;
82171         }
82172
82173         function gxCoords(root) {
82174           var elems = root.getElementsByTagName("coord");
82175           var coords = [];
82176           var times = [];
82177           if (elems.length === 0) elems = root.getElementsByTagName("gx:coord");
82178
82179           for (var i = 0; i < elems.length; i++) {
82180             coords.push(nodeVal(elems[i]).split(" ").map(parseFloat));
82181           }
82182
82183           var timeElems = root.getElementsByTagName("when");
82184
82185           for (var j = 0; j < timeElems.length; j++) {
82186             times.push(nodeVal(timeElems[j]));
82187           }
82188
82189           return {
82190             coords: coords,
82191             times: times
82192           };
82193         }
82194
82195         function getGeometry(root) {
82196           var geomNode;
82197           var geomNodes;
82198           var i;
82199           var j;
82200           var k;
82201           var geoms = [];
82202           var coordTimes = [];
82203
82204           if (get1(root, "MultiGeometry")) {
82205             return getGeometry(get1(root, "MultiGeometry"));
82206           }
82207
82208           if (get1(root, "MultiTrack")) {
82209             return getGeometry(get1(root, "MultiTrack"));
82210           }
82211
82212           if (get1(root, "gx:MultiTrack")) {
82213             return getGeometry(get1(root, "gx:MultiTrack"));
82214           }
82215
82216           for (i = 0; i < geotypes.length; i++) {
82217             geomNodes = root.getElementsByTagName(geotypes[i]);
82218
82219             if (geomNodes) {
82220               for (j = 0; j < geomNodes.length; j++) {
82221                 geomNode = geomNodes[j];
82222
82223                 if (geotypes[i] === "Point") {
82224                   geoms.push({
82225                     type: "Point",
82226                     coordinates: coord1(nodeVal(get1(geomNode, "coordinates")))
82227                   });
82228                 } else if (geotypes[i] === "LineString") {
82229                   geoms.push({
82230                     type: "LineString",
82231                     coordinates: coord(nodeVal(get1(geomNode, "coordinates")))
82232                   });
82233                 } else if (geotypes[i] === "Polygon") {
82234                   var rings = geomNode.getElementsByTagName("LinearRing"),
82235                       coords = [];
82236
82237                   for (k = 0; k < rings.length; k++) {
82238                     coords.push(coord(nodeVal(get1(rings[k], "coordinates"))));
82239                   }
82240
82241                   geoms.push({
82242                     type: "Polygon",
82243                     coordinates: coords
82244                   });
82245                 } else if (geotypes[i] === "Track" || geotypes[i] === "gx:Track") {
82246                   var track = gxCoords(geomNode);
82247                   geoms.push({
82248                     type: "LineString",
82249                     coordinates: track.coords
82250                   });
82251                   if (track.times.length) coordTimes.push(track.times);
82252                 }
82253               }
82254             }
82255           }
82256
82257           return {
82258             geoms: geoms,
82259             coordTimes: coordTimes
82260           };
82261         }
82262
82263         function getPlacemark(root, styleIndex, styleMapIndex, styleByHash) {
82264           var geomsAndTimes = getGeometry(root);
82265           var i;
82266           var properties = {};
82267           var name = nodeVal(get1(root, "name"));
82268           var address = nodeVal(get1(root, "address"));
82269           var styleUrl = nodeVal(get1(root, "styleUrl"));
82270           var description = nodeVal(get1(root, "description"));
82271           var timeSpan = get1(root, "TimeSpan");
82272           var timeStamp = get1(root, "TimeStamp");
82273           var extendedData = get1(root, "ExtendedData");
82274           var iconStyle = get1(root, "IconStyle");
82275           var labelStyle = get1(root, "LabelStyle");
82276           var lineStyle = get1(root, "LineStyle");
82277           var polyStyle = get1(root, "PolyStyle");
82278           var visibility = get1(root, "visibility");
82279           if (name) properties.name = name;
82280           if (address) properties.address = address;
82281
82282           if (styleUrl) {
82283             if (styleUrl[0] !== "#") {
82284               styleUrl = "#" + styleUrl;
82285             }
82286
82287             properties.styleUrl = styleUrl;
82288
82289             if (styleIndex[styleUrl]) {
82290               properties.styleHash = styleIndex[styleUrl];
82291             }
82292
82293             if (styleMapIndex[styleUrl]) {
82294               properties.styleMapHash = styleMapIndex[styleUrl];
82295               properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
82296             } // Try to populate the lineStyle or polyStyle since we got the style hash
82297
82298
82299             var style = styleByHash[properties.styleHash];
82300
82301             if (style) {
82302               if (!iconStyle) iconStyle = get1(style, "IconStyle");
82303               if (!labelStyle) labelStyle = get1(style, "LabelStyle");
82304               if (!lineStyle) lineStyle = get1(style, "LineStyle");
82305               if (!polyStyle) polyStyle = get1(style, "PolyStyle");
82306             }
82307           }
82308
82309           if (description) properties.description = description;
82310
82311           if (timeSpan) {
82312             var begin = nodeVal(get1(timeSpan, "begin"));
82313             var end = nodeVal(get1(timeSpan, "end"));
82314             properties.timespan = {
82315               begin: begin,
82316               end: end
82317             };
82318           }
82319
82320           if (timeStamp) {
82321             properties.timestamp = nodeVal(get1(timeStamp, "when"));
82322           }
82323
82324           if (iconStyle) {
82325             kmlColor(properties, iconStyle, "icon");
82326             numericProperty(properties, iconStyle, "scale", "icon-scale");
82327             numericProperty(properties, iconStyle, "heading", "icon-heading");
82328             var hotspot = get1(iconStyle, "hotSpot");
82329
82330             if (hotspot) {
82331               var left = parseFloat(hotspot.getAttribute("x"));
82332               var top = parseFloat(hotspot.getAttribute("y"));
82333               if (!isNaN(left) && !isNaN(top)) properties["icon-offset"] = [left, top];
82334             }
82335
82336             var icon = get1(iconStyle, "Icon");
82337
82338             if (icon) {
82339               var href = nodeVal(get1(icon, "href"));
82340               if (href) properties.icon = href;
82341             }
82342           }
82343
82344           if (labelStyle) {
82345             kmlColor(properties, labelStyle, "label");
82346             numericProperty(properties, labelStyle, "scale", "label-scale");
82347           }
82348
82349           if (lineStyle) {
82350             kmlColor(properties, lineStyle, "stroke");
82351             numericProperty(properties, lineStyle, "width", "stroke-width");
82352           }
82353
82354           if (polyStyle) {
82355             kmlColor(properties, polyStyle, "fill");
82356             var fill = nodeVal(get1(polyStyle, "fill"));
82357             var outline = nodeVal(get1(polyStyle, "outline"));
82358             if (fill) properties["fill-opacity"] = fill === "1" ? properties["fill-opacity"] || 1 : 0;
82359             if (outline) properties["stroke-opacity"] = outline === "1" ? properties["stroke-opacity"] || 1 : 0;
82360           }
82361
82362           if (extendedData) {
82363             var datas = extendedData.getElementsByTagName("Data"),
82364                 simpleDatas = extendedData.getElementsByTagName("SimpleData");
82365
82366             for (i = 0; i < datas.length; i++) {
82367               properties[datas[i].getAttribute("name")] = nodeVal(get1(datas[i], "value"));
82368             }
82369
82370             for (i = 0; i < simpleDatas.length; i++) {
82371               properties[simpleDatas[i].getAttribute("name")] = nodeVal(simpleDatas[i]);
82372             }
82373           }
82374
82375           if (visibility) {
82376             properties.visibility = nodeVal(visibility);
82377           }
82378
82379           if (geomsAndTimes.coordTimes.length) {
82380             properties.coordinateProperties = {
82381               times: geomsAndTimes.coordTimes.length === 1 ? geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes
82382             };
82383           }
82384
82385           var feature = {
82386             type: "Feature",
82387             geometry: geomsAndTimes.geoms.length === 0 ? null : geomsAndTimes.geoms.length === 1 ? geomsAndTimes.geoms[0] : {
82388               type: "GeometryCollection",
82389               geometries: geomsAndTimes.geoms
82390             },
82391             properties: properties
82392           };
82393           if (root.getAttribute("id")) feature.id = root.getAttribute("id");
82394           return feature;
82395         }
82396
82397         function kmlGen(doc) {
82398           var styleIndex, styleByHash, styleMapIndex, placemarks, styles, styleMaps, k, hash, l, pairs, pairsMap, m, j, feature;
82399           return regeneratorRuntime.wrap(function kmlGen$(_context3) {
82400             while (1) {
82401               switch (_context3.prev = _context3.next) {
82402                 case 0:
82403                   // styleindex keeps track of hashed styles in order to match feature
82404                   styleIndex = {};
82405                   styleByHash = {}; // stylemapindex keeps track of style maps to expose in properties
82406
82407                   styleMapIndex = {}; // atomic geospatial types supported by KML - MultiGeometry is
82408                   // handled separately
82409                   // all root placemarks in the file
82410
82411                   placemarks = doc.getElementsByTagName("Placemark");
82412                   styles = doc.getElementsByTagName("Style");
82413                   styleMaps = doc.getElementsByTagName("StyleMap");
82414
82415                   for (k = 0; k < styles.length; k++) {
82416                     hash = okhash(xml2str(styles[k])).toString(16);
82417                     styleIndex["#" + styles[k].getAttribute("id")] = hash;
82418                     styleByHash[hash] = styles[k];
82419                   }
82420
82421                   for (l = 0; l < styleMaps.length; l++) {
82422                     styleIndex["#" + styleMaps[l].getAttribute("id")] = okhash(xml2str(styleMaps[l])).toString(16);
82423                     pairs = styleMaps[l].getElementsByTagName("Pair");
82424                     pairsMap = {};
82425
82426                     for (m = 0; m < pairs.length; m++) {
82427                       pairsMap[nodeVal(get1(pairs[m], "key"))] = nodeVal(get1(pairs[m], "styleUrl"));
82428                     }
82429
82430                     styleMapIndex["#" + styleMaps[l].getAttribute("id")] = pairsMap;
82431                   }
82432
82433                   j = 0;
82434
82435                 case 9:
82436                   if (!(j < placemarks.length)) {
82437                     _context3.next = 17;
82438                     break;
82439                   }
82440
82441                   feature = getPlacemark(placemarks[j], styleIndex, styleMapIndex, styleByHash);
82442
82443                   if (!feature) {
82444                     _context3.next = 14;
82445                     break;
82446                   }
82447
82448                   _context3.next = 14;
82449                   return feature;
82450
82451                 case 14:
82452                   j++;
82453                   _context3.next = 9;
82454                   break;
82455
82456                 case 17:
82457                 case "end":
82458                   return _context3.stop();
82459               }
82460             }
82461           }, _marked3);
82462         }
82463
82464         function kml(doc) {
82465           return {
82466             type: "FeatureCollection",
82467             features: Array.from(kmlGen(doc))
82468           };
82469         }
82470
82471         var _initialized = false;
82472         var _enabled = false;
82473
82474         var _geojson;
82475
82476         function svgData(projection, context, dispatch) {
82477           var throttledRedraw = throttle(function () {
82478             dispatch.call('change');
82479           }, 1000);
82480
82481           var _showLabels = true;
82482           var detected = utilDetect();
82483           var layer = select(null);
82484
82485           var _vtService;
82486
82487           var _fileList;
82488
82489           var _template;
82490
82491           var _src;
82492
82493           function init() {
82494             if (_initialized) return; // run once
82495
82496             _geojson = {};
82497             _enabled = true;
82498
82499             function over(d3_event) {
82500               d3_event.stopPropagation();
82501               d3_event.preventDefault();
82502               d3_event.dataTransfer.dropEffect = 'copy';
82503             }
82504
82505             context.container().attr('dropzone', 'copy').on('drop.svgData', function (d3_event) {
82506               d3_event.stopPropagation();
82507               d3_event.preventDefault();
82508               if (!detected.filedrop) return;
82509               drawData.fileList(d3_event.dataTransfer.files);
82510             }).on('dragenter.svgData', over).on('dragexit.svgData', over).on('dragover.svgData', over);
82511             _initialized = true;
82512           }
82513
82514           function getService() {
82515             if (services.vectorTile && !_vtService) {
82516               _vtService = services.vectorTile;
82517
82518               _vtService.event.on('loadedData', throttledRedraw);
82519             } else if (!services.vectorTile && _vtService) {
82520               _vtService = null;
82521             }
82522
82523             return _vtService;
82524           }
82525
82526           function showLayer() {
82527             layerOn();
82528             layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
82529               dispatch.call('change');
82530             });
82531           }
82532
82533           function hideLayer() {
82534             throttledRedraw.cancel();
82535             layer.transition().duration(250).style('opacity', 0).on('end', layerOff);
82536           }
82537
82538           function layerOn() {
82539             layer.style('display', 'block');
82540           }
82541
82542           function layerOff() {
82543             layer.selectAll('.viewfield-group').remove();
82544             layer.style('display', 'none');
82545           } // ensure that all geojson features in a collection have IDs
82546
82547
82548           function ensureIDs(gj) {
82549             if (!gj) return null;
82550
82551             if (gj.type === 'FeatureCollection') {
82552               for (var i = 0; i < gj.features.length; i++) {
82553                 ensureFeatureID(gj.features[i]);
82554               }
82555             } else {
82556               ensureFeatureID(gj);
82557             }
82558
82559             return gj;
82560           } // ensure that each single Feature object has a unique ID
82561
82562
82563           function ensureFeatureID(feature) {
82564             if (!feature) return;
82565             feature.__featurehash__ = utilHashcode(fastJsonStableStringify(feature));
82566             return feature;
82567           } // Prefer an array of Features instead of a FeatureCollection
82568
82569
82570           function getFeatures(gj) {
82571             if (!gj) return [];
82572
82573             if (gj.type === 'FeatureCollection') {
82574               return gj.features;
82575             } else {
82576               return [gj];
82577             }
82578           }
82579
82580           function featureKey(d) {
82581             return d.__featurehash__;
82582           }
82583
82584           function isPolygon(d) {
82585             return d.geometry.type === 'Polygon' || d.geometry.type === 'MultiPolygon';
82586           }
82587
82588           function clipPathID(d) {
82589             return 'ideditor-data-' + d.__featurehash__ + '-clippath';
82590           }
82591
82592           function featureClasses(d) {
82593             return ['data' + d.__featurehash__, d.geometry.type, isPolygon(d) ? 'area' : '', d.__layerID__ || ''].filter(Boolean).join(' ');
82594           }
82595
82596           function drawData(selection) {
82597             var vtService = getService();
82598             var getPath = svgPath(projection).geojson;
82599             var getAreaPath = svgPath(projection, null, true).geojson;
82600             var hasData = drawData.hasData();
82601             layer = selection.selectAll('.layer-mapdata').data(_enabled && hasData ? [0] : []);
82602             layer.exit().remove();
82603             layer = layer.enter().append('g').attr('class', 'layer-mapdata').merge(layer);
82604             var surface = context.surface();
82605             if (!surface || surface.empty()) return; // not ready to draw yet, starting up
82606             // Gather data
82607
82608             var geoData, polygonData;
82609
82610             if (_template && vtService) {
82611               // fetch data from vector tile service
82612               var sourceID = _template;
82613               vtService.loadTiles(sourceID, _template, projection);
82614               geoData = vtService.data(sourceID, projection);
82615             } else {
82616               geoData = getFeatures(_geojson);
82617             }
82618
82619             geoData = geoData.filter(getPath);
82620             polygonData = geoData.filter(isPolygon); // Draw clip paths for polygons
82621
82622             var clipPaths = surface.selectAll('defs').selectAll('.clipPath-data').data(polygonData, featureKey);
82623             clipPaths.exit().remove();
82624             var clipPathsEnter = clipPaths.enter().append('clipPath').attr('class', 'clipPath-data').attr('id', clipPathID);
82625             clipPathsEnter.append('path');
82626             clipPaths.merge(clipPathsEnter).selectAll('path').attr('d', getAreaPath); // Draw fill, shadow, stroke layers
82627
82628             var datagroups = layer.selectAll('g.datagroup').data(['fill', 'shadow', 'stroke']);
82629             datagroups = datagroups.enter().append('g').attr('class', function (d) {
82630               return 'datagroup datagroup-' + d;
82631             }).merge(datagroups); // Draw paths
82632
82633             var pathData = {
82634               fill: polygonData,
82635               shadow: geoData,
82636               stroke: geoData
82637             };
82638             var paths = datagroups.selectAll('path').data(function (layer) {
82639               return pathData[layer];
82640             }, featureKey); // exit
82641
82642             paths.exit().remove(); // enter/update
82643
82644             paths = paths.enter().append('path').attr('class', function (d) {
82645               var datagroup = this.parentNode.__data__;
82646               return 'pathdata ' + datagroup + ' ' + featureClasses(d);
82647             }).attr('clip-path', function (d) {
82648               var datagroup = this.parentNode.__data__;
82649               return datagroup === 'fill' ? 'url(#' + clipPathID(d) + ')' : null;
82650             }).merge(paths).attr('d', function (d) {
82651               var datagroup = this.parentNode.__data__;
82652               return datagroup === 'fill' ? getAreaPath(d) : getPath(d);
82653             }); // Draw labels
82654
82655             layer.call(drawLabels, 'label-halo', geoData).call(drawLabels, 'label', geoData);
82656
82657             function drawLabels(selection, textClass, data) {
82658               var labelPath = d3_geoPath(projection);
82659               var labelData = data.filter(function (d) {
82660                 return _showLabels && d.properties && (d.properties.desc || d.properties.name);
82661               });
82662               var labels = selection.selectAll('text.' + textClass).data(labelData, featureKey); // exit
82663
82664               labels.exit().remove(); // enter/update
82665
82666               labels = labels.enter().append('text').attr('class', function (d) {
82667                 return textClass + ' ' + featureClasses(d);
82668               }).merge(labels).text(function (d) {
82669                 return d.properties.desc || d.properties.name;
82670               }).attr('x', function (d) {
82671                 var centroid = labelPath.centroid(d);
82672                 return centroid[0] + 11;
82673               }).attr('y', function (d) {
82674                 var centroid = labelPath.centroid(d);
82675                 return centroid[1];
82676               });
82677             }
82678           }
82679
82680           function getExtension(fileName) {
82681             if (!fileName) return;
82682             var re = /\.(gpx|kml|(geo)?json)$/i;
82683             var match = fileName.toLowerCase().match(re);
82684             return match && match.length && match[0];
82685           }
82686
82687           function xmlToDom(textdata) {
82688             return new DOMParser().parseFromString(textdata, 'text/xml');
82689           }
82690
82691           function stringifyGeojsonProperties(feature) {
82692             var properties = feature.properties;
82693
82694             for (var key in properties) {
82695               var property = properties[key];
82696
82697               if (typeof property === 'number' || typeof property === 'boolean' || Array.isArray(property)) {
82698                 properties[key] = property.toString();
82699               } else if (property === null) {
82700                 properties[key] = 'null';
82701               } else if (_typeof(property) === 'object') {
82702                 properties[key] = JSON.stringify(property);
82703               }
82704             }
82705           }
82706
82707           drawData.setFile = function (extension, data) {
82708             _template = null;
82709             _fileList = null;
82710             _geojson = null;
82711             _src = null;
82712             var gj;
82713
82714             switch (extension) {
82715               case '.gpx':
82716                 gj = gpx(xmlToDom(data));
82717                 break;
82718
82719               case '.kml':
82720                 gj = kml(xmlToDom(data));
82721                 break;
82722
82723               case '.geojson':
82724               case '.json':
82725                 gj = JSON.parse(data);
82726
82727                 if (gj.type === 'FeatureCollection') {
82728                   gj.features.forEach(stringifyGeojsonProperties);
82729                 } else if (gj.type === 'Feature') {
82730                   stringifyGeojsonProperties(gj);
82731                 }
82732
82733                 break;
82734             }
82735
82736             gj = gj || {};
82737
82738             if (Object.keys(gj).length) {
82739               _geojson = ensureIDs(gj);
82740               _src = extension + ' data file';
82741               this.fitZoom();
82742             }
82743
82744             dispatch.call('change');
82745             return this;
82746           };
82747
82748           drawData.showLabels = function (val) {
82749             if (!arguments.length) return _showLabels;
82750             _showLabels = val;
82751             return this;
82752           };
82753
82754           drawData.enabled = function (val) {
82755             if (!arguments.length) return _enabled;
82756             _enabled = val;
82757
82758             if (_enabled) {
82759               showLayer();
82760             } else {
82761               hideLayer();
82762             }
82763
82764             dispatch.call('change');
82765             return this;
82766           };
82767
82768           drawData.hasData = function () {
82769             var gj = _geojson || {};
82770             return !!(_template || Object.keys(gj).length);
82771           };
82772
82773           drawData.template = function (val, src) {
82774             if (!arguments.length) return _template; // test source against OSM imagery blocklists..
82775
82776             var osm = context.connection();
82777
82778             if (osm) {
82779               var blocklists = osm.imageryBlocklists();
82780               var fail = false;
82781               var tested = 0;
82782               var regex;
82783
82784               for (var i = 0; i < blocklists.length; i++) {
82785                 regex = blocklists[i];
82786                 fail = regex.test(val);
82787                 tested++;
82788                 if (fail) break;
82789               } // ensure at least one test was run.
82790
82791
82792               if (!tested) {
82793                 regex = /.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/;
82794                 fail = regex.test(val);
82795               }
82796             }
82797
82798             _template = val;
82799             _fileList = null;
82800             _geojson = null; // strip off the querystring/hash from the template,
82801             // it often includes the access token
82802
82803             _src = src || 'vectortile:' + val.split(/[?#]/)[0];
82804             dispatch.call('change');
82805             return this;
82806           };
82807
82808           drawData.geojson = function (gj, src) {
82809             if (!arguments.length) return _geojson;
82810             _template = null;
82811             _fileList = null;
82812             _geojson = null;
82813             _src = null;
82814             gj = gj || {};
82815
82816             if (Object.keys(gj).length) {
82817               _geojson = ensureIDs(gj);
82818               _src = src || 'unknown.geojson';
82819             }
82820
82821             dispatch.call('change');
82822             return this;
82823           };
82824
82825           drawData.fileList = function (fileList) {
82826             if (!arguments.length) return _fileList;
82827             _template = null;
82828             _fileList = fileList;
82829             _geojson = null;
82830             _src = null;
82831             if (!fileList || !fileList.length) return this;
82832             var f = fileList[0];
82833             var extension = getExtension(f.name);
82834             var reader = new FileReader();
82835
82836             reader.onload = function () {
82837               return function (e) {
82838                 drawData.setFile(extension, e.target.result);
82839               };
82840             }();
82841
82842             reader.readAsText(f);
82843             return this;
82844           };
82845
82846           drawData.url = function (url, defaultExtension) {
82847             _template = null;
82848             _fileList = null;
82849             _geojson = null;
82850             _src = null; // strip off any querystring/hash from the url before checking extension
82851
82852             var testUrl = url.split(/[?#]/)[0];
82853             var extension = getExtension(testUrl) || defaultExtension;
82854
82855             if (extension) {
82856               _template = null;
82857               d3_text(url).then(function (data) {
82858                 drawData.setFile(extension, data);
82859               })["catch"](function () {
82860                 /* ignore */
82861               });
82862             } else {
82863               drawData.template(url);
82864             }
82865
82866             return this;
82867           };
82868
82869           drawData.getSrc = function () {
82870             return _src || '';
82871           };
82872
82873           drawData.fitZoom = function () {
82874             var features = getFeatures(_geojson);
82875             if (!features.length) return;
82876             var map = context.map();
82877             var viewport = map.trimmedExtent().polygon();
82878             var coords = features.reduce(function (coords, feature) {
82879               var geom = feature.geometry;
82880               if (!geom) return coords;
82881               var c = geom.coordinates;
82882               /* eslint-disable no-fallthrough */
82883
82884               switch (geom.type) {
82885                 case 'Point':
82886                   c = [c];
82887
82888                 case 'MultiPoint':
82889                 case 'LineString':
82890                   break;
82891
82892                 case 'MultiPolygon':
82893                   c = utilArrayFlatten(c);
82894
82895                 case 'Polygon':
82896                 case 'MultiLineString':
82897                   c = utilArrayFlatten(c);
82898                   break;
82899               }
82900               /* eslint-enable no-fallthrough */
82901
82902
82903               return utilArrayUnion(coords, c);
82904             }, []);
82905
82906             if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
82907               var extent = geoExtent(d3_geoBounds({
82908                 type: 'LineString',
82909                 coordinates: coords
82910               }));
82911               map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
82912             }
82913
82914             return this;
82915           };
82916
82917           init();
82918           return drawData;
82919         }
82920
82921         function svgDebug(projection, context) {
82922           function drawDebug(selection) {
82923             var showTile = context.getDebug('tile');
82924             var showCollision = context.getDebug('collision');
82925             var showImagery = context.getDebug('imagery');
82926             var showTouchTargets = context.getDebug('target');
82927             var showDownloaded = context.getDebug('downloaded');
82928             var debugData = [];
82929
82930             if (showTile) {
82931               debugData.push({
82932                 "class": 'red',
82933                 label: 'tile'
82934               });
82935             }
82936
82937             if (showCollision) {
82938               debugData.push({
82939                 "class": 'yellow',
82940                 label: 'collision'
82941               });
82942             }
82943
82944             if (showImagery) {
82945               debugData.push({
82946                 "class": 'orange',
82947                 label: 'imagery'
82948               });
82949             }
82950
82951             if (showTouchTargets) {
82952               debugData.push({
82953                 "class": 'pink',
82954                 label: 'touchTargets'
82955               });
82956             }
82957
82958             if (showDownloaded) {
82959               debugData.push({
82960                 "class": 'purple',
82961                 label: 'downloaded'
82962               });
82963             }
82964
82965             var legend = context.container().select('.main-content').selectAll('.debug-legend').data(debugData.length ? [0] : []);
82966             legend.exit().remove();
82967             legend = legend.enter().append('div').attr('class', 'fillD debug-legend').merge(legend);
82968             var legendItems = legend.selectAll('.debug-legend-item').data(debugData, function (d) {
82969               return d.label;
82970             });
82971             legendItems.exit().remove();
82972             legendItems.enter().append('span').attr('class', function (d) {
82973               return "debug-legend-item ".concat(d["class"]);
82974             }).text(function (d) {
82975               return d.label;
82976             });
82977             var layer = selection.selectAll('.layer-debug').data(showImagery || showDownloaded ? [0] : []);
82978             layer.exit().remove();
82979             layer = layer.enter().append('g').attr('class', 'layer-debug').merge(layer); // imagery
82980
82981             var extent = context.map().extent();
82982             _mainFileFetcher.get('imagery').then(function (d) {
82983               var hits = showImagery && d.query.bbox(extent.rectangle(), true) || [];
82984               var features = hits.map(function (d) {
82985                 return d.features[d.id];
82986               });
82987               var imagery = layer.selectAll('path.debug-imagery').data(features);
82988               imagery.exit().remove();
82989               imagery.enter().append('path').attr('class', 'debug-imagery debug orange');
82990             })["catch"](function () {
82991               /* ignore */
82992             }); // downloaded
82993
82994             var osm = context.connection();
82995             var dataDownloaded = [];
82996
82997             if (osm && showDownloaded) {
82998               var rtree = osm.caches('get').tile.rtree;
82999               dataDownloaded = rtree.all().map(function (bbox) {
83000                 return {
83001                   type: 'Feature',
83002                   properties: {
83003                     id: bbox.id
83004                   },
83005                   geometry: {
83006                     type: 'Polygon',
83007                     coordinates: [[[bbox.minX, bbox.minY], [bbox.minX, bbox.maxY], [bbox.maxX, bbox.maxY], [bbox.maxX, bbox.minY], [bbox.minX, bbox.minY]]]
83008                   }
83009                 };
83010               });
83011             }
83012
83013             var downloaded = layer.selectAll('path.debug-downloaded').data(showDownloaded ? dataDownloaded : []);
83014             downloaded.exit().remove();
83015             downloaded.enter().append('path').attr('class', 'debug-downloaded debug purple'); // update
83016
83017             layer.selectAll('path').attr('d', svgPath(projection).geojson);
83018           } // This looks strange because `enabled` methods on other layers are
83019           // chainable getter/setters, and this one is just a getter.
83020
83021
83022           drawDebug.enabled = function () {
83023             if (!arguments.length) {
83024               return context.getDebug('tile') || context.getDebug('collision') || context.getDebug('imagery') || context.getDebug('target') || context.getDebug('downloaded');
83025             } else {
83026               return this;
83027             }
83028           };
83029
83030           return drawDebug;
83031         }
83032
83033         /*
83034             A standalone SVG element that contains only a `defs` sub-element. To be
83035             used once globally, since defs IDs must be unique within a document.
83036         */
83037
83038         function svgDefs(context) {
83039           var _defsSelection = select(null);
83040
83041           var _spritesheetIds = ['iD-sprite', 'maki-sprite', 'temaki-sprite', 'fa-sprite', 'community-sprite'];
83042
83043           function drawDefs(selection) {
83044             _defsSelection = selection.append('defs'); // add markers
83045
83046             _defsSelection.append('marker').attr('id', 'ideditor-oneway-marker').attr('viewBox', '0 0 10 5').attr('refX', 2.5).attr('refY', 2.5).attr('markerWidth', 2).attr('markerHeight', 2).attr('markerUnits', 'strokeWidth').attr('orient', 'auto').append('path').attr('class', 'oneway-marker-path').attr('d', 'M 5,3 L 0,3 L 0,2 L 5,2 L 5,0 L 10,2.5 L 5,5 z').attr('stroke', 'none').attr('fill', '#000').attr('opacity', '0.75'); // SVG markers have to be given a colour where they're defined
83047             // (they can't inherit it from the line they're attached to),
83048             // so we need to manually define markers for each color of tag
83049             // (also, it's slightly nicer if we can control the
83050             // positioning for different tags)
83051
83052
83053             function addSidedMarker(name, color, offset) {
83054               _defsSelection.append('marker').attr('id', 'ideditor-sided-marker-' + name).attr('viewBox', '0 0 2 2').attr('refX', 1).attr('refY', -offset).attr('markerWidth', 1.5).attr('markerHeight', 1.5).attr('markerUnits', 'strokeWidth').attr('orient', 'auto').append('path').attr('class', 'sided-marker-path sided-marker-' + name + '-path').attr('d', 'M 0,0 L 1,1 L 2,0 z').attr('stroke', 'none').attr('fill', color);
83055             }
83056
83057             addSidedMarker('natural', 'rgb(170, 170, 170)', 0); // for a coastline, the arrows are (somewhat unintuitively) on
83058             // the water side, so let's color them blue (with a gap) to
83059             // give a stronger indication
83060
83061             addSidedMarker('coastline', '#77dede', 1);
83062             addSidedMarker('waterway', '#77dede', 1); // barriers have a dashed line, and separating the triangle
83063             // from the line visually suits that
83064
83065             addSidedMarker('barrier', '#ddd', 1);
83066             addSidedMarker('man_made', '#fff', 0);
83067
83068             _defsSelection.append('marker').attr('id', 'ideditor-viewfield-marker').attr('viewBox', '0 0 16 16').attr('refX', 8).attr('refY', 16).attr('markerWidth', 4).attr('markerHeight', 4).attr('markerUnits', 'strokeWidth').attr('orient', 'auto').append('path').attr('class', 'viewfield-marker-path').attr('d', 'M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z').attr('fill', '#333').attr('fill-opacity', '0.75').attr('stroke', '#fff').attr('stroke-width', '0.5px').attr('stroke-opacity', '0.75');
83069
83070             _defsSelection.append('marker').attr('id', 'ideditor-viewfield-marker-wireframe').attr('viewBox', '0 0 16 16').attr('refX', 8).attr('refY', 16).attr('markerWidth', 4).attr('markerHeight', 4).attr('markerUnits', 'strokeWidth').attr('orient', 'auto').append('path').attr('class', 'viewfield-marker-path').attr('d', 'M 6,14 C 8,13.4 8,13.4 10,14 L 16,3 C 12,0 4,0 0,3 z').attr('fill', 'none').attr('stroke', '#fff').attr('stroke-width', '0.5px').attr('stroke-opacity', '0.75'); // add patterns
83071
83072
83073             var patterns = _defsSelection.selectAll('pattern').data([// pattern name, pattern image name
83074             ['beach', 'dots'], ['construction', 'construction'], ['cemetery', 'cemetery'], ['cemetery_christian', 'cemetery_christian'], ['cemetery_buddhist', 'cemetery_buddhist'], ['cemetery_muslim', 'cemetery_muslim'], ['cemetery_jewish', 'cemetery_jewish'], ['farmland', 'farmland'], ['farmyard', 'farmyard'], ['forest', 'forest'], ['forest_broadleaved', 'forest_broadleaved'], ['forest_needleleaved', 'forest_needleleaved'], ['forest_leafless', 'forest_leafless'], ['golf_green', 'grass'], ['grass', 'grass'], ['landfill', 'landfill'], ['meadow', 'grass'], ['orchard', 'orchard'], ['pond', 'pond'], ['quarry', 'quarry'], ['scrub', 'bushes'], ['vineyard', 'vineyard'], ['water_standing', 'lines'], ['waves', 'waves'], ['wetland', 'wetland'], ['wetland_marsh', 'wetland_marsh'], ['wetland_swamp', 'wetland_swamp'], ['wetland_bog', 'wetland_bog'], ['wetland_reedbed', 'wetland_reedbed']]).enter().append('pattern').attr('id', function (d) {
83075               return 'ideditor-pattern-' + d[0];
83076             }).attr('width', 32).attr('height', 32).attr('patternUnits', 'userSpaceOnUse');
83077
83078             patterns.append('rect').attr('x', 0).attr('y', 0).attr('width', 32).attr('height', 32).attr('class', function (d) {
83079               return 'pattern-color-' + d[0];
83080             });
83081             patterns.append('image').attr('x', 0).attr('y', 0).attr('width', 32).attr('height', 32).attr('xlink:href', function (d) {
83082               return context.imagePath('pattern/' + d[1] + '.png');
83083             }); // add clip paths
83084
83085             _defsSelection.selectAll('clipPath').data([12, 18, 20, 32, 45]).enter().append('clipPath').attr('id', function (d) {
83086               return 'ideditor-clip-square-' + d;
83087             }).append('rect').attr('x', 0).attr('y', 0).attr('width', function (d) {
83088               return d;
83089             }).attr('height', function (d) {
83090               return d;
83091             }); // add symbol spritesheets
83092
83093
83094             addSprites(_spritesheetIds, true);
83095           }
83096
83097           function addSprites(ids, overrideColors) {
83098             _spritesheetIds = utilArrayUniq(_spritesheetIds.concat(ids));
83099
83100             var spritesheets = _defsSelection.selectAll('.spritesheet').data(_spritesheetIds);
83101
83102             spritesheets.enter().append('g').attr('class', function (d) {
83103               return 'spritesheet spritesheet-' + d;
83104             }).each(function (d) {
83105               var url = context.imagePath(d + '.svg');
83106               var node = select(this).node();
83107               svg(url).then(function (svg) {
83108                 node.appendChild(select(svg.documentElement).attr('id', 'ideditor-' + d).node());
83109
83110                 if (overrideColors && d !== 'iD-sprite') {
83111                   // allow icon colors to be overridden..
83112                   select(node).selectAll('path').attr('fill', 'currentColor');
83113                 }
83114               })["catch"](function () {
83115                 /* ignore */
83116               });
83117             });
83118             spritesheets.exit().remove();
83119           }
83120
83121           drawDefs.addSprites = addSprites;
83122           return drawDefs;
83123         }
83124
83125         var _layerEnabled$2 = false;
83126
83127         var _qaService$2;
83128
83129         function svgKeepRight(projection, context, dispatch) {
83130           var throttledRedraw = throttle(function () {
83131             return dispatch.call('change');
83132           }, 1000);
83133
83134           var minZoom = 12;
83135           var touchLayer = select(null);
83136           var drawLayer = select(null);
83137           var layerVisible = false;
83138
83139           function markerPath(selection, klass) {
83140             selection.attr('class', klass).attr('transform', 'translate(-4, -24)').attr('d', 'M11.6,6.2H7.1l1.4-5.1C8.6,0.6,8.1,0,7.5,0H2.2C1.7,0,1.3,0.3,1.3,0.8L0,10.2c-0.1,0.6,0.4,1.1,0.9,1.1h4.6l-1.8,7.6C3.6,19.4,4.1,20,4.7,20c0.3,0,0.6-0.2,0.8-0.5l6.9-11.9C12.7,7,12.3,6.2,11.6,6.2z');
83141           } // Loosely-coupled keepRight service for fetching issues.
83142
83143
83144           function getService() {
83145             if (services.keepRight && !_qaService$2) {
83146               _qaService$2 = services.keepRight;
83147
83148               _qaService$2.on('loaded', throttledRedraw);
83149             } else if (!services.keepRight && _qaService$2) {
83150               _qaService$2 = null;
83151             }
83152
83153             return _qaService$2;
83154           } // Show the markers
83155
83156
83157           function editOn() {
83158             if (!layerVisible) {
83159               layerVisible = true;
83160               drawLayer.style('display', 'block');
83161             }
83162           } // Immediately remove the markers and their touch targets
83163
83164
83165           function editOff() {
83166             if (layerVisible) {
83167               layerVisible = false;
83168               drawLayer.style('display', 'none');
83169               drawLayer.selectAll('.qaItem.keepRight').remove();
83170               touchLayer.selectAll('.qaItem.keepRight').remove();
83171             }
83172           } // Enable the layer.  This shows the markers and transitions them to visible.
83173
83174
83175           function layerOn() {
83176             editOn();
83177             drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
83178               return dispatch.call('change');
83179             });
83180           } // Disable the layer.  This transitions the layer invisible and then hides the markers.
83181
83182
83183           function layerOff() {
83184             throttledRedraw.cancel();
83185             drawLayer.interrupt();
83186             touchLayer.selectAll('.qaItem.keepRight').remove();
83187             drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
83188               editOff();
83189               dispatch.call('change');
83190             });
83191           } // Update the issue markers
83192
83193
83194           function updateMarkers() {
83195             if (!layerVisible || !_layerEnabled$2) return;
83196             var service = getService();
83197             var selectedID = context.selectedErrorID();
83198             var data = service ? service.getItems(projection) : [];
83199             var getTransform = svgPointTransform(projection); // Draw markers..
83200
83201             var markers = drawLayer.selectAll('.qaItem.keepRight').data(data, function (d) {
83202               return d.id;
83203             }); // exit
83204
83205             markers.exit().remove(); // enter
83206
83207             var markersEnter = markers.enter().append('g').attr('class', function (d) {
83208               return "qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.parentIssueType);
83209             });
83210             markersEnter.append('ellipse').attr('cx', 0.5).attr('cy', 1).attr('rx', 6.5).attr('ry', 3).attr('class', 'stroke');
83211             markersEnter.append('path').call(markerPath, 'shadow');
83212             markersEnter.append('use').attr('class', 'qaItem-fill').attr('width', '20px').attr('height', '20px').attr('x', '-8px').attr('y', '-22px').attr('xlink:href', '#iD-icon-bolt'); // update
83213
83214             markers.merge(markersEnter).sort(sortY).classed('selected', function (d) {
83215               return d.id === selectedID;
83216             }).attr('transform', getTransform); // Draw targets..
83217
83218             if (touchLayer.empty()) return;
83219             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
83220             var targets = touchLayer.selectAll('.qaItem.keepRight').data(data, function (d) {
83221               return d.id;
83222             }); // exit
83223
83224             targets.exit().remove(); // enter/update
83225
83226             targets.enter().append('rect').attr('width', '20px').attr('height', '20px').attr('x', '-8px').attr('y', '-22px').merge(targets).sort(sortY).attr('class', function (d) {
83227               return "qaItem ".concat(d.service, " target ").concat(fillClass, " itemId-").concat(d.id);
83228             }).attr('transform', getTransform);
83229
83230             function sortY(a, b) {
83231               return a.id === selectedID ? 1 : b.id === selectedID ? -1 : a.severity === 'error' && b.severity !== 'error' ? 1 : b.severity === 'error' && a.severity !== 'error' ? -1 : b.loc[1] - a.loc[1];
83232             }
83233           } // Draw the keepRight layer and schedule loading issues and updating markers.
83234
83235
83236           function drawKeepRight(selection) {
83237             var service = getService();
83238             var surface = context.surface();
83239
83240             if (surface && !surface.empty()) {
83241               touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
83242             }
83243
83244             drawLayer = selection.selectAll('.layer-keepRight').data(service ? [0] : []);
83245             drawLayer.exit().remove();
83246             drawLayer = drawLayer.enter().append('g').attr('class', 'layer-keepRight').style('display', _layerEnabled$2 ? 'block' : 'none').merge(drawLayer);
83247
83248             if (_layerEnabled$2) {
83249               if (service && ~~context.map().zoom() >= minZoom) {
83250                 editOn();
83251                 service.loadIssues(projection);
83252                 updateMarkers();
83253               } else {
83254                 editOff();
83255               }
83256             }
83257           } // Toggles the layer on and off
83258
83259
83260           drawKeepRight.enabled = function (val) {
83261             if (!arguments.length) return _layerEnabled$2;
83262             _layerEnabled$2 = val;
83263
83264             if (_layerEnabled$2) {
83265               layerOn();
83266             } else {
83267               layerOff();
83268
83269               if (context.selectedErrorID()) {
83270                 context.enter(modeBrowse(context));
83271               }
83272             }
83273
83274             dispatch.call('change');
83275             return this;
83276           };
83277
83278           drawKeepRight.supported = function () {
83279             return !!getService();
83280           };
83281
83282           return drawKeepRight;
83283         }
83284
83285         function svgGeolocate(projection) {
83286           var layer = select(null);
83287
83288           var _position;
83289
83290           function init() {
83291             if (svgGeolocate.initialized) return; // run once
83292
83293             svgGeolocate.enabled = false;
83294             svgGeolocate.initialized = true;
83295           }
83296
83297           function showLayer() {
83298             layer.style('display', 'block');
83299           }
83300
83301           function hideLayer() {
83302             layer.transition().duration(250).style('opacity', 0);
83303           }
83304
83305           function layerOn() {
83306             layer.style('opacity', 0).transition().duration(250).style('opacity', 1);
83307           }
83308
83309           function layerOff() {
83310             layer.style('display', 'none');
83311           }
83312
83313           function transform(d) {
83314             return svgPointTransform(projection)(d);
83315           }
83316
83317           function accuracy(accuracy, loc) {
83318             // converts accuracy to pixels...
83319             var degreesRadius = geoMetersToLat(accuracy),
83320                 tangentLoc = [loc[0], loc[1] + degreesRadius],
83321                 projectedTangent = projection(tangentLoc),
83322                 projectedLoc = projection([loc[0], loc[1]]); // southern most point will have higher pixel value...
83323
83324             return Math.round(projectedLoc[1] - projectedTangent[1]).toString();
83325           }
83326
83327           function update() {
83328             var geolocation = {
83329               loc: [_position.coords.longitude, _position.coords.latitude]
83330             };
83331             var groups = layer.selectAll('.geolocations').selectAll('.geolocation').data([geolocation]);
83332             groups.exit().remove();
83333             var pointsEnter = groups.enter().append('g').attr('class', 'geolocation');
83334             pointsEnter.append('circle').attr('class', 'geolocate-radius').attr('dx', '0').attr('dy', '0').attr('fill', 'rgb(15,128,225)').attr('fill-opacity', '0.3').attr('r', '0');
83335             pointsEnter.append('circle').attr('dx', '0').attr('dy', '0').attr('fill', 'rgb(15,128,225)').attr('stroke', 'white').attr('stroke-width', '1.5').attr('r', '6');
83336             groups.merge(pointsEnter).attr('transform', transform);
83337             layer.select('.geolocate-radius').attr('r', accuracy(_position.coords.accuracy, geolocation.loc));
83338           }
83339
83340           function drawLocation(selection) {
83341             var enabled = svgGeolocate.enabled;
83342             layer = selection.selectAll('.layer-geolocate').data([0]);
83343             layer.exit().remove();
83344             var layerEnter = layer.enter().append('g').attr('class', 'layer-geolocate').style('display', enabled ? 'block' : 'none');
83345             layerEnter.append('g').attr('class', 'geolocations');
83346             layer = layerEnter.merge(layer);
83347
83348             if (enabled) {
83349               update();
83350             } else {
83351               layerOff();
83352             }
83353           }
83354
83355           drawLocation.enabled = function (position, enabled) {
83356             if (!arguments.length) return svgGeolocate.enabled;
83357             _position = position;
83358             svgGeolocate.enabled = enabled;
83359
83360             if (svgGeolocate.enabled) {
83361               showLayer();
83362               layerOn();
83363             } else {
83364               hideLayer();
83365             }
83366
83367             return this;
83368           };
83369
83370           init();
83371           return drawLocation;
83372         }
83373
83374         function svgLabels(projection, context) {
83375           var path = d3_geoPath(projection);
83376           var detected = utilDetect();
83377           var baselineHack = detected.ie || detected.browser.toLowerCase() === 'edge' || detected.browser.toLowerCase() === 'firefox' && detected.version >= 70;
83378
83379           var _rdrawn = new RBush();
83380
83381           var _rskipped = new RBush();
83382
83383           var _textWidthCache = {};
83384           var _entitybboxes = {}; // Listed from highest to lowest priority
83385
83386           var labelStack = [['line', 'aeroway', '*', 12], ['line', 'highway', 'motorway', 12], ['line', 'highway', 'trunk', 12], ['line', 'highway', 'primary', 12], ['line', 'highway', 'secondary', 12], ['line', 'highway', 'tertiary', 12], ['line', 'highway', '*', 12], ['line', 'railway', '*', 12], ['line', 'waterway', '*', 12], ['area', 'aeroway', '*', 12], ['area', 'amenity', '*', 12], ['area', 'building', '*', 12], ['area', 'historic', '*', 12], ['area', 'leisure', '*', 12], ['area', 'man_made', '*', 12], ['area', 'natural', '*', 12], ['area', 'shop', '*', 12], ['area', 'tourism', '*', 12], ['area', 'camp_site', '*', 12], ['point', 'aeroway', '*', 10], ['point', 'amenity', '*', 10], ['point', 'building', '*', 10], ['point', 'historic', '*', 10], ['point', 'leisure', '*', 10], ['point', 'man_made', '*', 10], ['point', 'natural', '*', 10], ['point', 'shop', '*', 10], ['point', 'tourism', '*', 10], ['point', 'camp_site', '*', 10], ['line', 'name', '*', 12], ['area', 'name', '*', 12], ['point', 'name', '*', 10]];
83387
83388           function shouldSkipIcon(preset) {
83389             var noIcons = ['building', 'landuse', 'natural'];
83390             return noIcons.some(function (s) {
83391               return preset.id.indexOf(s) >= 0;
83392             });
83393           }
83394
83395           function get(array, prop) {
83396             return function (d, i) {
83397               return array[i][prop];
83398             };
83399           }
83400
83401           function textWidth(text, size, elem) {
83402             var c = _textWidthCache[size];
83403             if (!c) c = _textWidthCache[size] = {};
83404
83405             if (c[text]) {
83406               return c[text];
83407             } else if (elem) {
83408               c[text] = elem.getComputedTextLength();
83409               return c[text];
83410             } else {
83411               var str = encodeURIComponent(text).match(/%[CDEFcdef]/g);
83412
83413               if (str === null) {
83414                 return size / 3 * 2 * text.length;
83415               } else {
83416                 return size / 3 * (2 * text.length + str.length);
83417               }
83418             }
83419           }
83420
83421           function drawLinePaths(selection, entities, filter, classes, labels) {
83422             var paths = selection.selectAll('path').filter(filter).data(entities, osmEntity.key); // exit
83423
83424             paths.exit().remove(); // enter/update
83425
83426             paths.enter().append('path').style('stroke-width', get(labels, 'font-size')).attr('id', function (d) {
83427               return 'ideditor-labelpath-' + d.id;
83428             }).attr('class', classes).merge(paths).attr('d', get(labels, 'lineString'));
83429           }
83430
83431           function drawLineLabels(selection, entities, filter, classes, labels) {
83432             var texts = selection.selectAll('text.' + classes).filter(filter).data(entities, osmEntity.key); // exit
83433
83434             texts.exit().remove(); // enter
83435
83436             texts.enter().append('text').attr('class', function (d, i) {
83437               return classes + ' ' + labels[i].classes + ' ' + d.id;
83438             }).attr('dy', baselineHack ? '0.35em' : null).append('textPath').attr('class', 'textpath'); // update
83439
83440             selection.selectAll('text.' + classes).selectAll('.textpath').filter(filter).data(entities, osmEntity.key).attr('startOffset', '50%').attr('xlink:href', function (d) {
83441               return '#ideditor-labelpath-' + d.id;
83442             }).text(utilDisplayNameForPath);
83443           }
83444
83445           function drawPointLabels(selection, entities, filter, classes, labels) {
83446             var texts = selection.selectAll('text.' + classes).filter(filter).data(entities, osmEntity.key); // exit
83447
83448             texts.exit().remove(); // enter/update
83449
83450             texts.enter().append('text').attr('class', function (d, i) {
83451               return classes + ' ' + labels[i].classes + ' ' + d.id;
83452             }).merge(texts).attr('x', get(labels, 'x')).attr('y', get(labels, 'y')).style('text-anchor', get(labels, 'textAnchor')).text(utilDisplayName).each(function (d, i) {
83453               textWidth(utilDisplayName(d), labels[i].height, this);
83454             });
83455           }
83456
83457           function drawAreaLabels(selection, entities, filter, classes, labels) {
83458             entities = entities.filter(hasText);
83459             labels = labels.filter(hasText);
83460             drawPointLabels(selection, entities, filter, classes, labels);
83461
83462             function hasText(d, i) {
83463               return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
83464             }
83465           }
83466
83467           function drawAreaIcons(selection, entities, filter, classes, labels) {
83468             var icons = selection.selectAll('use.' + classes).filter(filter).data(entities, osmEntity.key); // exit
83469
83470             icons.exit().remove(); // enter/update
83471
83472             icons.enter().append('use').attr('class', 'icon ' + classes).attr('width', '17px').attr('height', '17px').merge(icons).attr('transform', get(labels, 'transform')).attr('xlink:href', function (d) {
83473               var preset = _mainPresetIndex.match(d, context.graph());
83474               var picon = preset && preset.icon;
83475
83476               if (!picon) {
83477                 return '';
83478               } else {
83479                 var isMaki = /^maki-/.test(picon);
83480                 return '#' + picon + (isMaki ? '-15' : '');
83481               }
83482             });
83483           }
83484
83485           function drawCollisionBoxes(selection, rtree, which) {
83486             var classes = 'debug ' + which + ' ' + (which === 'debug-skipped' ? 'orange' : 'yellow');
83487             var gj = [];
83488
83489             if (context.getDebug('collision')) {
83490               gj = rtree.all().map(function (d) {
83491                 return {
83492                   type: 'Polygon',
83493                   coordinates: [[[d.minX, d.minY], [d.maxX, d.minY], [d.maxX, d.maxY], [d.minX, d.maxY], [d.minX, d.minY]]]
83494                 };
83495               });
83496             }
83497
83498             var boxes = selection.selectAll('.' + which).data(gj); // exit
83499
83500             boxes.exit().remove(); // enter/update
83501
83502             boxes.enter().append('path').attr('class', classes).merge(boxes).attr('d', d3_geoPath());
83503           }
83504
83505           function drawLabels(selection, graph, entities, filter, dimensions, fullRedraw) {
83506             var wireframe = context.surface().classed('fill-wireframe');
83507             var zoom = geoScaleToZoom(projection.scale());
83508             var labelable = [];
83509             var renderNodeAs = {};
83510             var i, j, k, entity, geometry;
83511
83512             for (i = 0; i < labelStack.length; i++) {
83513               labelable.push([]);
83514             }
83515
83516             if (fullRedraw) {
83517               _rdrawn.clear();
83518
83519               _rskipped.clear();
83520
83521               _entitybboxes = {};
83522             } else {
83523               for (i = 0; i < entities.length; i++) {
83524                 entity = entities[i];
83525                 var toRemove = [].concat(_entitybboxes[entity.id] || []).concat(_entitybboxes[entity.id + 'I'] || []);
83526
83527                 for (j = 0; j < toRemove.length; j++) {
83528                   _rdrawn.remove(toRemove[j]);
83529
83530                   _rskipped.remove(toRemove[j]);
83531                 }
83532               }
83533             } // Loop through all the entities to do some preprocessing
83534
83535
83536             for (i = 0; i < entities.length; i++) {
83537               entity = entities[i];
83538               geometry = entity.geometry(graph); // Insert collision boxes around interesting points/vertices
83539
83540               if (geometry === 'point' || geometry === 'vertex' && isInterestingVertex(entity)) {
83541                 var hasDirections = entity.directions(graph, projection).length;
83542                 var markerPadding;
83543
83544                 if (!wireframe && geometry === 'point' && !(zoom >= 18 && hasDirections)) {
83545                   renderNodeAs[entity.id] = 'point';
83546                   markerPadding = 20; // extra y for marker height
83547                 } else {
83548                   renderNodeAs[entity.id] = 'vertex';
83549                   markerPadding = 0;
83550                 }
83551
83552                 var coord = projection(entity.loc);
83553                 var nodePadding = 10;
83554                 var bbox = {
83555                   minX: coord[0] - nodePadding,
83556                   minY: coord[1] - nodePadding - markerPadding,
83557                   maxX: coord[0] + nodePadding,
83558                   maxY: coord[1] + nodePadding
83559                 };
83560                 doInsert(bbox, entity.id + 'P');
83561               } // From here on, treat vertices like points
83562
83563
83564               if (geometry === 'vertex') {
83565                 geometry = 'point';
83566               } // Determine which entities are label-able
83567
83568
83569               var preset = geometry === 'area' && _mainPresetIndex.match(entity, graph);
83570               var icon = preset && !shouldSkipIcon(preset) && preset.icon;
83571               if (!icon && !utilDisplayName(entity)) continue;
83572
83573               for (k = 0; k < labelStack.length; k++) {
83574                 var matchGeom = labelStack[k][0];
83575                 var matchKey = labelStack[k][1];
83576                 var matchVal = labelStack[k][2];
83577                 var hasVal = entity.tags[matchKey];
83578
83579                 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
83580                   labelable[k].push(entity);
83581                   break;
83582                 }
83583               }
83584             }
83585
83586             var positions = {
83587               point: [],
83588               line: [],
83589               area: []
83590             };
83591             var labelled = {
83592               point: [],
83593               line: [],
83594               area: []
83595             }; // Try and find a valid label for labellable entities
83596
83597             for (k = 0; k < labelable.length; k++) {
83598               var fontSize = labelStack[k][3];
83599
83600               for (i = 0; i < labelable[k].length; i++) {
83601                 entity = labelable[k][i];
83602                 geometry = entity.geometry(graph);
83603                 var getName = geometry === 'line' ? utilDisplayNameForPath : utilDisplayName;
83604                 var name = getName(entity);
83605                 var width = name && textWidth(name, fontSize);
83606                 var p = null;
83607
83608                 if (geometry === 'point' || geometry === 'vertex') {
83609                   // no point or vertex labels in wireframe mode
83610                   // no vertex labels at low zooms (vertices have no icons)
83611                   if (wireframe) continue;
83612                   var renderAs = renderNodeAs[entity.id];
83613                   if (renderAs === 'vertex' && zoom < 17) continue;
83614                   p = getPointLabel(entity, width, fontSize, renderAs);
83615                 } else if (geometry === 'line') {
83616                   p = getLineLabel(entity, width, fontSize);
83617                 } else if (geometry === 'area') {
83618                   p = getAreaLabel(entity, width, fontSize);
83619                 }
83620
83621                 if (p) {
83622                   if (geometry === 'vertex') {
83623                     geometry = 'point';
83624                   } // treat vertex like point
83625
83626
83627                   p.classes = geometry + ' tag-' + labelStack[k][1];
83628                   positions[geometry].push(p);
83629                   labelled[geometry].push(entity);
83630                 }
83631               }
83632             }
83633
83634             function isInterestingVertex(entity) {
83635               var selectedIDs = context.selectedIDs();
83636               return entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph) || selectedIDs.indexOf(entity.id) !== -1 || graph.parentWays(entity).some(function (parent) {
83637                 return selectedIDs.indexOf(parent.id) !== -1;
83638               });
83639             }
83640
83641             function getPointLabel(entity, width, height, geometry) {
83642               var y = geometry === 'point' ? -12 : 0;
83643               var pointOffsets = {
83644                 ltr: [15, y, 'start'],
83645                 rtl: [-15, y, 'end']
83646               };
83647               var textDirection = _mainLocalizer.textDirection();
83648               var coord = projection(entity.loc);
83649               var textPadding = 2;
83650               var offset = pointOffsets[textDirection];
83651               var p = {
83652                 height: height,
83653                 width: width,
83654                 x: coord[0] + offset[0],
83655                 y: coord[1] + offset[1],
83656                 textAnchor: offset[2]
83657               }; // insert a collision box for the text label..
83658
83659               var bbox;
83660
83661               if (textDirection === 'rtl') {
83662                 bbox = {
83663                   minX: p.x - width - textPadding,
83664                   minY: p.y - height / 2 - textPadding,
83665                   maxX: p.x + textPadding,
83666                   maxY: p.y + height / 2 + textPadding
83667                 };
83668               } else {
83669                 bbox = {
83670                   minX: p.x - textPadding,
83671                   minY: p.y - height / 2 - textPadding,
83672                   maxX: p.x + width + textPadding,
83673                   maxY: p.y + height / 2 + textPadding
83674                 };
83675               }
83676
83677               if (tryInsert([bbox], entity.id, true)) {
83678                 return p;
83679               }
83680             }
83681
83682             function getLineLabel(entity, width, height) {
83683               var viewport = geoExtent(context.projection.clipExtent()).polygon();
83684               var points = graph.childNodes(entity).map(function (node) {
83685                 return projection(node.loc);
83686               });
83687               var length = geoPathLength(points);
83688               if (length < width + 20) return; // % along the line to attempt to place the label
83689
83690               var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70, 25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
83691               var padding = 3;
83692
83693               for (var i = 0; i < lineOffsets.length; i++) {
83694                 var offset = lineOffsets[i];
83695                 var middle = offset / 100 * length;
83696                 var start = middle - width / 2;
83697                 if (start < 0 || start + width > length) continue; // generate subpath and ignore paths that are invalid or don't cross viewport.
83698
83699                 var sub = subpath(points, start, start + width);
83700
83701                 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
83702                   continue;
83703                 }
83704
83705                 var isReverse = reverse(sub);
83706
83707                 if (isReverse) {
83708                   sub = sub.reverse();
83709                 }
83710
83711                 var bboxes = [];
83712                 var boxsize = (height + 2) / 2;
83713
83714                 for (var j = 0; j < sub.length - 1; j++) {
83715                   var a = sub[j];
83716                   var b = sub[j + 1]; // split up the text into small collision boxes
83717
83718                   var num = Math.max(1, Math.floor(geoVecLength(a, b) / boxsize / 2));
83719
83720                   for (var box = 0; box < num; box++) {
83721                     var p = geoVecInterp(a, b, box / num);
83722                     var x0 = p[0] - boxsize - padding;
83723                     var y0 = p[1] - boxsize - padding;
83724                     var x1 = p[0] + boxsize + padding;
83725                     var y1 = p[1] + boxsize + padding;
83726                     bboxes.push({
83727                       minX: Math.min(x0, x1),
83728                       minY: Math.min(y0, y1),
83729                       maxX: Math.max(x0, x1),
83730                       maxY: Math.max(y0, y1)
83731                     });
83732                   }
83733                 }
83734
83735                 if (tryInsert(bboxes, entity.id, false)) {
83736                   // accept this one
83737                   return {
83738                     'font-size': height + 2,
83739                     lineString: lineString(sub),
83740                     startOffset: offset + '%'
83741                   };
83742                 }
83743               }
83744
83745               function reverse(p) {
83746                 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
83747                 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI / 2 && angle > -Math.PI / 2);
83748               }
83749
83750               function lineString(points) {
83751                 return 'M' + points.join('L');
83752               }
83753
83754               function subpath(points, from, to) {
83755                 var sofar = 0;
83756                 var start, end, i0, i1;
83757
83758                 for (var i = 0; i < points.length - 1; i++) {
83759                   var a = points[i];
83760                   var b = points[i + 1];
83761                   var current = geoVecLength(a, b);
83762                   var portion;
83763
83764                   if (!start && sofar + current >= from) {
83765                     portion = (from - sofar) / current;
83766                     start = [a[0] + portion * (b[0] - a[0]), a[1] + portion * (b[1] - a[1])];
83767                     i0 = i + 1;
83768                   }
83769
83770                   if (!end && sofar + current >= to) {
83771                     portion = (to - sofar) / current;
83772                     end = [a[0] + portion * (b[0] - a[0]), a[1] + portion * (b[1] - a[1])];
83773                     i1 = i + 1;
83774                   }
83775
83776                   sofar += current;
83777                 }
83778
83779                 var result = points.slice(i0, i1);
83780                 result.unshift(start);
83781                 result.push(end);
83782                 return result;
83783               }
83784             }
83785
83786             function getAreaLabel(entity, width, height) {
83787               var centroid = path.centroid(entity.asGeoJSON(graph));
83788               var extent = entity.extent(graph);
83789               var areaWidth = projection(extent[1])[0] - projection(extent[0])[0];
83790               if (isNaN(centroid[0]) || areaWidth < 20) return;
83791               var preset = _mainPresetIndex.match(entity, context.graph());
83792               var picon = preset && preset.icon;
83793               var iconSize = 17;
83794               var padding = 2;
83795               var p = {};
83796
83797               if (picon) {
83798                 // icon and label..
83799                 if (addIcon()) {
83800                   addLabel(iconSize + padding);
83801                   return p;
83802                 }
83803               } else {
83804                 // label only..
83805                 if (addLabel(0)) {
83806                   return p;
83807                 }
83808               }
83809
83810               function addIcon() {
83811                 var iconX = centroid[0] - iconSize / 2;
83812                 var iconY = centroid[1] - iconSize / 2;
83813                 var bbox = {
83814                   minX: iconX,
83815                   minY: iconY,
83816                   maxX: iconX + iconSize,
83817                   maxY: iconY + iconSize
83818                 };
83819
83820                 if (tryInsert([bbox], entity.id + 'I', true)) {
83821                   p.transform = 'translate(' + iconX + ',' + iconY + ')';
83822                   return true;
83823                 }
83824
83825                 return false;
83826               }
83827
83828               function addLabel(yOffset) {
83829                 if (width && areaWidth >= width + 20) {
83830                   var labelX = centroid[0];
83831                   var labelY = centroid[1] + yOffset;
83832                   var bbox = {
83833                     minX: labelX - width / 2 - padding,
83834                     minY: labelY - height / 2 - padding,
83835                     maxX: labelX + width / 2 + padding,
83836                     maxY: labelY + height / 2 + padding
83837                   };
83838
83839                   if (tryInsert([bbox], entity.id, true)) {
83840                     p.x = labelX;
83841                     p.y = labelY;
83842                     p.textAnchor = 'middle';
83843                     p.height = height;
83844                     return true;
83845                   }
83846                 }
83847
83848                 return false;
83849               }
83850             } // force insert a singular bounding box
83851             // singular box only, no array, id better be unique
83852
83853
83854             function doInsert(bbox, id) {
83855               bbox.id = id;
83856               var oldbox = _entitybboxes[id];
83857
83858               if (oldbox) {
83859                 _rdrawn.remove(oldbox);
83860               }
83861
83862               _entitybboxes[id] = bbox;
83863
83864               _rdrawn.insert(bbox);
83865             }
83866
83867             function tryInsert(bboxes, id, saveSkipped) {
83868               var skipped = false;
83869
83870               for (var i = 0; i < bboxes.length; i++) {
83871                 var bbox = bboxes[i];
83872                 bbox.id = id; // Check that label is visible
83873
83874                 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
83875                   skipped = true;
83876                   break;
83877                 }
83878
83879                 if (_rdrawn.collides(bbox)) {
83880                   skipped = true;
83881                   break;
83882                 }
83883               }
83884
83885               _entitybboxes[id] = bboxes;
83886
83887               if (skipped) {
83888                 if (saveSkipped) {
83889                   _rskipped.load(bboxes);
83890                 }
83891               } else {
83892                 _rdrawn.load(bboxes);
83893               }
83894
83895               return !skipped;
83896             }
83897
83898             var layer = selection.selectAll('.layer-osm.labels');
83899             layer.selectAll('.labels-group').data(['halo', 'label', 'debug']).enter().append('g').attr('class', function (d) {
83900               return 'labels-group ' + d;
83901             });
83902             var halo = layer.selectAll('.labels-group.halo');
83903             var label = layer.selectAll('.labels-group.label');
83904             var debug = layer.selectAll('.labels-group.debug'); // points
83905
83906             drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
83907             drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point); // lines
83908
83909             drawLinePaths(layer, labelled.line, filter, '', positions.line);
83910             drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
83911             drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line); // areas
83912
83913             drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
83914             drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
83915             drawAreaIcons(label, labelled.area, filter, 'areaicon', positions.area);
83916             drawAreaIcons(halo, labelled.area, filter, 'areaicon-halo', positions.area); // debug
83917
83918             drawCollisionBoxes(debug, _rskipped, 'debug-skipped');
83919             drawCollisionBoxes(debug, _rdrawn, 'debug-drawn');
83920             layer.call(filterLabels);
83921           }
83922
83923           function filterLabels(selection) {
83924             var drawLayer = selection.selectAll('.layer-osm.labels');
83925             var layers = drawLayer.selectAll('.labels-group.halo, .labels-group.label');
83926             layers.selectAll('.nolabel').classed('nolabel', false);
83927             var mouse = context.map().mouse();
83928             var graph = context.graph();
83929             var selectedIDs = context.selectedIDs();
83930             var ids = [];
83931             var pad, bbox; // hide labels near the mouse
83932
83933             if (mouse) {
83934               pad = 20;
83935               bbox = {
83936                 minX: mouse[0] - pad,
83937                 minY: mouse[1] - pad,
83938                 maxX: mouse[0] + pad,
83939                 maxY: mouse[1] + pad
83940               };
83941
83942               var nearMouse = _rdrawn.search(bbox).map(function (entity) {
83943                 return entity.id;
83944               });
83945
83946               ids.push.apply(ids, nearMouse);
83947             } // hide labels on selected nodes (they look weird when dragging / haloed)
83948
83949
83950             for (var i = 0; i < selectedIDs.length; i++) {
83951               var entity = graph.hasEntity(selectedIDs[i]);
83952
83953               if (entity && entity.type === 'node') {
83954                 ids.push(selectedIDs[i]);
83955               }
83956             }
83957
83958             layers.selectAll(utilEntitySelector(ids)).classed('nolabel', true); // draw the mouse bbox if debugging is on..
83959
83960             var debug = selection.selectAll('.labels-group.debug');
83961             var gj = [];
83962
83963             if (context.getDebug('collision')) {
83964               gj = bbox ? [{
83965                 type: 'Polygon',
83966                 coordinates: [[[bbox.minX, bbox.minY], [bbox.maxX, bbox.minY], [bbox.maxX, bbox.maxY], [bbox.minX, bbox.maxY], [bbox.minX, bbox.minY]]]
83967               }] : [];
83968             }
83969
83970             var box = debug.selectAll('.debug-mouse').data(gj); // exit
83971
83972             box.exit().remove(); // enter/update
83973
83974             box.enter().append('path').attr('class', 'debug debug-mouse yellow').merge(box).attr('d', d3_geoPath());
83975           }
83976
83977           var throttleFilterLabels = throttle(filterLabels, 100);
83978
83979           drawLabels.observe = function (selection) {
83980             var listener = function listener() {
83981               throttleFilterLabels(selection);
83982             };
83983
83984             selection.on('mousemove.hidelabels', listener);
83985             context.on('enter.hidelabels', listener);
83986           };
83987
83988           drawLabels.off = function (selection) {
83989             throttleFilterLabels.cancel();
83990             selection.on('mousemove.hidelabels', null);
83991             context.on('enter.hidelabels', null);
83992           };
83993
83994           return drawLabels;
83995         }
83996
83997         var _layerEnabled$1 = false;
83998
83999         var _qaService$1;
84000
84001         function svgImproveOSM(projection, context, dispatch) {
84002           var throttledRedraw = throttle(function () {
84003             return dispatch.call('change');
84004           }, 1000);
84005
84006           var minZoom = 12;
84007           var touchLayer = select(null);
84008           var drawLayer = select(null);
84009           var layerVisible = false;
84010
84011           function markerPath(selection, klass) {
84012             selection.attr('class', klass).attr('transform', 'translate(-10, -28)').attr('points', '16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6');
84013           } // Loosely-coupled improveOSM service for fetching issues
84014
84015
84016           function getService() {
84017             if (services.improveOSM && !_qaService$1) {
84018               _qaService$1 = services.improveOSM;
84019
84020               _qaService$1.on('loaded', throttledRedraw);
84021             } else if (!services.improveOSM && _qaService$1) {
84022               _qaService$1 = null;
84023             }
84024
84025             return _qaService$1;
84026           } // Show the markers
84027
84028
84029           function editOn() {
84030             if (!layerVisible) {
84031               layerVisible = true;
84032               drawLayer.style('display', 'block');
84033             }
84034           } // Immediately remove the markers and their touch targets
84035
84036
84037           function editOff() {
84038             if (layerVisible) {
84039               layerVisible = false;
84040               drawLayer.style('display', 'none');
84041               drawLayer.selectAll('.qaItem.improveOSM').remove();
84042               touchLayer.selectAll('.qaItem.improveOSM').remove();
84043             }
84044           } // Enable the layer.  This shows the markers and transitions them to visible.
84045
84046
84047           function layerOn() {
84048             editOn();
84049             drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
84050               return dispatch.call('change');
84051             });
84052           } // Disable the layer.  This transitions the layer invisible and then hides the markers.
84053
84054
84055           function layerOff() {
84056             throttledRedraw.cancel();
84057             drawLayer.interrupt();
84058             touchLayer.selectAll('.qaItem.improveOSM').remove();
84059             drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
84060               editOff();
84061               dispatch.call('change');
84062             });
84063           } // Update the issue markers
84064
84065
84066           function updateMarkers() {
84067             if (!layerVisible || !_layerEnabled$1) return;
84068             var service = getService();
84069             var selectedID = context.selectedErrorID();
84070             var data = service ? service.getItems(projection) : [];
84071             var getTransform = svgPointTransform(projection); // Draw markers..
84072
84073             var markers = drawLayer.selectAll('.qaItem.improveOSM').data(data, function (d) {
84074               return d.id;
84075             }); // exit
84076
84077             markers.exit().remove(); // enter
84078
84079             var markersEnter = markers.enter().append('g').attr('class', function (d) {
84080               return "qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
84081             });
84082             markersEnter.append('polygon').call(markerPath, 'shadow');
84083             markersEnter.append('ellipse').attr('cx', 0).attr('cy', 0).attr('rx', 4.5).attr('ry', 2).attr('class', 'stroke');
84084             markersEnter.append('polygon').attr('fill', 'currentColor').call(markerPath, 'qaItem-fill');
84085             markersEnter.append('use').attr('transform', 'translate(-6.5, -23)').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('xlink:href', function (d) {
84086               var picon = d.icon;
84087
84088               if (!picon) {
84089                 return '';
84090               } else {
84091                 var isMaki = /^maki-/.test(picon);
84092                 return "#".concat(picon).concat(isMaki ? '-11' : '');
84093               }
84094             }); // update
84095
84096             markers.merge(markersEnter).sort(sortY).classed('selected', function (d) {
84097               return d.id === selectedID;
84098             }).attr('transform', getTransform); // Draw targets..
84099
84100             if (touchLayer.empty()) return;
84101             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
84102             var targets = touchLayer.selectAll('.qaItem.improveOSM').data(data, function (d) {
84103               return d.id;
84104             }); // exit
84105
84106             targets.exit().remove(); // enter/update
84107
84108             targets.enter().append('rect').attr('width', '20px').attr('height', '30px').attr('x', '-10px').attr('y', '-28px').merge(targets).sort(sortY).attr('class', function (d) {
84109               return "qaItem ".concat(d.service, " target ").concat(fillClass, " itemId-").concat(d.id);
84110             }).attr('transform', getTransform);
84111
84112             function sortY(a, b) {
84113               return a.id === selectedID ? 1 : b.id === selectedID ? -1 : b.loc[1] - a.loc[1];
84114             }
84115           } // Draw the ImproveOSM layer and schedule loading issues and updating markers.
84116
84117
84118           function drawImproveOSM(selection) {
84119             var service = getService();
84120             var surface = context.surface();
84121
84122             if (surface && !surface.empty()) {
84123               touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
84124             }
84125
84126             drawLayer = selection.selectAll('.layer-improveOSM').data(service ? [0] : []);
84127             drawLayer.exit().remove();
84128             drawLayer = drawLayer.enter().append('g').attr('class', 'layer-improveOSM').style('display', _layerEnabled$1 ? 'block' : 'none').merge(drawLayer);
84129
84130             if (_layerEnabled$1) {
84131               if (service && ~~context.map().zoom() >= minZoom) {
84132                 editOn();
84133                 service.loadIssues(projection);
84134                 updateMarkers();
84135               } else {
84136                 editOff();
84137               }
84138             }
84139           } // Toggles the layer on and off
84140
84141
84142           drawImproveOSM.enabled = function (val) {
84143             if (!arguments.length) return _layerEnabled$1;
84144             _layerEnabled$1 = val;
84145
84146             if (_layerEnabled$1) {
84147               layerOn();
84148             } else {
84149               layerOff();
84150
84151               if (context.selectedErrorID()) {
84152                 context.enter(modeBrowse(context));
84153               }
84154             }
84155
84156             dispatch.call('change');
84157             return this;
84158           };
84159
84160           drawImproveOSM.supported = function () {
84161             return !!getService();
84162           };
84163
84164           return drawImproveOSM;
84165         }
84166
84167         var _layerEnabled = false;
84168
84169         var _qaService;
84170
84171         function svgOsmose(projection, context, dispatch) {
84172           var throttledRedraw = throttle(function () {
84173             return dispatch.call('change');
84174           }, 1000);
84175
84176           var minZoom = 12;
84177           var touchLayer = select(null);
84178           var drawLayer = select(null);
84179           var layerVisible = false;
84180
84181           function markerPath(selection, klass) {
84182             selection.attr('class', klass).attr('transform', 'translate(-10, -28)').attr('points', '16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6');
84183           } // Loosely-coupled osmose service for fetching issues
84184
84185
84186           function getService() {
84187             if (services.osmose && !_qaService) {
84188               _qaService = services.osmose;
84189
84190               _qaService.on('loaded', throttledRedraw);
84191             } else if (!services.osmose && _qaService) {
84192               _qaService = null;
84193             }
84194
84195             return _qaService;
84196           } // Show the markers
84197
84198
84199           function editOn() {
84200             if (!layerVisible) {
84201               layerVisible = true;
84202               drawLayer.style('display', 'block');
84203             }
84204           } // Immediately remove the markers and their touch targets
84205
84206
84207           function editOff() {
84208             if (layerVisible) {
84209               layerVisible = false;
84210               drawLayer.style('display', 'none');
84211               drawLayer.selectAll('.qaItem.osmose').remove();
84212               touchLayer.selectAll('.qaItem.osmose').remove();
84213             }
84214           } // Enable the layer.  This shows the markers and transitions them to visible.
84215
84216
84217           function layerOn() {
84218             editOn();
84219             drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
84220               return dispatch.call('change');
84221             });
84222           } // Disable the layer.  This transitions the layer invisible and then hides the markers.
84223
84224
84225           function layerOff() {
84226             throttledRedraw.cancel();
84227             drawLayer.interrupt();
84228             touchLayer.selectAll('.qaItem.osmose').remove();
84229             drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
84230               editOff();
84231               dispatch.call('change');
84232             });
84233           } // Update the issue markers
84234
84235
84236           function updateMarkers() {
84237             if (!layerVisible || !_layerEnabled) return;
84238             var service = getService();
84239             var selectedID = context.selectedErrorID();
84240             var data = service ? service.getItems(projection) : [];
84241             var getTransform = svgPointTransform(projection); // Draw markers..
84242
84243             var markers = drawLayer.selectAll('.qaItem.osmose').data(data, function (d) {
84244               return d.id;
84245             }); // exit
84246
84247             markers.exit().remove(); // enter
84248
84249             var markersEnter = markers.enter().append('g').attr('class', function (d) {
84250               return "qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
84251             });
84252             markersEnter.append('polygon').call(markerPath, 'shadow');
84253             markersEnter.append('ellipse').attr('cx', 0).attr('cy', 0).attr('rx', 4.5).attr('ry', 2).attr('class', 'stroke');
84254             markersEnter.append('polygon').attr('fill', function (d) {
84255               return service.getColor(d.item);
84256             }).call(markerPath, 'qaItem-fill');
84257             markersEnter.append('use').attr('transform', 'translate(-6.5, -23)').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('xlink:href', function (d) {
84258               var picon = d.icon;
84259
84260               if (!picon) {
84261                 return '';
84262               } else {
84263                 var isMaki = /^maki-/.test(picon);
84264                 return "#".concat(picon).concat(isMaki ? '-11' : '');
84265               }
84266             }); // update
84267
84268             markers.merge(markersEnter).sort(sortY).classed('selected', function (d) {
84269               return d.id === selectedID;
84270             }).attr('transform', getTransform); // Draw targets..
84271
84272             if (touchLayer.empty()) return;
84273             var fillClass = context.getDebug('target') ? 'pink' : 'nocolor';
84274             var targets = touchLayer.selectAll('.qaItem.osmose').data(data, function (d) {
84275               return d.id;
84276             }); // exit
84277
84278             targets.exit().remove(); // enter/update
84279
84280             targets.enter().append('rect').attr('width', '20px').attr('height', '30px').attr('x', '-10px').attr('y', '-28px').merge(targets).sort(sortY).attr('class', function (d) {
84281               return "qaItem ".concat(d.service, " target ").concat(fillClass, " itemId-").concat(d.id);
84282             }).attr('transform', getTransform);
84283
84284             function sortY(a, b) {
84285               return a.id === selectedID ? 1 : b.id === selectedID ? -1 : b.loc[1] - a.loc[1];
84286             }
84287           } // Draw the Osmose layer and schedule loading issues and updating markers.
84288
84289
84290           function drawOsmose(selection) {
84291             var service = getService();
84292             var surface = context.surface();
84293
84294             if (surface && !surface.empty()) {
84295               touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
84296             }
84297
84298             drawLayer = selection.selectAll('.layer-osmose').data(service ? [0] : []);
84299             drawLayer.exit().remove();
84300             drawLayer = drawLayer.enter().append('g').attr('class', 'layer-osmose').style('display', _layerEnabled ? 'block' : 'none').merge(drawLayer);
84301
84302             if (_layerEnabled) {
84303               if (service && ~~context.map().zoom() >= minZoom) {
84304                 editOn();
84305                 service.loadIssues(projection);
84306                 updateMarkers();
84307               } else {
84308                 editOff();
84309               }
84310             }
84311           } // Toggles the layer on and off
84312
84313
84314           drawOsmose.enabled = function (val) {
84315             if (!arguments.length) return _layerEnabled;
84316             _layerEnabled = val;
84317
84318             if (_layerEnabled) {
84319               // Strings supplied by Osmose fetched before showing layer for first time
84320               // NOTE: Currently no way to change locale in iD at runtime, would need to re-call this method if that's ever implemented
84321               // Also, If layer is toggled quickly multiple requests are sent
84322               getService().loadStrings().then(layerOn)["catch"](function (err) {
84323                 console.log(err); // eslint-disable-line no-console
84324               });
84325             } else {
84326               layerOff();
84327
84328               if (context.selectedErrorID()) {
84329                 context.enter(modeBrowse(context));
84330               }
84331             }
84332
84333             dispatch.call('change');
84334             return this;
84335           };
84336
84337           drawOsmose.supported = function () {
84338             return !!getService();
84339           };
84340
84341           return drawOsmose;
84342         }
84343
84344         function svgStreetside(projection, context, dispatch) {
84345           var throttledRedraw = throttle(function () {
84346             dispatch.call('change');
84347           }, 1000);
84348
84349           var minZoom = 14;
84350           var minMarkerZoom = 16;
84351           var minViewfieldZoom = 18;
84352           var layer = select(null);
84353           var _viewerYaw = 0;
84354           var _selectedSequence = null;
84355
84356           var _streetside;
84357           /**
84358            * init().
84359            */
84360
84361
84362           function init() {
84363             if (svgStreetside.initialized) return; // run once
84364
84365             svgStreetside.enabled = false;
84366             svgStreetside.initialized = true;
84367           }
84368           /**
84369            * getService().
84370            */
84371
84372
84373           function getService() {
84374             if (services.streetside && !_streetside) {
84375               _streetside = services.streetside;
84376
84377               _streetside.event.on('viewerChanged.svgStreetside', viewerChanged).on('loadedImages.svgStreetside', throttledRedraw);
84378             } else if (!services.streetside && _streetside) {
84379               _streetside = null;
84380             }
84381
84382             return _streetside;
84383           }
84384           /**
84385            * showLayer().
84386            */
84387
84388
84389           function showLayer() {
84390             var service = getService();
84391             if (!service) return;
84392             editOn();
84393             layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
84394               dispatch.call('change');
84395             });
84396           }
84397           /**
84398            * hideLayer().
84399            */
84400
84401
84402           function hideLayer() {
84403             throttledRedraw.cancel();
84404             layer.transition().duration(250).style('opacity', 0).on('end', editOff);
84405           }
84406           /**
84407            * editOn().
84408            */
84409
84410
84411           function editOn() {
84412             layer.style('display', 'block');
84413           }
84414           /**
84415            * editOff().
84416            */
84417
84418
84419           function editOff() {
84420             layer.selectAll('.viewfield-group').remove();
84421             layer.style('display', 'none');
84422           }
84423           /**
84424            * click() Handles 'bubble' point click event.
84425            */
84426
84427
84428           function click(d3_event, d) {
84429             var service = getService();
84430             if (!service) return; // try to preserve the viewer rotation when staying on the same sequence
84431
84432             if (d.sequenceKey !== _selectedSequence) {
84433               _viewerYaw = 0; // reset
84434             }
84435
84436             _selectedSequence = d.sequenceKey;
84437             service.ensureViewerLoaded(context).then(function () {
84438               service.selectImage(context, d.key).yaw(_viewerYaw).showViewer(context);
84439             });
84440             context.map().centerEase(d.loc);
84441           }
84442           /**
84443            * mouseover().
84444            */
84445
84446
84447           function mouseover(d3_event, d) {
84448             var service = getService();
84449             if (service) service.setStyles(context, d);
84450           }
84451           /**
84452            * mouseout().
84453            */
84454
84455
84456           function mouseout() {
84457             var service = getService();
84458             if (service) service.setStyles(context, null);
84459           }
84460           /**
84461            * transform().
84462            */
84463
84464
84465           function transform(d) {
84466             var t = svgPointTransform(projection)(d);
84467             var rot = d.ca + _viewerYaw;
84468
84469             if (rot) {
84470               t += ' rotate(' + Math.floor(rot) + ',0,0)';
84471             }
84472
84473             return t;
84474           }
84475
84476           function viewerChanged() {
84477             var service = getService();
84478             if (!service) return;
84479             var viewer = service.viewer();
84480             if (!viewer) return; // update viewfield rotation
84481
84482             _viewerYaw = viewer.getYaw(); // avoid updating if the map is currently transformed
84483             // e.g. during drags or easing.
84484
84485             if (context.map().isTransformed()) return;
84486             layer.selectAll('.viewfield-group.currentView').attr('transform', transform);
84487           }
84488
84489           function filterBubbles(bubbles) {
84490             var fromDate = context.photos().fromDate();
84491             var toDate = context.photos().toDate();
84492             var usernames = context.photos().usernames();
84493
84494             if (fromDate) {
84495               var fromTimestamp = new Date(fromDate).getTime();
84496               bubbles = bubbles.filter(function (bubble) {
84497                 return new Date(bubble.captured_at).getTime() >= fromTimestamp;
84498               });
84499             }
84500
84501             if (toDate) {
84502               var toTimestamp = new Date(toDate).getTime();
84503               bubbles = bubbles.filter(function (bubble) {
84504                 return new Date(bubble.captured_at).getTime() <= toTimestamp;
84505               });
84506             }
84507
84508             if (usernames) {
84509               bubbles = bubbles.filter(function (bubble) {
84510                 return usernames.indexOf(bubble.captured_by) !== -1;
84511               });
84512             }
84513
84514             return bubbles;
84515           }
84516
84517           function filterSequences(sequences) {
84518             var fromDate = context.photos().fromDate();
84519             var toDate = context.photos().toDate();
84520             var usernames = context.photos().usernames();
84521
84522             if (fromDate) {
84523               var fromTimestamp = new Date(fromDate).getTime();
84524               sequences = sequences.filter(function (sequences) {
84525                 return new Date(sequences.properties.captured_at).getTime() >= fromTimestamp;
84526               });
84527             }
84528
84529             if (toDate) {
84530               var toTimestamp = new Date(toDate).getTime();
84531               sequences = sequences.filter(function (sequences) {
84532                 return new Date(sequences.properties.captured_at).getTime() <= toTimestamp;
84533               });
84534             }
84535
84536             if (usernames) {
84537               sequences = sequences.filter(function (sequences) {
84538                 return usernames.indexOf(sequences.properties.captured_by) !== -1;
84539               });
84540             }
84541
84542             return sequences;
84543           }
84544           /**
84545            * update().
84546            */
84547
84548
84549           function update() {
84550             var viewer = context.container().select('.photoviewer');
84551             var selected = viewer.empty() ? undefined : viewer.datum();
84552             var z = ~~context.map().zoom();
84553             var showMarkers = z >= minMarkerZoom;
84554             var showViewfields = z >= minViewfieldZoom;
84555             var service = getService();
84556             var sequences = [];
84557             var bubbles = [];
84558
84559             if (context.photos().showsPanoramic()) {
84560               sequences = service ? service.sequences(projection) : [];
84561               bubbles = service && showMarkers ? service.bubbles(projection) : [];
84562               sequences = filterSequences(sequences);
84563               bubbles = filterBubbles(bubbles);
84564             }
84565
84566             var traces = layer.selectAll('.sequences').selectAll('.sequence').data(sequences, function (d) {
84567               return d.properties.key;
84568             }); // exit
84569
84570             traces.exit().remove(); // enter/update
84571
84572             traces = traces.enter().append('path').attr('class', 'sequence').merge(traces).attr('d', svgPath(projection).geojson);
84573             var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(bubbles, function (d) {
84574               // force reenter once bubbles are attached to a sequence
84575               return d.key + (d.sequenceKey ? 'v1' : 'v0');
84576             }); // exit
84577
84578             groups.exit().remove(); // enter
84579
84580             var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group').on('mouseenter', mouseover).on('mouseleave', mouseout).on('click', click);
84581             groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
84582
84583             var markers = groups.merge(groupsEnter).sort(function (a, b) {
84584               return a === selected ? 1 : b === selected ? -1 : b.loc[1] - a.loc[1];
84585             }).attr('transform', transform).select('.viewfield-scale');
84586             markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
84587             var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
84588             viewfields.exit().remove(); // viewfields may or may not be drawn...
84589             // but if they are, draw below the circles
84590
84591             viewfields.enter().insert('path', 'circle').attr('class', 'viewfield').attr('transform', 'scale(1.5,1.5),translate(-8, -13)').attr('d', viewfieldPath);
84592
84593             function viewfieldPath() {
84594               var d = this.parentNode.__data__;
84595
84596               if (d.pano) {
84597                 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
84598               } else {
84599                 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
84600               }
84601             }
84602           }
84603           /**
84604            * drawImages()
84605            * drawImages is the method that is returned (and that runs) every time 'svgStreetside()' is called.
84606            * 'svgStreetside()' is called from index.js
84607            */
84608
84609
84610           function drawImages(selection) {
84611             var enabled = svgStreetside.enabled;
84612             var service = getService();
84613             layer = selection.selectAll('.layer-streetside-images').data(service ? [0] : []);
84614             layer.exit().remove();
84615             var layerEnter = layer.enter().append('g').attr('class', 'layer-streetside-images').style('display', enabled ? 'block' : 'none');
84616             layerEnter.append('g').attr('class', 'sequences');
84617             layerEnter.append('g').attr('class', 'markers');
84618             layer = layerEnter.merge(layer);
84619
84620             if (enabled) {
84621               if (service && ~~context.map().zoom() >= minZoom) {
84622                 editOn();
84623                 update();
84624                 service.loadBubbles(projection);
84625               } else {
84626                 editOff();
84627               }
84628             }
84629           }
84630           /**
84631            * drawImages.enabled().
84632            */
84633
84634
84635           drawImages.enabled = function (_) {
84636             if (!arguments.length) return svgStreetside.enabled;
84637             svgStreetside.enabled = _;
84638
84639             if (svgStreetside.enabled) {
84640               showLayer();
84641               context.photos().on('change.streetside', update);
84642             } else {
84643               hideLayer();
84644               context.photos().on('change.streetside', null);
84645             }
84646
84647             dispatch.call('change');
84648             return this;
84649           };
84650           /**
84651            * drawImages.supported().
84652            */
84653
84654
84655           drawImages.supported = function () {
84656             return !!getService();
84657           };
84658
84659           init();
84660           return drawImages;
84661         }
84662
84663         function svgMapillaryImages(projection, context, dispatch) {
84664           var throttledRedraw = throttle(function () {
84665             dispatch.call('change');
84666           }, 1000);
84667
84668           var minZoom = 12;
84669           var minMarkerZoom = 16;
84670           var minViewfieldZoom = 18;
84671           var layer = select(null);
84672
84673           var _mapillary;
84674
84675           function init() {
84676             if (svgMapillaryImages.initialized) return; // run once
84677
84678             svgMapillaryImages.enabled = false;
84679             svgMapillaryImages.initialized = true;
84680           }
84681
84682           function getService() {
84683             if (services.mapillary && !_mapillary) {
84684               _mapillary = services.mapillary;
84685
84686               _mapillary.event.on('loadedImages', throttledRedraw);
84687             } else if (!services.mapillary && _mapillary) {
84688               _mapillary = null;
84689             }
84690
84691             return _mapillary;
84692           }
84693
84694           function showLayer() {
84695             var service = getService();
84696             if (!service) return;
84697             editOn();
84698             layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
84699               dispatch.call('change');
84700             });
84701           }
84702
84703           function hideLayer() {
84704             throttledRedraw.cancel();
84705             layer.transition().duration(250).style('opacity', 0).on('end', editOff);
84706           }
84707
84708           function editOn() {
84709             layer.style('display', 'block');
84710           }
84711
84712           function editOff() {
84713             layer.selectAll('.viewfield-group').remove();
84714             layer.style('display', 'none');
84715           }
84716
84717           function click(d3_event, image) {
84718             var service = getService();
84719             if (!service) return;
84720             service.ensureViewerLoaded(context).then(function () {
84721               service.selectImage(context, image.id).showViewer(context);
84722             });
84723             context.map().centerEase(image.loc);
84724           }
84725
84726           function mouseover(d3_event, image) {
84727             var service = getService();
84728             if (service) service.setStyles(context, image);
84729           }
84730
84731           function mouseout() {
84732             var service = getService();
84733             if (service) service.setStyles(context, null);
84734           }
84735
84736           function transform(d) {
84737             var t = svgPointTransform(projection)(d);
84738
84739             if (d.ca) {
84740               t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
84741             }
84742
84743             return t;
84744           }
84745
84746           function filterImages(images) {
84747             var showsPano = context.photos().showsPanoramic();
84748             var showsFlat = context.photos().showsFlat();
84749             var fromDate = context.photos().fromDate();
84750             var toDate = context.photos().toDate();
84751
84752             if (!showsPano || !showsFlat) {
84753               images = images.filter(function (image) {
84754                 if (image.is_pano) return showsPano;
84755                 return showsFlat;
84756               });
84757             }
84758
84759             if (fromDate) {
84760               images = images.filter(function (image) {
84761                 return new Date(image.captured_at).getTime() >= new Date(fromDate).getTime();
84762               });
84763             }
84764
84765             if (toDate) {
84766               images = images.filter(function (image) {
84767                 return new Date(image.captured_at).getTime() <= new Date(toDate).getTime();
84768               });
84769             }
84770
84771             return images;
84772           }
84773
84774           function filterSequences(sequences) {
84775             var showsPano = context.photos().showsPanoramic();
84776             var showsFlat = context.photos().showsFlat();
84777             var fromDate = context.photos().fromDate();
84778             var toDate = context.photos().toDate();
84779
84780             if (!showsPano || !showsFlat) {
84781               sequences = sequences.filter(function (sequence) {
84782                 if (sequence.properties.hasOwnProperty('is_pano')) {
84783                   if (sequence.properties.is_pano) return showsPano;
84784                   return showsFlat;
84785                 }
84786
84787                 return false;
84788               });
84789             }
84790
84791             if (fromDate) {
84792               sequences = sequences.filter(function (sequence) {
84793                 return new Date(sequence.properties.captured_at).getTime() >= new Date(fromDate).getTime().toString();
84794               });
84795             }
84796
84797             if (toDate) {
84798               sequences = sequences.filter(function (sequence) {
84799                 return new Date(sequence.properties.captured_at).getTime() <= new Date(toDate).getTime().toString();
84800               });
84801             }
84802
84803             return sequences;
84804           }
84805
84806           function update() {
84807             var z = ~~context.map().zoom();
84808             var showMarkers = z >= minMarkerZoom;
84809             var showViewfields = z >= minViewfieldZoom;
84810             var service = getService();
84811             var sequences = service ? service.sequences(projection) : [];
84812             var images = service && showMarkers ? service.images(projection) : [];
84813             images = filterImages(images);
84814             sequences = filterSequences(sequences);
84815             service.filterViewer(context);
84816             var traces = layer.selectAll('.sequences').selectAll('.sequence').data(sequences, function (d) {
84817               return d.properties.id;
84818             }); // exit
84819
84820             traces.exit().remove(); // enter/update
84821
84822             traces = traces.enter().append('path').attr('class', 'sequence').merge(traces).attr('d', svgPath(projection).geojson);
84823             var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(images, function (d) {
84824               return d.id;
84825             }); // exit
84826
84827             groups.exit().remove(); // enter
84828
84829             var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group').on('mouseenter', mouseover).on('mouseleave', mouseout).on('click', click);
84830             groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
84831
84832             var markers = groups.merge(groupsEnter).sort(function (a, b) {
84833               return b.loc[1] - a.loc[1]; // sort Y
84834             }).attr('transform', transform).select('.viewfield-scale');
84835             markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
84836             var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
84837             viewfields.exit().remove();
84838             viewfields.enter() // viewfields may or may not be drawn...
84839             .insert('path', 'circle') // but if they are, draw below the circles
84840             .attr('class', 'viewfield').classed('pano', function () {
84841               return this.parentNode.__data__.is_pano;
84842             }).attr('transform', 'scale(1.5,1.5),translate(-8, -13)').attr('d', viewfieldPath);
84843
84844             function viewfieldPath() {
84845               if (this.parentNode.__data__.is_pano) {
84846                 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
84847               } else {
84848                 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
84849               }
84850             }
84851           }
84852
84853           function drawImages(selection) {
84854             var enabled = svgMapillaryImages.enabled;
84855             var service = getService();
84856             layer = selection.selectAll('.layer-mapillary').data(service ? [0] : []);
84857             layer.exit().remove();
84858             var layerEnter = layer.enter().append('g').attr('class', 'layer-mapillary').style('display', enabled ? 'block' : 'none');
84859             layerEnter.append('g').attr('class', 'sequences');
84860             layerEnter.append('g').attr('class', 'markers');
84861             layer = layerEnter.merge(layer);
84862
84863             if (enabled) {
84864               if (service && ~~context.map().zoom() >= minZoom) {
84865                 editOn();
84866                 update();
84867                 service.loadImages(projection);
84868               } else {
84869                 editOff();
84870               }
84871             }
84872           }
84873
84874           drawImages.enabled = function (_) {
84875             if (!arguments.length) return svgMapillaryImages.enabled;
84876             svgMapillaryImages.enabled = _;
84877
84878             if (svgMapillaryImages.enabled) {
84879               showLayer();
84880               context.photos().on('change.mapillary_images', update);
84881             } else {
84882               hideLayer();
84883               context.photos().on('change.mapillary_images', null);
84884             }
84885
84886             dispatch.call('change');
84887             return this;
84888           };
84889
84890           drawImages.supported = function () {
84891             return !!getService();
84892           };
84893
84894           init();
84895           return drawImages;
84896         }
84897
84898         function svgMapillaryPosition(projection, context) {
84899           var throttledRedraw = throttle(function () {
84900             update();
84901           }, 1000);
84902
84903           var minZoom = 12;
84904           var minViewfieldZoom = 18;
84905           var layer = select(null);
84906
84907           var _mapillary;
84908
84909           var viewerCompassAngle;
84910
84911           function init() {
84912             if (svgMapillaryPosition.initialized) return; // run once
84913
84914             svgMapillaryPosition.initialized = true;
84915           }
84916
84917           function getService() {
84918             if (services.mapillary && !_mapillary) {
84919               _mapillary = services.mapillary;
84920
84921               _mapillary.event.on('imageChanged', throttledRedraw);
84922
84923               _mapillary.event.on('bearingChanged', function (e) {
84924                 viewerCompassAngle = e.bearing;
84925                 if (context.map().isTransformed()) return;
84926                 layer.selectAll('.viewfield-group.currentView').filter(function (d) {
84927                   return d.is_pano;
84928                 }).attr('transform', transform);
84929               });
84930             } else if (!services.mapillary && _mapillary) {
84931               _mapillary = null;
84932             }
84933
84934             return _mapillary;
84935           }
84936
84937           function editOn() {
84938             layer.style('display', 'block');
84939           }
84940
84941           function editOff() {
84942             layer.selectAll('.viewfield-group').remove();
84943             layer.style('display', 'none');
84944           }
84945
84946           function transform(d) {
84947             var t = svgPointTransform(projection)(d);
84948
84949             if (d.is_pano && viewerCompassAngle !== null && isFinite(viewerCompassAngle)) {
84950               t += ' rotate(' + Math.floor(viewerCompassAngle) + ',0,0)';
84951             } else if (d.ca) {
84952               t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
84953             }
84954
84955             return t;
84956           }
84957
84958           function update() {
84959             var z = ~~context.map().zoom();
84960             var showViewfields = z >= minViewfieldZoom;
84961             var service = getService();
84962             var image = service && service.getActiveImage();
84963             var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(image ? [image] : [], function (d) {
84964               return d.id;
84965             }); // exit
84966
84967             groups.exit().remove(); // enter
84968
84969             var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group currentView highlighted');
84970             groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
84971
84972             var markers = groups.merge(groupsEnter).attr('transform', transform).select('.viewfield-scale');
84973             markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
84974             var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
84975             viewfields.exit().remove();
84976             viewfields.enter().insert('path', 'circle').attr('class', 'viewfield').attr('transform', 'scale(1.5,1.5),translate(-8, -13)').attr('d', 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z');
84977           }
84978
84979           function drawImages(selection) {
84980             var service = getService();
84981             layer = selection.selectAll('.layer-mapillary-position').data(service ? [0] : []);
84982             layer.exit().remove();
84983             var layerEnter = layer.enter().append('g').attr('class', 'layer-mapillary-position');
84984             layerEnter.append('g').attr('class', 'markers');
84985             layer = layerEnter.merge(layer);
84986
84987             if (service && ~~context.map().zoom() >= minZoom) {
84988               editOn();
84989               update();
84990             } else {
84991               editOff();
84992             }
84993           }
84994
84995           drawImages.enabled = function () {
84996             update();
84997             return this;
84998           };
84999
85000           drawImages.supported = function () {
85001             return !!getService();
85002           };
85003
85004           init();
85005           return drawImages;
85006         }
85007
85008         function svgMapillarySigns(projection, context, dispatch) {
85009           var throttledRedraw = throttle(function () {
85010             dispatch.call('change');
85011           }, 1000);
85012
85013           var minZoom = 12;
85014           var layer = select(null);
85015
85016           var _mapillary;
85017
85018           function init() {
85019             if (svgMapillarySigns.initialized) return; // run once
85020
85021             svgMapillarySigns.enabled = false;
85022             svgMapillarySigns.initialized = true;
85023           }
85024
85025           function getService() {
85026             if (services.mapillary && !_mapillary) {
85027               _mapillary = services.mapillary;
85028
85029               _mapillary.event.on('loadedSigns', throttledRedraw);
85030             } else if (!services.mapillary && _mapillary) {
85031               _mapillary = null;
85032             }
85033
85034             return _mapillary;
85035           }
85036
85037           function showLayer() {
85038             var service = getService();
85039             if (!service) return;
85040             service.loadSignResources(context);
85041             editOn();
85042           }
85043
85044           function hideLayer() {
85045             throttledRedraw.cancel();
85046             editOff();
85047           }
85048
85049           function editOn() {
85050             layer.style('display', 'block');
85051           }
85052
85053           function editOff() {
85054             layer.selectAll('.icon-sign').remove();
85055             layer.style('display', 'none');
85056           }
85057
85058           function click(d3_event, d) {
85059             var service = getService();
85060             if (!service) return;
85061             context.map().centerEase(d.loc);
85062             var selectedImageId = service.getActiveImage() && service.getActiveImage().id;
85063             service.getDetections(d.id).then(function (detections) {
85064               if (detections.length) {
85065                 var imageId = detections[0].image.id;
85066
85067                 if (imageId === selectedImageId) {
85068                   service.highlightDetection(detections[0]).selectImage(context, imageId);
85069                 } else {
85070                   service.ensureViewerLoaded(context).then(function () {
85071                     service.highlightDetection(detections[0]).selectImage(context, imageId).showViewer(context);
85072                   });
85073                 }
85074               }
85075             });
85076           }
85077
85078           function filterData(detectedFeatures) {
85079             var fromDate = context.photos().fromDate();
85080             var toDate = context.photos().toDate();
85081
85082             if (fromDate) {
85083               var fromTimestamp = new Date(fromDate).getTime();
85084               detectedFeatures = detectedFeatures.filter(function (feature) {
85085                 return new Date(feature.last_seen_at).getTime() >= fromTimestamp;
85086               });
85087             }
85088
85089             if (toDate) {
85090               var toTimestamp = new Date(toDate).getTime();
85091               detectedFeatures = detectedFeatures.filter(function (feature) {
85092                 return new Date(feature.first_seen_at).getTime() <= toTimestamp;
85093               });
85094             }
85095
85096             return detectedFeatures;
85097           }
85098
85099           function update() {
85100             var service = getService();
85101             var data = service ? service.signs(projection) : [];
85102             data = filterData(data);
85103             var transform = svgPointTransform(projection);
85104             var signs = layer.selectAll('.icon-sign').data(data, function (d) {
85105               return d.id;
85106             }); // exit
85107
85108             signs.exit().remove(); // enter
85109
85110             var enter = signs.enter().append('g').attr('class', 'icon-sign icon-detected').on('click', click);
85111             enter.append('use').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px').attr('xlink:href', function (d) {
85112               return '#' + d.value;
85113             });
85114             enter.append('rect').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px'); // update
85115
85116             signs.merge(enter).attr('transform', transform);
85117           }
85118
85119           function drawSigns(selection) {
85120             var enabled = svgMapillarySigns.enabled;
85121             var service = getService();
85122             layer = selection.selectAll('.layer-mapillary-signs').data(service ? [0] : []);
85123             layer.exit().remove();
85124             layer = layer.enter().append('g').attr('class', 'layer-mapillary-signs layer-mapillary-detections').style('display', enabled ? 'block' : 'none').merge(layer);
85125
85126             if (enabled) {
85127               if (service && ~~context.map().zoom() >= minZoom) {
85128                 editOn();
85129                 update();
85130                 service.loadSigns(projection);
85131                 service.showSignDetections(true);
85132               } else {
85133                 editOff();
85134               }
85135             } else if (service) {
85136               service.showSignDetections(false);
85137             }
85138           }
85139
85140           drawSigns.enabled = function (_) {
85141             if (!arguments.length) return svgMapillarySigns.enabled;
85142             svgMapillarySigns.enabled = _;
85143
85144             if (svgMapillarySigns.enabled) {
85145               showLayer();
85146               context.photos().on('change.mapillary_signs', update);
85147             } else {
85148               hideLayer();
85149               context.photos().on('change.mapillary_signs', null);
85150             }
85151
85152             dispatch.call('change');
85153             return this;
85154           };
85155
85156           drawSigns.supported = function () {
85157             return !!getService();
85158           };
85159
85160           init();
85161           return drawSigns;
85162         }
85163
85164         function svgMapillaryMapFeatures(projection, context, dispatch) {
85165           var throttledRedraw = throttle(function () {
85166             dispatch.call('change');
85167           }, 1000);
85168
85169           var minZoom = 12;
85170           var layer = select(null);
85171
85172           var _mapillary;
85173
85174           function init() {
85175             if (svgMapillaryMapFeatures.initialized) return; // run once
85176
85177             svgMapillaryMapFeatures.enabled = false;
85178             svgMapillaryMapFeatures.initialized = true;
85179           }
85180
85181           function getService() {
85182             if (services.mapillary && !_mapillary) {
85183               _mapillary = services.mapillary;
85184
85185               _mapillary.event.on('loadedMapFeatures', throttledRedraw);
85186             } else if (!services.mapillary && _mapillary) {
85187               _mapillary = null;
85188             }
85189
85190             return _mapillary;
85191           }
85192
85193           function showLayer() {
85194             var service = getService();
85195             if (!service) return;
85196             service.loadObjectResources(context);
85197             editOn();
85198           }
85199
85200           function hideLayer() {
85201             throttledRedraw.cancel();
85202             editOff();
85203           }
85204
85205           function editOn() {
85206             layer.style('display', 'block');
85207           }
85208
85209           function editOff() {
85210             layer.selectAll('.icon-map-feature').remove();
85211             layer.style('display', 'none');
85212           }
85213
85214           function click(d3_event, d) {
85215             var service = getService();
85216             if (!service) return;
85217             context.map().centerEase(d.loc);
85218             var selectedImageId = service.getActiveImage() && service.getActiveImage().id;
85219             service.getDetections(d.id).then(function (detections) {
85220               if (detections.length) {
85221                 var imageId = detections[0].image.id;
85222
85223                 if (imageId === selectedImageId) {
85224                   service.highlightDetection(detections[0]).selectImage(context, imageId);
85225                 } else {
85226                   service.ensureViewerLoaded(context).then(function () {
85227                     service.highlightDetection(detections[0]).selectImage(context, imageId).showViewer(context);
85228                   });
85229                 }
85230               }
85231             });
85232           }
85233
85234           function filterData(detectedFeatures) {
85235             var fromDate = context.photos().fromDate();
85236             var toDate = context.photos().toDate();
85237
85238             if (fromDate) {
85239               detectedFeatures = detectedFeatures.filter(function (feature) {
85240                 return new Date(feature.last_seen_at).getTime() >= new Date(fromDate).getTime();
85241               });
85242             }
85243
85244             if (toDate) {
85245               detectedFeatures = detectedFeatures.filter(function (feature) {
85246                 return new Date(feature.first_seen_at).getTime() <= new Date(toDate).getTime();
85247               });
85248             }
85249
85250             return detectedFeatures;
85251           }
85252
85253           function update() {
85254             var service = getService();
85255             var data = service ? service.mapFeatures(projection) : [];
85256             data = filterData(data);
85257             var transform = svgPointTransform(projection);
85258             var mapFeatures = layer.selectAll('.icon-map-feature').data(data, function (d) {
85259               return d.id;
85260             }); // exit
85261
85262             mapFeatures.exit().remove(); // enter
85263
85264             var enter = mapFeatures.enter().append('g').attr('class', 'icon-map-feature icon-detected').on('click', click);
85265             enter.append('title').text(function (d) {
85266               var id = d.value.replace(/--/g, '.').replace(/-/g, '_');
85267               return _t('mapillary_map_features.' + id);
85268             });
85269             enter.append('use').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px').attr('xlink:href', function (d) {
85270               if (d.value === 'object--billboard') {
85271                 // no billboard icon right now, so use the advertisement icon
85272                 return '#object--sign--advertisement';
85273               }
85274
85275               return '#' + d.value;
85276             });
85277             enter.append('rect').attr('width', '24px').attr('height', '24px').attr('x', '-12px').attr('y', '-12px'); // update
85278
85279             mapFeatures.merge(enter).attr('transform', transform);
85280           }
85281
85282           function drawMapFeatures(selection) {
85283             var enabled = svgMapillaryMapFeatures.enabled;
85284             var service = getService();
85285             layer = selection.selectAll('.layer-mapillary-map-features').data(service ? [0] : []);
85286             layer.exit().remove();
85287             layer = layer.enter().append('g').attr('class', 'layer-mapillary-map-features layer-mapillary-detections').style('display', enabled ? 'block' : 'none').merge(layer);
85288
85289             if (enabled) {
85290               if (service && ~~context.map().zoom() >= minZoom) {
85291                 editOn();
85292                 update();
85293                 service.loadMapFeatures(projection);
85294                 service.showFeatureDetections(true);
85295               } else {
85296                 editOff();
85297               }
85298             } else if (service) {
85299               service.showFeatureDetections(false);
85300             }
85301           }
85302
85303           drawMapFeatures.enabled = function (_) {
85304             if (!arguments.length) return svgMapillaryMapFeatures.enabled;
85305             svgMapillaryMapFeatures.enabled = _;
85306
85307             if (svgMapillaryMapFeatures.enabled) {
85308               showLayer();
85309               context.photos().on('change.mapillary_map_features', update);
85310             } else {
85311               hideLayer();
85312               context.photos().on('change.mapillary_map_features', null);
85313             }
85314
85315             dispatch.call('change');
85316             return this;
85317           };
85318
85319           drawMapFeatures.supported = function () {
85320             return !!getService();
85321           };
85322
85323           init();
85324           return drawMapFeatures;
85325         }
85326
85327         function svgKartaviewImages(projection, context, dispatch) {
85328           var throttledRedraw = throttle(function () {
85329             dispatch.call('change');
85330           }, 1000);
85331
85332           var minZoom = 12;
85333           var minMarkerZoom = 16;
85334           var minViewfieldZoom = 18;
85335           var layer = select(null);
85336
85337           var _kartaview;
85338
85339           function init() {
85340             if (svgKartaviewImages.initialized) return; // run once
85341
85342             svgKartaviewImages.enabled = false;
85343             svgKartaviewImages.initialized = true;
85344           }
85345
85346           function getService() {
85347             if (services.kartaview && !_kartaview) {
85348               _kartaview = services.kartaview;
85349
85350               _kartaview.event.on('loadedImages', throttledRedraw);
85351             } else if (!services.kartaview && _kartaview) {
85352               _kartaview = null;
85353             }
85354
85355             return _kartaview;
85356           }
85357
85358           function showLayer() {
85359             var service = getService();
85360             if (!service) return;
85361             editOn();
85362             layer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end', function () {
85363               dispatch.call('change');
85364             });
85365           }
85366
85367           function hideLayer() {
85368             throttledRedraw.cancel();
85369             layer.transition().duration(250).style('opacity', 0).on('end', editOff);
85370           }
85371
85372           function editOn() {
85373             layer.style('display', 'block');
85374           }
85375
85376           function editOff() {
85377             layer.selectAll('.viewfield-group').remove();
85378             layer.style('display', 'none');
85379           }
85380
85381           function click(d3_event, d) {
85382             var service = getService();
85383             if (!service) return;
85384             service.ensureViewerLoaded(context).then(function () {
85385               service.selectImage(context, d.key).showViewer(context);
85386             });
85387             context.map().centerEase(d.loc);
85388           }
85389
85390           function mouseover(d3_event, d) {
85391             var service = getService();
85392             if (service) service.setStyles(context, d);
85393           }
85394
85395           function mouseout() {
85396             var service = getService();
85397             if (service) service.setStyles(context, null);
85398           }
85399
85400           function transform(d) {
85401             var t = svgPointTransform(projection)(d);
85402
85403             if (d.ca) {
85404               t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
85405             }
85406
85407             return t;
85408           }
85409
85410           function filterImages(images) {
85411             var fromDate = context.photos().fromDate();
85412             var toDate = context.photos().toDate();
85413             var usernames = context.photos().usernames();
85414
85415             if (fromDate) {
85416               var fromTimestamp = new Date(fromDate).getTime();
85417               images = images.filter(function (item) {
85418                 return new Date(item.captured_at).getTime() >= fromTimestamp;
85419               });
85420             }
85421
85422             if (toDate) {
85423               var toTimestamp = new Date(toDate).getTime();
85424               images = images.filter(function (item) {
85425                 return new Date(item.captured_at).getTime() <= toTimestamp;
85426               });
85427             }
85428
85429             if (usernames) {
85430               images = images.filter(function (item) {
85431                 return usernames.indexOf(item.captured_by) !== -1;
85432               });
85433             }
85434
85435             return images;
85436           }
85437
85438           function filterSequences(sequences) {
85439             var fromDate = context.photos().fromDate();
85440             var toDate = context.photos().toDate();
85441             var usernames = context.photos().usernames();
85442
85443             if (fromDate) {
85444               var fromTimestamp = new Date(fromDate).getTime();
85445               sequences = sequences.filter(function (image) {
85446                 return new Date(image.properties.captured_at).getTime() >= fromTimestamp;
85447               });
85448             }
85449
85450             if (toDate) {
85451               var toTimestamp = new Date(toDate).getTime();
85452               sequences = sequences.filter(function (image) {
85453                 return new Date(image.properties.captured_at).getTime() <= toTimestamp;
85454               });
85455             }
85456
85457             if (usernames) {
85458               sequences = sequences.filter(function (image) {
85459                 return usernames.indexOf(image.properties.captured_by) !== -1;
85460               });
85461             }
85462
85463             return sequences;
85464           }
85465
85466           function update() {
85467             var viewer = context.container().select('.photoviewer');
85468             var selected = viewer.empty() ? undefined : viewer.datum();
85469             var z = ~~context.map().zoom();
85470             var showMarkers = z >= minMarkerZoom;
85471             var showViewfields = z >= minViewfieldZoom;
85472             var service = getService();
85473             var sequences = [];
85474             var images = [];
85475
85476             if (context.photos().showsFlat()) {
85477               sequences = service ? service.sequences(projection) : [];
85478               images = service && showMarkers ? service.images(projection) : [];
85479               sequences = filterSequences(sequences);
85480               images = filterImages(images);
85481             }
85482
85483             var traces = layer.selectAll('.sequences').selectAll('.sequence').data(sequences, function (d) {
85484               return d.properties.key;
85485             }); // exit
85486
85487             traces.exit().remove(); // enter/update
85488
85489             traces = traces.enter().append('path').attr('class', 'sequence').merge(traces).attr('d', svgPath(projection).geojson);
85490             var groups = layer.selectAll('.markers').selectAll('.viewfield-group').data(images, function (d) {
85491               return d.key;
85492             }); // exit
85493
85494             groups.exit().remove(); // enter
85495
85496             var groupsEnter = groups.enter().append('g').attr('class', 'viewfield-group').on('mouseenter', mouseover).on('mouseleave', mouseout).on('click', click);
85497             groupsEnter.append('g').attr('class', 'viewfield-scale'); // update
85498
85499             var markers = groups.merge(groupsEnter).sort(function (a, b) {
85500               return a === selected ? 1 : b === selected ? -1 : b.loc[1] - a.loc[1]; // sort Y
85501             }).attr('transform', transform).select('.viewfield-scale');
85502             markers.selectAll('circle').data([0]).enter().append('circle').attr('dx', '0').attr('dy', '0').attr('r', '6');
85503             var viewfields = markers.selectAll('.viewfield').data(showViewfields ? [0] : []);
85504             viewfields.exit().remove();
85505             viewfields.enter() // viewfields may or may not be drawn...
85506             .insert('path', 'circle') // but if they are, draw below the circles
85507             .attr('class', 'viewfield').attr('transform', 'scale(1.5,1.5),translate(-8, -13)').attr('d', 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z');
85508           }
85509
85510           function drawImages(selection) {
85511             var enabled = svgKartaviewImages.enabled,
85512                 service = getService();
85513             layer = selection.selectAll('.layer-kartaview').data(service ? [0] : []);
85514             layer.exit().remove();
85515             var layerEnter = layer.enter().append('g').attr('class', 'layer-kartaview').style('display', enabled ? 'block' : 'none');
85516             layerEnter.append('g').attr('class', 'sequences');
85517             layerEnter.append('g').attr('class', 'markers');
85518             layer = layerEnter.merge(layer);
85519
85520             if (enabled) {
85521               if (service && ~~context.map().zoom() >= minZoom) {
85522                 editOn();
85523                 update();
85524                 service.loadImages(projection);
85525               } else {
85526                 editOff();
85527               }
85528             }
85529           }
85530
85531           drawImages.enabled = function (_) {
85532             if (!arguments.length) return svgKartaviewImages.enabled;
85533             svgKartaviewImages.enabled = _;
85534
85535             if (svgKartaviewImages.enabled) {
85536               showLayer();
85537               context.photos().on('change.kartaview_images', update);
85538             } else {
85539               hideLayer();
85540               context.photos().on('change.kartaview_images', null);
85541             }
85542
85543             dispatch.call('change');
85544             return this;
85545           };
85546
85547           drawImages.supported = function () {
85548             return !!getService();
85549           };
85550
85551           init();
85552           return drawImages;
85553         }
85554
85555         function svgOsm(projection, context, dispatch) {
85556           var enabled = true;
85557
85558           function drawOsm(selection) {
85559             selection.selectAll('.layer-osm').data(['covered', 'areas', 'lines', 'points', 'labels']).enter().append('g').attr('class', function (d) {
85560               return 'layer-osm ' + d;
85561             });
85562             selection.selectAll('.layer-osm.points').selectAll('.points-group').data(['points', 'midpoints', 'vertices', 'turns']).enter().append('g').attr('class', function (d) {
85563               return 'points-group ' + d;
85564             });
85565           }
85566
85567           function showLayer() {
85568             var layer = context.surface().selectAll('.data-layer.osm');
85569             layer.interrupt();
85570             layer.classed('disabled', false).style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
85571               dispatch.call('change');
85572             });
85573           }
85574
85575           function hideLayer() {
85576             var layer = context.surface().selectAll('.data-layer.osm');
85577             layer.interrupt();
85578             layer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
85579               layer.classed('disabled', true);
85580               dispatch.call('change');
85581             });
85582           }
85583
85584           drawOsm.enabled = function (val) {
85585             if (!arguments.length) return enabled;
85586             enabled = val;
85587
85588             if (enabled) {
85589               showLayer();
85590             } else {
85591               hideLayer();
85592             }
85593
85594             dispatch.call('change');
85595             return this;
85596           };
85597
85598           return drawOsm;
85599         }
85600
85601         var _notesEnabled = false;
85602
85603         var _osmService;
85604
85605         function svgNotes(projection, context, dispatch) {
85606           if (!dispatch) {
85607             dispatch = dispatch$8('change');
85608           }
85609
85610           var throttledRedraw = throttle(function () {
85611             dispatch.call('change');
85612           }, 1000);
85613
85614           var minZoom = 12;
85615           var touchLayer = select(null);
85616           var drawLayer = select(null);
85617           var _notesVisible = false;
85618
85619           function markerPath(selection, klass) {
85620             selection.attr('class', klass).attr('transform', 'translate(-8, -22)').attr('d', 'm17.5,0l-15,0c-1.37,0 -2.5,1.12 -2.5,2.5l0,11.25c0,1.37 1.12,2.5 2.5,2.5l3.75,0l0,3.28c0,0.38 0.43,0.6 0.75,0.37l4.87,-3.65l5.62,0c1.37,0 2.5,-1.12 2.5,-2.5l0,-11.25c0,-1.37 -1.12,-2.5 -2.5,-2.5z');
85621           } // Loosely-coupled osm service for fetching notes.
85622
85623
85624           function getService() {
85625             if (services.osm && !_osmService) {
85626               _osmService = services.osm;
85627
85628               _osmService.on('loadedNotes', throttledRedraw);
85629             } else if (!services.osm && _osmService) {
85630               _osmService = null;
85631             }
85632
85633             return _osmService;
85634           } // Show the notes
85635
85636
85637           function editOn() {
85638             if (!_notesVisible) {
85639               _notesVisible = true;
85640               drawLayer.style('display', 'block');
85641             }
85642           } // Immediately remove the notes and their touch targets
85643
85644
85645           function editOff() {
85646             if (_notesVisible) {
85647               _notesVisible = false;
85648               drawLayer.style('display', 'none');
85649               drawLayer.selectAll('.note').remove();
85650               touchLayer.selectAll('.note').remove();
85651             }
85652           } // Enable the layer.  This shows the notes and transitions them to visible.
85653
85654
85655           function layerOn() {
85656             editOn();
85657             drawLayer.style('opacity', 0).transition().duration(250).style('opacity', 1).on('end interrupt', function () {
85658               dispatch.call('change');
85659             });
85660           } // Disable the layer.  This transitions the layer invisible and then hides the notes.
85661
85662
85663           function layerOff() {
85664             throttledRedraw.cancel();
85665             drawLayer.interrupt();
85666             touchLayer.selectAll('.note').remove();
85667             drawLayer.transition().duration(250).style('opacity', 0).on('end interrupt', function () {
85668               editOff();
85669               dispatch.call('change');
85670             });
85671           } // Update the note markers
85672
85673
85674           function updateMarkers() {
85675             if (!_notesVisible || !_notesEnabled) return;
85676             var service = getService();
85677             var selectedID = context.selectedNoteID();
85678             var data = service ? service.notes(projection) : [];
85679             var getTransform = svgPointTransform(projection); // Draw markers..
85680
85681             var notes = drawLayer.selectAll('.note').data(data, function (d) {
85682               return d.status + d.id;
85683             }); // exit
85684
85685             notes.exit().remove(); // enter
85686
85687             var notesEnter = notes.enter().append('g').attr('class', function (d) {
85688               return 'note note-' + d.id + ' ' + d.status;
85689             }).classed('new', function (d) {
85690               return d.id < 0;
85691             });
85692             notesEnter.append('ellipse').attr('cx', 0.5).attr('cy', 1).attr('rx', 6.5).attr('ry', 3).attr('class', 'stroke');
85693             notesEnter.append('path').call(markerPath, 'shadow');
85694             notesEnter.append('use').attr('class', 'note-fill').attr('width', '20px').attr('height', '20px').attr('x', '-8px').attr('y', '-22px').attr('xlink:href', '#iD-icon-note');
85695             notesEnter.selectAll('.icon-annotation').data(function (d) {
85696               return [d];
85697             }).enter().append('use').attr('class', 'icon-annotation').attr('width', '10px').attr('height', '10px').attr('x', '-3px').attr('y', '-19px').attr('xlink:href', function (d) {
85698               if (d.id < 0) return '#iD-icon-plus';
85699               if (d.status === 'open') return '#iD-icon-close';
85700               return '#iD-icon-apply';
85701             }); // update
85702
85703             notes.merge(notesEnter).sort(sortY).classed('selected', function (d) {
85704               var mode = context.mode();
85705               var isMoving = mode && mode.id === 'drag-note'; // no shadows when dragging
85706
85707               return !isMoving && d.id === selectedID;
85708             }).attr('transform', getTransform); // Draw targets..
85709
85710             if (touchLayer.empty()) return;
85711             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
85712             var targets = touchLayer.selectAll('.note').data(data, function (d) {
85713               return d.id;
85714             }); // exit
85715
85716             targets.exit().remove(); // enter/update
85717
85718             targets.enter().append('rect').attr('width', '20px').attr('height', '20px').attr('x', '-8px').attr('y', '-22px').merge(targets).sort(sortY).attr('class', function (d) {
85719               var newClass = d.id < 0 ? 'new' : '';
85720               return 'note target note-' + d.id + ' ' + fillClass + newClass;
85721             }).attr('transform', getTransform);
85722
85723             function sortY(a, b) {
85724               if (a.id === selectedID) return 1;
85725               if (b.id === selectedID) return -1;
85726               return b.loc[1] - a.loc[1];
85727             }
85728           } // Draw the notes layer and schedule loading notes and updating markers.
85729
85730
85731           function drawNotes(selection) {
85732             var service = getService();
85733             var surface = context.surface();
85734
85735             if (surface && !surface.empty()) {
85736               touchLayer = surface.selectAll('.data-layer.touch .layer-touch.markers');
85737             }
85738
85739             drawLayer = selection.selectAll('.layer-notes').data(service ? [0] : []);
85740             drawLayer.exit().remove();
85741             drawLayer = drawLayer.enter().append('g').attr('class', 'layer-notes').style('display', _notesEnabled ? 'block' : 'none').merge(drawLayer);
85742
85743             if (_notesEnabled) {
85744               if (service && ~~context.map().zoom() >= minZoom) {
85745                 editOn();
85746                 service.loadNotes(projection);
85747                 updateMarkers();
85748               } else {
85749                 editOff();
85750               }
85751             }
85752           } // Toggles the layer on and off
85753
85754
85755           drawNotes.enabled = function (val) {
85756             if (!arguments.length) return _notesEnabled;
85757             _notesEnabled = val;
85758
85759             if (_notesEnabled) {
85760               layerOn();
85761             } else {
85762               layerOff();
85763
85764               if (context.selectedNoteID()) {
85765                 context.enter(modeBrowse(context));
85766               }
85767             }
85768
85769             dispatch.call('change');
85770             return this;
85771           };
85772
85773           return drawNotes;
85774         }
85775
85776         function svgTouch() {
85777           function drawTouch(selection) {
85778             selection.selectAll('.layer-touch').data(['areas', 'lines', 'points', 'turns', 'markers']).enter().append('g').attr('class', function (d) {
85779               return 'layer-touch ' + d;
85780             });
85781           }
85782
85783           return drawTouch;
85784         }
85785
85786         function refresh(selection, node) {
85787           var cr = node.getBoundingClientRect();
85788           var prop = [cr.width, cr.height];
85789           selection.property('__dimensions__', prop);
85790           return prop;
85791         }
85792
85793         function utilGetDimensions(selection, force) {
85794           if (!selection || selection.empty()) {
85795             return [0, 0];
85796           }
85797
85798           var node = selection.node(),
85799               cached = selection.property('__dimensions__');
85800           return !cached || force ? refresh(selection, node) : cached;
85801         }
85802         function utilSetDimensions(selection, dimensions) {
85803           if (!selection || selection.empty()) {
85804             return selection;
85805           }
85806
85807           var node = selection.node();
85808
85809           if (dimensions === null) {
85810             refresh(selection, node);
85811             return selection;
85812           }
85813
85814           return selection.property('__dimensions__', [dimensions[0], dimensions[1]]).attr('width', dimensions[0]).attr('height', dimensions[1]);
85815         }
85816
85817         function svgLayers(projection, context) {
85818           var dispatch = dispatch$8('change');
85819           var svg = select(null);
85820           var _layers = [{
85821             id: 'osm',
85822             layer: svgOsm(projection, context, dispatch)
85823           }, {
85824             id: 'notes',
85825             layer: svgNotes(projection, context, dispatch)
85826           }, {
85827             id: 'data',
85828             layer: svgData(projection, context, dispatch)
85829           }, {
85830             id: 'keepRight',
85831             layer: svgKeepRight(projection, context, dispatch)
85832           }, {
85833             id: 'improveOSM',
85834             layer: svgImproveOSM(projection, context, dispatch)
85835           }, {
85836             id: 'osmose',
85837             layer: svgOsmose(projection, context, dispatch)
85838           }, {
85839             id: 'streetside',
85840             layer: svgStreetside(projection, context, dispatch)
85841           }, {
85842             id: 'mapillary',
85843             layer: svgMapillaryImages(projection, context, dispatch)
85844           }, {
85845             id: 'mapillary-position',
85846             layer: svgMapillaryPosition(projection, context)
85847           }, {
85848             id: 'mapillary-map-features',
85849             layer: svgMapillaryMapFeatures(projection, context, dispatch)
85850           }, {
85851             id: 'mapillary-signs',
85852             layer: svgMapillarySigns(projection, context, dispatch)
85853           }, {
85854             id: 'kartaview',
85855             layer: svgKartaviewImages(projection, context, dispatch)
85856           }, {
85857             id: 'debug',
85858             layer: svgDebug(projection, context)
85859           }, {
85860             id: 'geolocate',
85861             layer: svgGeolocate(projection)
85862           }, {
85863             id: 'touch',
85864             layer: svgTouch()
85865           }];
85866
85867           function drawLayers(selection) {
85868             svg = selection.selectAll('.surface').data([0]);
85869             svg = svg.enter().append('svg').attr('class', 'surface').merge(svg);
85870             var defs = svg.selectAll('.surface-defs').data([0]);
85871             defs.enter().append('defs').attr('class', 'surface-defs');
85872             var groups = svg.selectAll('.data-layer').data(_layers);
85873             groups.exit().remove();
85874             groups.enter().append('g').attr('class', function (d) {
85875               return 'data-layer ' + d.id;
85876             }).merge(groups).each(function (d) {
85877               select(this).call(d.layer);
85878             });
85879           }
85880
85881           drawLayers.all = function () {
85882             return _layers;
85883           };
85884
85885           drawLayers.layer = function (id) {
85886             var obj = _layers.find(function (o) {
85887               return o.id === id;
85888             });
85889
85890             return obj && obj.layer;
85891           };
85892
85893           drawLayers.only = function (what) {
85894             var arr = [].concat(what);
85895
85896             var all = _layers.map(function (layer) {
85897               return layer.id;
85898             });
85899
85900             return drawLayers.remove(utilArrayDifference(all, arr));
85901           };
85902
85903           drawLayers.remove = function (what) {
85904             var arr = [].concat(what);
85905             arr.forEach(function (id) {
85906               _layers = _layers.filter(function (o) {
85907                 return o.id !== id;
85908               });
85909             });
85910             dispatch.call('change');
85911             return this;
85912           };
85913
85914           drawLayers.add = function (what) {
85915             var arr = [].concat(what);
85916             arr.forEach(function (obj) {
85917               if ('id' in obj && 'layer' in obj) {
85918                 _layers.push(obj);
85919               }
85920             });
85921             dispatch.call('change');
85922             return this;
85923           };
85924
85925           drawLayers.dimensions = function (val) {
85926             if (!arguments.length) return utilGetDimensions(svg);
85927             utilSetDimensions(svg, val);
85928             return this;
85929           };
85930
85931           return utilRebind(drawLayers, dispatch, 'on');
85932         }
85933
85934         function svgLines(projection, context) {
85935           var detected = utilDetect();
85936           var highway_stack = {
85937             motorway: 0,
85938             motorway_link: 1,
85939             trunk: 2,
85940             trunk_link: 3,
85941             primary: 4,
85942             primary_link: 5,
85943             secondary: 6,
85944             tertiary: 7,
85945             unclassified: 8,
85946             residential: 9,
85947             service: 10,
85948             footway: 11
85949           };
85950
85951           function drawTargets(selection, graph, entities, filter) {
85952             var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
85953             var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor ';
85954             var getPath = svgPath(projection).geojson;
85955             var activeID = context.activeID();
85956             var base = context.history().base(); // The targets and nopes will be MultiLineString sub-segments of the ways
85957
85958             var data = {
85959               targets: [],
85960               nopes: []
85961             };
85962             entities.forEach(function (way) {
85963               var features = svgSegmentWay(way, graph, activeID);
85964               data.targets.push.apply(data.targets, features.passive);
85965               data.nopes.push.apply(data.nopes, features.active);
85966             }); // Targets allow hover and vertex snapping
85967
85968             var targetData = data.targets.filter(getPath);
85969             var targets = selection.selectAll('.line.target-allowed').filter(function (d) {
85970               return filter(d.properties.entity);
85971             }).data(targetData, function key(d) {
85972               return d.id;
85973             }); // exit
85974
85975             targets.exit().remove();
85976
85977             var segmentWasEdited = function segmentWasEdited(d) {
85978               var wayID = d.properties.entity.id; // if the whole line was edited, don't draw segment changes
85979
85980               if (!base.entities[wayID] || !fastDeepEqual(graph.entities[wayID].nodes, base.entities[wayID].nodes)) {
85981                 return false;
85982               }
85983
85984               return d.properties.nodes.some(function (n) {
85985                 return !base.entities[n.id] || !fastDeepEqual(graph.entities[n.id].loc, base.entities[n.id].loc);
85986               });
85987             }; // enter/update
85988
85989
85990             targets.enter().append('path').merge(targets).attr('d', getPath).attr('class', function (d) {
85991               return 'way line target target-allowed ' + targetClass + d.id;
85992             }).classed('segment-edited', segmentWasEdited); // NOPE
85993
85994             var nopeData = data.nopes.filter(getPath);
85995             var nopes = selection.selectAll('.line.target-nope').filter(function (d) {
85996               return filter(d.properties.entity);
85997             }).data(nopeData, function key(d) {
85998               return d.id;
85999             }); // exit
86000
86001             nopes.exit().remove(); // enter/update
86002
86003             nopes.enter().append('path').merge(nopes).attr('d', getPath).attr('class', function (d) {
86004               return 'way line target target-nope ' + nopeClass + d.id;
86005             }).classed('segment-edited', segmentWasEdited);
86006           }
86007
86008           function drawLines(selection, graph, entities, filter) {
86009             var base = context.history().base();
86010
86011             function waystack(a, b) {
86012               var selected = context.selectedIDs();
86013               var scoreA = selected.indexOf(a.id) !== -1 ? 20 : 0;
86014               var scoreB = selected.indexOf(b.id) !== -1 ? 20 : 0;
86015
86016               if (a.tags.highway) {
86017                 scoreA -= highway_stack[a.tags.highway];
86018               }
86019
86020               if (b.tags.highway) {
86021                 scoreB -= highway_stack[b.tags.highway];
86022               }
86023
86024               return scoreA - scoreB;
86025             }
86026
86027             function drawLineGroup(selection, klass, isSelected) {
86028               // Note: Don't add `.selected` class in draw modes
86029               var mode = context.mode();
86030               var isDrawing = mode && /^draw/.test(mode.id);
86031               var selectedClass = !isDrawing && isSelected ? 'selected ' : '';
86032               var lines = selection.selectAll('path').filter(filter).data(getPathData(isSelected), osmEntity.key);
86033               lines.exit().remove(); // Optimization: Call expensive TagClasses only on enter selection. This
86034               // works because osmEntity.key is defined to include the entity v attribute.
86035
86036               lines.enter().append('path').attr('class', function (d) {
86037                 var prefix = 'way line'; // if this line isn't styled by its own tags
86038
86039                 if (!d.hasInterestingTags()) {
86040                   var parentRelations = graph.parentRelations(d);
86041                   var parentMultipolygons = parentRelations.filter(function (relation) {
86042                     return relation.isMultipolygon();
86043                   }); // and if it's a member of at least one multipolygon relation
86044
86045                   if (parentMultipolygons.length > 0 && // and only multipolygon relations
86046                   parentRelations.length === parentMultipolygons.length) {
86047                     // then fudge the classes to style this as an area edge
86048                     prefix = 'relation area';
86049                   }
86050                 }
86051
86052                 var oldMPClass = oldMultiPolygonOuters[d.id] ? 'old-multipolygon ' : '';
86053                 return prefix + ' ' + klass + ' ' + selectedClass + oldMPClass + d.id;
86054               }).classed('added', function (d) {
86055                 return !base.entities[d.id];
86056               }).classed('geometry-edited', function (d) {
86057                 return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].nodes, base.entities[d.id].nodes);
86058               }).classed('retagged', function (d) {
86059                 return graph.entities[d.id] && base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
86060               }).call(svgTagClasses()).merge(lines).sort(waystack).attr('d', getPath).call(svgTagClasses().tags(svgRelationMemberTags(graph)));
86061               return selection;
86062             }
86063
86064             function getPathData(isSelected) {
86065               return function () {
86066                 var layer = this.parentNode.__data__;
86067                 var data = pathdata[layer] || [];
86068                 return data.filter(function (d) {
86069                   if (isSelected) {
86070                     return context.selectedIDs().indexOf(d.id) !== -1;
86071                   } else {
86072                     return context.selectedIDs().indexOf(d.id) === -1;
86073                   }
86074                 });
86075               };
86076             }
86077
86078             function addMarkers(layergroup, pathclass, groupclass, groupdata, marker) {
86079               var markergroup = layergroup.selectAll('g.' + groupclass).data([pathclass]);
86080               markergroup = markergroup.enter().append('g').attr('class', groupclass).merge(markergroup);
86081               var markers = markergroup.selectAll('path').filter(filter).data(function data() {
86082                 return groupdata[this.parentNode.__data__] || [];
86083               }, function key(d) {
86084                 return [d.id, d.index];
86085               });
86086               markers.exit().remove();
86087               markers = markers.enter().append('path').attr('class', pathclass).merge(markers).attr('marker-mid', marker).attr('d', function (d) {
86088                 return d.d;
86089               });
86090
86091               if (detected.ie) {
86092                 markers.each(function () {
86093                   this.parentNode.insertBefore(this, this);
86094                 });
86095               }
86096             }
86097
86098             var getPath = svgPath(projection, graph);
86099             var ways = [];
86100             var onewaydata = {};
86101             var sideddata = {};
86102             var oldMultiPolygonOuters = {};
86103
86104             for (var i = 0; i < entities.length; i++) {
86105               var entity = entities[i];
86106               var outer = osmOldMultipolygonOuterMember(entity, graph);
86107
86108               if (outer) {
86109                 ways.push(entity.mergeTags(outer.tags));
86110                 oldMultiPolygonOuters[outer.id] = true;
86111               } else if (entity.geometry(graph) === 'line') {
86112                 ways.push(entity);
86113               }
86114             }
86115
86116             ways = ways.filter(getPath);
86117             var pathdata = utilArrayGroupBy(ways, function (way) {
86118               return way.layer();
86119             });
86120             Object.keys(pathdata).forEach(function (k) {
86121               var v = pathdata[k];
86122               var onewayArr = v.filter(function (d) {
86123                 return d.isOneWay();
86124               });
86125               var onewaySegments = svgMarkerSegments(projection, graph, 35, function shouldReverse(entity) {
86126                 return entity.tags.oneway === '-1';
86127               }, function bothDirections(entity) {
86128                 return entity.tags.oneway === 'reversible' || entity.tags.oneway === 'alternating';
86129               });
86130               onewaydata[k] = utilArrayFlatten(onewayArr.map(onewaySegments));
86131               var sidedArr = v.filter(function (d) {
86132                 return d.isSided();
86133               });
86134               var sidedSegments = svgMarkerSegments(projection, graph, 30, function shouldReverse() {
86135                 return false;
86136               }, function bothDirections() {
86137                 return false;
86138               });
86139               sideddata[k] = utilArrayFlatten(sidedArr.map(sidedSegments));
86140             });
86141             var covered = selection.selectAll('.layer-osm.covered'); // under areas
86142
86143             var uncovered = selection.selectAll('.layer-osm.lines'); // over areas
86144
86145             var touchLayer = selection.selectAll('.layer-touch.lines'); // Draw lines..
86146
86147             [covered, uncovered].forEach(function (selection) {
86148               var range = selection === covered ? range$1(-10, 0) : range$1(0, 11);
86149               var layergroup = selection.selectAll('g.layergroup').data(range);
86150               layergroup = layergroup.enter().append('g').attr('class', function (d) {
86151                 return 'layergroup layer' + String(d);
86152               }).merge(layergroup);
86153               layergroup.selectAll('g.linegroup').data(['shadow', 'casing', 'stroke', 'shadow-highlighted', 'casing-highlighted', 'stroke-highlighted']).enter().append('g').attr('class', function (d) {
86154                 return 'linegroup line-' + d;
86155               });
86156               layergroup.selectAll('g.line-shadow').call(drawLineGroup, 'shadow', false);
86157               layergroup.selectAll('g.line-casing').call(drawLineGroup, 'casing', false);
86158               layergroup.selectAll('g.line-stroke').call(drawLineGroup, 'stroke', false);
86159               layergroup.selectAll('g.line-shadow-highlighted').call(drawLineGroup, 'shadow', true);
86160               layergroup.selectAll('g.line-casing-highlighted').call(drawLineGroup, 'casing', true);
86161               layergroup.selectAll('g.line-stroke-highlighted').call(drawLineGroup, 'stroke', true);
86162               addMarkers(layergroup, 'oneway', 'onewaygroup', onewaydata, 'url(#ideditor-oneway-marker)');
86163               addMarkers(layergroup, 'sided', 'sidedgroup', sideddata, function marker(d) {
86164                 var category = graph.entity(d.id).sidednessIdentifier();
86165                 return 'url(#ideditor-sided-marker-' + category + ')';
86166               });
86167             }); // Draw touch targets..
86168
86169             touchLayer.call(drawTargets, graph, ways, filter);
86170           }
86171
86172           return drawLines;
86173         }
86174
86175         function svgMidpoints(projection, context) {
86176           var targetRadius = 8;
86177
86178           function drawTargets(selection, graph, entities, filter) {
86179             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
86180             var getTransform = svgPointTransform(projection).geojson;
86181             var data = entities.map(function (midpoint) {
86182               return {
86183                 type: 'Feature',
86184                 id: midpoint.id,
86185                 properties: {
86186                   target: true,
86187                   entity: midpoint
86188                 },
86189                 geometry: {
86190                   type: 'Point',
86191                   coordinates: midpoint.loc
86192                 }
86193               };
86194             });
86195             var targets = selection.selectAll('.midpoint.target').filter(function (d) {
86196               return filter(d.properties.entity);
86197             }).data(data, function key(d) {
86198               return d.id;
86199             }); // exit
86200
86201             targets.exit().remove(); // enter/update
86202
86203             targets.enter().append('circle').attr('r', targetRadius).merge(targets).attr('class', function (d) {
86204               return 'node midpoint target ' + fillClass + d.id;
86205             }).attr('transform', getTransform);
86206           }
86207
86208           function drawMidpoints(selection, graph, entities, filter, extent) {
86209             var drawLayer = selection.selectAll('.layer-osm.points .points-group.midpoints');
86210             var touchLayer = selection.selectAll('.layer-touch.points');
86211             var mode = context.mode();
86212
86213             if (mode && mode.id !== 'select' || !context.map().withinEditableZoom()) {
86214               drawLayer.selectAll('.midpoint').remove();
86215               touchLayer.selectAll('.midpoint.target').remove();
86216               return;
86217             }
86218
86219             var poly = extent.polygon();
86220             var midpoints = {};
86221
86222             for (var i = 0; i < entities.length; i++) {
86223               var entity = entities[i];
86224               if (entity.type !== 'way') continue;
86225               if (!filter(entity)) continue;
86226               if (context.selectedIDs().indexOf(entity.id) < 0) continue;
86227               var nodes = graph.childNodes(entity);
86228
86229               for (var j = 0; j < nodes.length - 1; j++) {
86230                 var a = nodes[j];
86231                 var b = nodes[j + 1];
86232                 var id = [a.id, b.id].sort().join('-');
86233
86234                 if (midpoints[id]) {
86235                   midpoints[id].parents.push(entity);
86236                 } else if (geoVecLength(projection(a.loc), projection(b.loc)) > 40) {
86237                   var point = geoVecInterp(a.loc, b.loc, 0.5);
86238                   var loc = null;
86239
86240                   if (extent.intersects(point)) {
86241                     loc = point;
86242                   } else {
86243                     for (var k = 0; k < 4; k++) {
86244                       point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
86245
86246                       if (point && geoVecLength(projection(a.loc), projection(point)) > 20 && geoVecLength(projection(b.loc), projection(point)) > 20) {
86247                         loc = point;
86248                         break;
86249                       }
86250                     }
86251                   }
86252
86253                   if (loc) {
86254                     midpoints[id] = {
86255                       type: 'midpoint',
86256                       id: id,
86257                       loc: loc,
86258                       edge: [a.id, b.id],
86259                       parents: [entity]
86260                     };
86261                   }
86262                 }
86263               }
86264             }
86265
86266             function midpointFilter(d) {
86267               if (midpoints[d.id]) return true;
86268
86269               for (var i = 0; i < d.parents.length; i++) {
86270                 if (filter(d.parents[i])) {
86271                   return true;
86272                 }
86273               }
86274
86275               return false;
86276             }
86277
86278             var groups = drawLayer.selectAll('.midpoint').filter(midpointFilter).data(Object.values(midpoints), function (d) {
86279               return d.id;
86280             });
86281             groups.exit().remove();
86282             var enter = groups.enter().insert('g', ':first-child').attr('class', 'midpoint');
86283             enter.append('polygon').attr('points', '-6,8 10,0 -6,-8').attr('class', 'shadow');
86284             enter.append('polygon').attr('points', '-3,4 5,0 -3,-4').attr('class', 'fill');
86285             groups = groups.merge(enter).attr('transform', function (d) {
86286               var translate = svgPointTransform(projection);
86287               var a = graph.entity(d.edge[0]);
86288               var b = graph.entity(d.edge[1]);
86289               var angle = geoAngle(a, b, projection) * (180 / Math.PI);
86290               return translate(d) + ' rotate(' + angle + ')';
86291             }).call(svgTagClasses().tags(function (d) {
86292               return d.parents[0].tags;
86293             })); // Propagate data bindings.
86294
86295             groups.select('polygon.shadow');
86296             groups.select('polygon.fill'); // Draw touch targets..
86297
86298             touchLayer.call(drawTargets, graph, Object.values(midpoints), midpointFilter);
86299           }
86300
86301           return drawMidpoints;
86302         }
86303
86304         function svgPoints(projection, context) {
86305           function markerPath(selection, klass) {
86306             selection.attr('class', klass).attr('transform', 'translate(-8, -23)').attr('d', 'M 17,8 C 17,13 11,21 8.5,23.5 C 6,21 0,13 0,8 C 0,4 4,-0.5 8.5,-0.5 C 13,-0.5 17,4 17,8 z');
86307           }
86308
86309           function sortY(a, b) {
86310             return b.loc[1] - a.loc[1];
86311           } // Avoid exit/enter if we're just moving stuff around.
86312           // The node will get a new version but we only need to run the update selection.
86313
86314
86315           function fastEntityKey(d) {
86316             var mode = context.mode();
86317             var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
86318             return isMoving ? d.id : osmEntity.key(d);
86319           }
86320
86321           function drawTargets(selection, graph, entities, filter) {
86322             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
86323             var getTransform = svgPointTransform(projection).geojson;
86324             var activeID = context.activeID();
86325             var data = [];
86326             entities.forEach(function (node) {
86327               if (activeID === node.id) return; // draw no target on the activeID
86328
86329               data.push({
86330                 type: 'Feature',
86331                 id: node.id,
86332                 properties: {
86333                   target: true,
86334                   entity: node
86335                 },
86336                 geometry: node.asGeoJSON()
86337               });
86338             });
86339             var targets = selection.selectAll('.point.target').filter(function (d) {
86340               return filter(d.properties.entity);
86341             }).data(data, function key(d) {
86342               return d.id;
86343             }); // exit
86344
86345             targets.exit().remove(); // enter/update
86346
86347             targets.enter().append('rect').attr('x', -10).attr('y', -26).attr('width', 20).attr('height', 30).merge(targets).attr('class', function (d) {
86348               return 'node point target ' + fillClass + d.id;
86349             }).attr('transform', getTransform);
86350           }
86351
86352           function drawPoints(selection, graph, entities, filter) {
86353             var wireframe = context.surface().classed('fill-wireframe');
86354             var zoom = geoScaleToZoom(projection.scale());
86355             var base = context.history().base(); // Points with a direction will render as vertices at higher zooms..
86356
86357             function renderAsPoint(entity) {
86358               return entity.geometry(graph) === 'point' && !(zoom >= 18 && entity.directions(graph, projection).length);
86359             } // All points will render as vertices in wireframe mode too..
86360
86361
86362             var points = wireframe ? [] : entities.filter(renderAsPoint);
86363             points.sort(sortY);
86364             var drawLayer = selection.selectAll('.layer-osm.points .points-group.points');
86365             var touchLayer = selection.selectAll('.layer-touch.points'); // Draw points..
86366
86367             var groups = drawLayer.selectAll('g.point').filter(filter).data(points, fastEntityKey);
86368             groups.exit().remove();
86369             var enter = groups.enter().append('g').attr('class', function (d) {
86370               return 'node point ' + d.id;
86371             }).order();
86372             enter.append('path').call(markerPath, 'shadow');
86373             enter.append('ellipse').attr('cx', 0.5).attr('cy', 1).attr('rx', 6.5).attr('ry', 3).attr('class', 'stroke');
86374             enter.append('path').call(markerPath, 'stroke');
86375             enter.append('use').attr('transform', 'translate(-5, -19)').attr('class', 'icon').attr('width', '11px').attr('height', '11px');
86376             groups = groups.merge(enter).attr('transform', svgPointTransform(projection)).classed('added', function (d) {
86377               return !base.entities[d.id]; // if it doesn't exist in the base graph, it's new
86378             }).classed('moved', function (d) {
86379               return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].loc, base.entities[d.id].loc);
86380             }).classed('retagged', function (d) {
86381               return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
86382             }).call(svgTagClasses());
86383             groups.select('.shadow'); // propagate bound data
86384
86385             groups.select('.stroke'); // propagate bound data
86386
86387             groups.select('.icon') // propagate bound data
86388             .attr('xlink:href', function (entity) {
86389               var preset = _mainPresetIndex.match(entity, graph);
86390               var picon = preset && preset.icon;
86391
86392               if (!picon) {
86393                 return '';
86394               } else {
86395                 var isMaki = /^maki-/.test(picon);
86396                 return '#' + picon + (isMaki ? '-11' : '');
86397               }
86398             }); // Draw touch targets..
86399
86400             touchLayer.call(drawTargets, graph, points, filter);
86401           }
86402
86403           return drawPoints;
86404         }
86405
86406         function svgTurns(projection, context) {
86407           function icon(turn) {
86408             var u = turn.u ? '-u' : '';
86409             if (turn.no) return '#iD-turn-no' + u;
86410             if (turn.only) return '#iD-turn-only' + u;
86411             return '#iD-turn-yes' + u;
86412           }
86413
86414           function drawTurns(selection, graph, turns) {
86415             function turnTransform(d) {
86416               var pxRadius = 50;
86417               var toWay = graph.entity(d.to.way);
86418               var toPoints = graph.childNodes(toWay).map(function (n) {
86419                 return n.loc;
86420               }).map(projection);
86421               var toLength = geoPathLength(toPoints);
86422               var mid = toLength / 2; // midpoint of destination way
86423
86424               var toNode = graph.entity(d.to.node);
86425               var toVertex = graph.entity(d.to.vertex);
86426               var a = geoAngle(toVertex, toNode, projection);
86427               var o = projection(toVertex.loc);
86428               var r = d.u ? 0 // u-turn: no radius
86429               : !toWay.__via ? pxRadius // leaf way: put marker at pxRadius
86430               : Math.min(mid, pxRadius); // via way: prefer pxRadius, fallback to mid for very short ways
86431
86432               return 'translate(' + (r * Math.cos(a) + o[0]) + ',' + (r * Math.sin(a) + o[1]) + ') ' + 'rotate(' + a * 180 / Math.PI + ')';
86433             }
86434
86435             var drawLayer = selection.selectAll('.layer-osm.points .points-group.turns');
86436             var touchLayer = selection.selectAll('.layer-touch.turns'); // Draw turns..
86437
86438             var groups = drawLayer.selectAll('g.turn').data(turns, function (d) {
86439               return d.key;
86440             }); // exit
86441
86442             groups.exit().remove(); // enter
86443
86444             var groupsEnter = groups.enter().append('g').attr('class', function (d) {
86445               return 'turn ' + d.key;
86446             });
86447             var turnsEnter = groupsEnter.filter(function (d) {
86448               return !d.u;
86449             });
86450             turnsEnter.append('rect').attr('transform', 'translate(-22, -12)').attr('width', '44').attr('height', '24');
86451             turnsEnter.append('use').attr('transform', 'translate(-22, -12)').attr('width', '44').attr('height', '24');
86452             var uEnter = groupsEnter.filter(function (d) {
86453               return d.u;
86454             });
86455             uEnter.append('circle').attr('r', '16');
86456             uEnter.append('use').attr('transform', 'translate(-16, -16)').attr('width', '32').attr('height', '32'); // update
86457
86458             groups = groups.merge(groupsEnter).attr('opacity', function (d) {
86459               return d.direct === false ? '0.7' : null;
86460             }).attr('transform', turnTransform);
86461             groups.select('use').attr('xlink:href', icon);
86462             groups.select('rect'); // propagate bound data
86463
86464             groups.select('circle'); // propagate bound data
86465             // Draw touch targets..
86466
86467             var fillClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
86468             groups = touchLayer.selectAll('g.turn').data(turns, function (d) {
86469               return d.key;
86470             }); // exit
86471
86472             groups.exit().remove(); // enter
86473
86474             groupsEnter = groups.enter().append('g').attr('class', function (d) {
86475               return 'turn ' + d.key;
86476             });
86477             turnsEnter = groupsEnter.filter(function (d) {
86478               return !d.u;
86479             });
86480             turnsEnter.append('rect').attr('class', 'target ' + fillClass).attr('transform', 'translate(-22, -12)').attr('width', '44').attr('height', '24');
86481             uEnter = groupsEnter.filter(function (d) {
86482               return d.u;
86483             });
86484             uEnter.append('circle').attr('class', 'target ' + fillClass).attr('r', '16'); // update
86485
86486             groups = groups.merge(groupsEnter).attr('transform', turnTransform);
86487             groups.select('rect'); // propagate bound data
86488
86489             groups.select('circle'); // propagate bound data
86490
86491             return this;
86492           }
86493
86494           return drawTurns;
86495         }
86496
86497         function svgVertices(projection, context) {
86498           var radiuses = {
86499             //       z16-, z17,   z18+,  w/icon
86500             shadow: [6, 7.5, 7.5, 12],
86501             stroke: [2.5, 3.5, 3.5, 8],
86502             fill: [1, 1.5, 1.5, 1.5]
86503           };
86504
86505           var _currHoverTarget;
86506
86507           var _currPersistent = {};
86508           var _currHover = {};
86509           var _prevHover = {};
86510           var _currSelected = {};
86511           var _prevSelected = {};
86512           var _radii = {};
86513
86514           function sortY(a, b) {
86515             return b.loc[1] - a.loc[1];
86516           } // Avoid exit/enter if we're just moving stuff around.
86517           // The node will get a new version but we only need to run the update selection.
86518
86519
86520           function fastEntityKey(d) {
86521             var mode = context.mode();
86522             var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
86523             return isMoving ? d.id : osmEntity.key(d);
86524           }
86525
86526           function draw(selection, graph, vertices, sets, filter) {
86527             sets = sets || {
86528               selected: {},
86529               important: {},
86530               hovered: {}
86531             };
86532             var icons = {};
86533             var directions = {};
86534             var wireframe = context.surface().classed('fill-wireframe');
86535             var zoom = geoScaleToZoom(projection.scale());
86536             var z = zoom < 17 ? 0 : zoom < 18 ? 1 : 2;
86537             var activeID = context.activeID();
86538             var base = context.history().base();
86539
86540             function getIcon(d) {
86541               // always check latest entity, as fastEntityKey avoids enter/exit now
86542               var entity = graph.entity(d.id);
86543               if (entity.id in icons) return icons[entity.id];
86544               icons[entity.id] = entity.hasInterestingTags() && _mainPresetIndex.match(entity, graph).icon;
86545               return icons[entity.id];
86546             } // memoize directions results, return false for empty arrays (for use in filter)
86547
86548
86549             function getDirections(entity) {
86550               if (entity.id in directions) return directions[entity.id];
86551               var angles = entity.directions(graph, projection);
86552               directions[entity.id] = angles.length ? angles : false;
86553               return angles;
86554             }
86555
86556             function updateAttributes(selection) {
86557               ['shadow', 'stroke', 'fill'].forEach(function (klass) {
86558                 var rads = radiuses[klass];
86559                 selection.selectAll('.' + klass).each(function (entity) {
86560                   var i = z && getIcon(entity);
86561                   var r = rads[i ? 3 : z]; // slightly increase the size of unconnected endpoints #3775
86562
86563                   if (entity.id !== activeID && entity.isEndpoint(graph) && !entity.isConnected(graph)) {
86564                     r += 1.5;
86565                   }
86566
86567                   if (klass === 'shadow') {
86568                     // remember this value, so we don't need to
86569                     _radii[entity.id] = r; // recompute it when we draw the touch targets
86570                   }
86571
86572                   select(this).attr('r', r).attr('visibility', i && klass === 'fill' ? 'hidden' : null);
86573                 });
86574               });
86575             }
86576
86577             vertices.sort(sortY);
86578             var groups = selection.selectAll('g.vertex').filter(filter).data(vertices, fastEntityKey); // exit
86579
86580             groups.exit().remove(); // enter
86581
86582             var enter = groups.enter().append('g').attr('class', function (d) {
86583               return 'node vertex ' + d.id;
86584             }).order();
86585             enter.append('circle').attr('class', 'shadow');
86586             enter.append('circle').attr('class', 'stroke'); // Vertices with tags get a fill.
86587
86588             enter.filter(function (d) {
86589               return d.hasInterestingTags();
86590             }).append('circle').attr('class', 'fill'); // update
86591
86592             groups = groups.merge(enter).attr('transform', svgPointTransform(projection)).classed('sibling', function (d) {
86593               return d.id in sets.selected;
86594             }).classed('shared', function (d) {
86595               return graph.isShared(d);
86596             }).classed('endpoint', function (d) {
86597               return d.isEndpoint(graph);
86598             }).classed('added', function (d) {
86599               return !base.entities[d.id]; // if it doesn't exist in the base graph, it's new
86600             }).classed('moved', function (d) {
86601               return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].loc, base.entities[d.id].loc);
86602             }).classed('retagged', function (d) {
86603               return base.entities[d.id] && !fastDeepEqual(graph.entities[d.id].tags, base.entities[d.id].tags);
86604             }).call(updateAttributes); // Vertices with icons get a `use`.
86605
86606             var iconUse = groups.selectAll('.icon').data(function data(d) {
86607               return zoom >= 17 && getIcon(d) ? [d] : [];
86608             }, fastEntityKey); // exit
86609
86610             iconUse.exit().remove(); // enter
86611
86612             iconUse.enter().append('use').attr('class', 'icon').attr('width', '11px').attr('height', '11px').attr('transform', 'translate(-5.5, -5.5)').attr('xlink:href', function (d) {
86613               var picon = getIcon(d);
86614               var isMaki = /^maki-/.test(picon);
86615               return '#' + picon + (isMaki ? '-11' : '');
86616             }); // Vertices with directions get viewfields
86617
86618             var dgroups = groups.selectAll('.viewfieldgroup').data(function data(d) {
86619               return zoom >= 18 && getDirections(d) ? [d] : [];
86620             }, fastEntityKey); // exit
86621
86622             dgroups.exit().remove(); // enter/update
86623
86624             dgroups = dgroups.enter().insert('g', '.shadow').attr('class', 'viewfieldgroup').merge(dgroups);
86625             var viewfields = dgroups.selectAll('.viewfield').data(getDirections, function key(d) {
86626               return osmEntity.key(d);
86627             }); // exit
86628
86629             viewfields.exit().remove(); // enter/update
86630
86631             viewfields.enter().append('path').attr('class', 'viewfield').attr('d', 'M0,0H0').merge(viewfields).attr('marker-start', 'url(#ideditor-viewfield-marker' + (wireframe ? '-wireframe' : '') + ')').attr('transform', function (d) {
86632               return 'rotate(' + d + ')';
86633             });
86634           }
86635
86636           function drawTargets(selection, graph, entities, filter) {
86637             var targetClass = context.getDebug('target') ? 'pink ' : 'nocolor ';
86638             var nopeClass = context.getDebug('target') ? 'red ' : 'nocolor ';
86639             var getTransform = svgPointTransform(projection).geojson;
86640             var activeID = context.activeID();
86641             var data = {
86642               targets: [],
86643               nopes: []
86644             };
86645             entities.forEach(function (node) {
86646               if (activeID === node.id) return; // draw no target on the activeID
86647
86648               var vertexType = svgPassiveVertex(node, graph, activeID);
86649
86650               if (vertexType !== 0) {
86651                 // passive or adjacent - allow to connect
86652                 data.targets.push({
86653                   type: 'Feature',
86654                   id: node.id,
86655                   properties: {
86656                     target: true,
86657                     entity: node
86658                   },
86659                   geometry: node.asGeoJSON()
86660                 });
86661               } else {
86662                 data.nopes.push({
86663                   type: 'Feature',
86664                   id: node.id + '-nope',
86665                   properties: {
86666                     nope: true,
86667                     target: true,
86668                     entity: node
86669                   },
86670                   geometry: node.asGeoJSON()
86671                 });
86672               }
86673             }); // Targets allow hover and vertex snapping
86674
86675             var targets = selection.selectAll('.vertex.target-allowed').filter(function (d) {
86676               return filter(d.properties.entity);
86677             }).data(data.targets, function key(d) {
86678               return d.id;
86679             }); // exit
86680
86681             targets.exit().remove(); // enter/update
86682
86683             targets.enter().append('circle').attr('r', function (d) {
86684               return _radii[d.id] || radiuses.shadow[3];
86685             }).merge(targets).attr('class', function (d) {
86686               return 'node vertex target target-allowed ' + targetClass + d.id;
86687             }).attr('transform', getTransform); // NOPE
86688
86689             var nopes = selection.selectAll('.vertex.target-nope').filter(function (d) {
86690               return filter(d.properties.entity);
86691             }).data(data.nopes, function key(d) {
86692               return d.id;
86693             }); // exit
86694
86695             nopes.exit().remove(); // enter/update
86696
86697             nopes.enter().append('circle').attr('r', function (d) {
86698               return _radii[d.properties.entity.id] || radiuses.shadow[3];
86699             }).merge(nopes).attr('class', function (d) {
86700               return 'node vertex target target-nope ' + nopeClass + d.id;
86701             }).attr('transform', getTransform);
86702           } // Points can also render as vertices:
86703           // 1. in wireframe mode or
86704           // 2. at higher zooms if they have a direction
86705
86706
86707           function renderAsVertex(entity, graph, wireframe, zoom) {
86708             var geometry = entity.geometry(graph);
86709             return geometry === 'vertex' || geometry === 'point' && (wireframe || zoom >= 18 && entity.directions(graph, projection).length);
86710           }
86711
86712           function isEditedNode(node, base, head) {
86713             var baseNode = base.entities[node.id];
86714             var headNode = head.entities[node.id];
86715             return !headNode || !baseNode || !fastDeepEqual(headNode.tags, baseNode.tags) || !fastDeepEqual(headNode.loc, baseNode.loc);
86716           }
86717
86718           function getSiblingAndChildVertices(ids, graph, wireframe, zoom) {
86719             var results = {};
86720             var seenIds = {};
86721
86722             function addChildVertices(entity) {
86723               // avoid redundant work and infinite recursion of circular relations
86724               if (seenIds[entity.id]) return;
86725               seenIds[entity.id] = true;
86726               var geometry = entity.geometry(graph);
86727
86728               if (!context.features().isHiddenFeature(entity, graph, geometry)) {
86729                 var i;
86730
86731                 if (entity.type === 'way') {
86732                   for (i = 0; i < entity.nodes.length; i++) {
86733                     var child = graph.hasEntity(entity.nodes[i]);
86734
86735                     if (child) {
86736                       addChildVertices(child);
86737                     }
86738                   }
86739                 } else if (entity.type === 'relation') {
86740                   for (i = 0; i < entity.members.length; i++) {
86741                     var member = graph.hasEntity(entity.members[i].id);
86742
86743                     if (member) {
86744                       addChildVertices(member);
86745                     }
86746                   }
86747                 } else if (renderAsVertex(entity, graph, wireframe, zoom)) {
86748                   results[entity.id] = entity;
86749                 }
86750               }
86751             }
86752
86753             ids.forEach(function (id) {
86754               var entity = graph.hasEntity(id);
86755               if (!entity) return;
86756
86757               if (entity.type === 'node') {
86758                 if (renderAsVertex(entity, graph, wireframe, zoom)) {
86759                   results[entity.id] = entity;
86760                   graph.parentWays(entity).forEach(function (entity) {
86761                     addChildVertices(entity);
86762                   });
86763                 }
86764               } else {
86765                 // way, relation
86766                 addChildVertices(entity);
86767               }
86768             });
86769             return results;
86770           }
86771
86772           function drawVertices(selection, graph, entities, filter, extent, fullRedraw) {
86773             var wireframe = context.surface().classed('fill-wireframe');
86774             var visualDiff = context.surface().classed('highlight-edited');
86775             var zoom = geoScaleToZoom(projection.scale());
86776             var mode = context.mode();
86777             var isMoving = mode && /^(add|draw|drag|move|rotate)/.test(mode.id);
86778             var base = context.history().base();
86779             var drawLayer = selection.selectAll('.layer-osm.points .points-group.vertices');
86780             var touchLayer = selection.selectAll('.layer-touch.points');
86781
86782             if (fullRedraw) {
86783               _currPersistent = {};
86784               _radii = {};
86785             } // Collect important vertices from the `entities` list..
86786             // (during a partial redraw, it will not contain everything)
86787
86788
86789             for (var i = 0; i < entities.length; i++) {
86790               var entity = entities[i];
86791               var geometry = entity.geometry(graph);
86792               var keep = false; // a point that looks like a vertex..
86793
86794               if (geometry === 'point' && renderAsVertex(entity, graph, wireframe, zoom)) {
86795                 _currPersistent[entity.id] = entity;
86796                 keep = true; // a vertex of some importance..
86797               } else if (geometry === 'vertex' && (entity.hasInterestingTags() || entity.isEndpoint(graph) || entity.isConnected(graph) || visualDiff && isEditedNode(entity, base, graph))) {
86798                 _currPersistent[entity.id] = entity;
86799                 keep = true;
86800               } // whatever this is, it's not a persistent vertex..
86801
86802
86803               if (!keep && !fullRedraw) {
86804                 delete _currPersistent[entity.id];
86805               }
86806             } // 3 sets of vertices to consider:
86807
86808
86809             var sets = {
86810               persistent: _currPersistent,
86811               // persistent = important vertices (render always)
86812               selected: _currSelected,
86813               // selected + siblings of selected (render always)
86814               hovered: _currHover // hovered + siblings of hovered (render only in draw modes)
86815
86816             };
86817             var all = Object.assign({}, isMoving ? _currHover : {}, _currSelected, _currPersistent); // Draw the vertices..
86818             // The filter function controls the scope of what objects d3 will touch (exit/enter/update)
86819             // Adjust the filter function to expand the scope beyond whatever entities were passed in.
86820
86821             var filterRendered = function filterRendered(d) {
86822               return d.id in _currPersistent || d.id in _currSelected || d.id in _currHover || filter(d);
86823             };
86824
86825             drawLayer.call(draw, graph, currentVisible(all), sets, filterRendered); // Draw touch targets..
86826             // When drawing, render all targets (not just those affected by a partial redraw)
86827
86828             var filterTouch = function filterTouch(d) {
86829               return isMoving ? true : filterRendered(d);
86830             };
86831
86832             touchLayer.call(drawTargets, graph, currentVisible(all), filterTouch);
86833
86834             function currentVisible(which) {
86835               return Object.keys(which).map(graph.hasEntity, graph) // the current version of this entity
86836               .filter(function (entity) {
86837                 return entity && entity.intersects(extent, graph);
86838               });
86839             }
86840           } // partial redraw - only update the selected items..
86841
86842
86843           drawVertices.drawSelected = function (selection, graph, extent) {
86844             var wireframe = context.surface().classed('fill-wireframe');
86845             var zoom = geoScaleToZoom(projection.scale());
86846             _prevSelected = _currSelected || {};
86847
86848             if (context.map().isInWideSelection()) {
86849               _currSelected = {};
86850               context.selectedIDs().forEach(function (id) {
86851                 var entity = graph.hasEntity(id);
86852                 if (!entity) return;
86853
86854                 if (entity.type === 'node') {
86855                   if (renderAsVertex(entity, graph, wireframe, zoom)) {
86856                     _currSelected[entity.id] = entity;
86857                   }
86858                 }
86859               });
86860             } else {
86861               _currSelected = getSiblingAndChildVertices(context.selectedIDs(), graph, wireframe, zoom);
86862             } // note that drawVertices will add `_currSelected` automatically if needed..
86863
86864
86865             var filter = function filter(d) {
86866               return d.id in _prevSelected;
86867             };
86868
86869             drawVertices(selection, graph, Object.values(_prevSelected), filter, extent, false);
86870           }; // partial redraw - only update the hovered items..
86871
86872
86873           drawVertices.drawHover = function (selection, graph, target, extent) {
86874             if (target === _currHoverTarget) return; // continue only if something changed
86875
86876             var wireframe = context.surface().classed('fill-wireframe');
86877             var zoom = geoScaleToZoom(projection.scale());
86878             _prevHover = _currHover || {};
86879             _currHoverTarget = target;
86880             var entity = target && target.properties && target.properties.entity;
86881
86882             if (entity) {
86883               _currHover = getSiblingAndChildVertices([entity.id], graph, wireframe, zoom);
86884             } else {
86885               _currHover = {};
86886             } // note that drawVertices will add `_currHover` automatically if needed..
86887
86888
86889             var filter = function filter(d) {
86890               return d.id in _prevHover;
86891             };
86892
86893             drawVertices(selection, graph, Object.values(_prevHover), filter, extent, false);
86894           };
86895
86896           return drawVertices;
86897         }
86898
86899         function utilBindOnce(target, type, listener, capture) {
86900           var typeOnce = type + '.once';
86901
86902           function one() {
86903             target.on(typeOnce, null);
86904             listener.apply(this, arguments);
86905           }
86906
86907           target.on(typeOnce, one, capture);
86908           return this;
86909         }
86910
86911         function defaultFilter(d3_event) {
86912           return !d3_event.ctrlKey && !d3_event.button;
86913         }
86914
86915         function defaultExtent() {
86916           var e = this;
86917
86918           if (e instanceof SVGElement) {
86919             e = e.ownerSVGElement || e;
86920
86921             if (e.hasAttribute('viewBox')) {
86922               e = e.viewBox.baseVal;
86923               return [[e.x, e.y], [e.x + e.width, e.y + e.height]];
86924             }
86925
86926             return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]];
86927           }
86928
86929           return [[0, 0], [e.clientWidth, e.clientHeight]];
86930         }
86931
86932         function defaultWheelDelta(d3_event) {
86933           return -d3_event.deltaY * (d3_event.deltaMode === 1 ? 0.05 : d3_event.deltaMode ? 1 : 0.002);
86934         }
86935
86936         function defaultConstrain(transform, extent, translateExtent) {
86937           var dx0 = transform.invertX(extent[0][0]) - translateExtent[0][0],
86938               dx1 = transform.invertX(extent[1][0]) - translateExtent[1][0],
86939               dy0 = transform.invertY(extent[0][1]) - translateExtent[0][1],
86940               dy1 = transform.invertY(extent[1][1]) - translateExtent[1][1];
86941           return transform.translate(dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1), dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1));
86942         }
86943
86944         function utilZoomPan() {
86945           var filter = defaultFilter,
86946               extent = defaultExtent,
86947               constrain = defaultConstrain,
86948               wheelDelta = defaultWheelDelta,
86949               scaleExtent = [0, Infinity],
86950               translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]],
86951               interpolate = interpolateZoom,
86952               dispatch = dispatch$8('start', 'zoom', 'end'),
86953               _wheelDelay = 150,
86954               _transform = identity$2,
86955               _activeGesture;
86956
86957           function zoom(selection) {
86958             selection.on('pointerdown.zoom', pointerdown).on('wheel.zoom', wheeled).style('touch-action', 'none').style('-webkit-tap-highlight-color', 'rgba(0,0,0,0)');
86959             select(window).on('pointermove.zoompan', pointermove).on('pointerup.zoompan pointercancel.zoompan', pointerup);
86960           }
86961
86962           zoom.transform = function (collection, transform, point) {
86963             var selection = collection.selection ? collection.selection() : collection;
86964
86965             if (collection !== selection) {
86966               schedule(collection, transform, point);
86967             } else {
86968               selection.interrupt().each(function () {
86969                 gesture(this, arguments).start(null).zoom(null, null, typeof transform === 'function' ? transform.apply(this, arguments) : transform).end(null);
86970               });
86971             }
86972           };
86973
86974           zoom.scaleBy = function (selection, k, p) {
86975             zoom.scaleTo(selection, function () {
86976               var k0 = _transform.k,
86977                   k1 = typeof k === 'function' ? k.apply(this, arguments) : k;
86978               return k0 * k1;
86979             }, p);
86980           };
86981
86982           zoom.scaleTo = function (selection, k, p) {
86983             zoom.transform(selection, function () {
86984               var e = extent.apply(this, arguments),
86985                   t0 = _transform,
86986                   p0 = !p ? centroid(e) : typeof p === 'function' ? p.apply(this, arguments) : p,
86987                   p1 = t0.invert(p0),
86988                   k1 = typeof k === 'function' ? k.apply(this, arguments) : k;
86989               return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent);
86990             }, p);
86991           };
86992
86993           zoom.translateBy = function (selection, x, y) {
86994             zoom.transform(selection, function () {
86995               return constrain(_transform.translate(typeof x === 'function' ? x.apply(this, arguments) : x, typeof y === 'function' ? y.apply(this, arguments) : y), extent.apply(this, arguments), translateExtent);
86996             });
86997           };
86998
86999           zoom.translateTo = function (selection, x, y, p) {
87000             zoom.transform(selection, function () {
87001               var e = extent.apply(this, arguments),
87002                   t = _transform,
87003                   p0 = !p ? centroid(e) : typeof p === 'function' ? p.apply(this, arguments) : p;
87004               return constrain(identity$2.translate(p0[0], p0[1]).scale(t.k).translate(typeof x === 'function' ? -x.apply(this, arguments) : -x, typeof y === 'function' ? -y.apply(this, arguments) : -y), e, translateExtent);
87005             }, p);
87006           };
87007
87008           function scale(transform, k) {
87009             k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k));
87010             return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
87011           }
87012
87013           function translate(transform, p0, p1) {
87014             var x = p0[0] - p1[0] * transform.k,
87015                 y = p0[1] - p1[1] * transform.k;
87016             return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
87017           }
87018
87019           function centroid(extent) {
87020             return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
87021           }
87022
87023           function schedule(transition, transform, point) {
87024             transition.on('start.zoom', function () {
87025               gesture(this, arguments).start(null);
87026             }).on('interrupt.zoom end.zoom', function () {
87027               gesture(this, arguments).end(null);
87028             }).tween('zoom', function () {
87029               var that = this,
87030                   args = arguments,
87031                   g = gesture(that, args),
87032                   e = extent.apply(that, args),
87033                   p = !point ? centroid(e) : typeof point === 'function' ? point.apply(that, args) : point,
87034                   w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
87035                   a = _transform,
87036                   b = typeof transform === 'function' ? transform.apply(that, args) : transform,
87037                   i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
87038               return function (t) {
87039                 if (t === 1) {
87040                   // Avoid rounding error on end.
87041                   t = b;
87042                 } else {
87043                   var l = i(t);
87044                   var k = w / l[2];
87045                   t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k);
87046                 }
87047
87048                 g.zoom(null, null, t);
87049               };
87050             });
87051           }
87052
87053           function gesture(that, args, clean) {
87054             return !clean && _activeGesture || new Gesture(that, args);
87055           }
87056
87057           function Gesture(that, args) {
87058             this.that = that;
87059             this.args = args;
87060             this.active = 0;
87061             this.extent = extent.apply(that, args);
87062           }
87063
87064           Gesture.prototype = {
87065             start: function start(d3_event) {
87066               if (++this.active === 1) {
87067                 _activeGesture = this;
87068                 dispatch.call('start', this, d3_event);
87069               }
87070
87071               return this;
87072             },
87073             zoom: function zoom(d3_event, key, transform) {
87074               if (this.mouse && key !== 'mouse') this.mouse[1] = transform.invert(this.mouse[0]);
87075               if (this.pointer0 && key !== 'touch') this.pointer0[1] = transform.invert(this.pointer0[0]);
87076               if (this.pointer1 && key !== 'touch') this.pointer1[1] = transform.invert(this.pointer1[0]);
87077               _transform = transform;
87078               dispatch.call('zoom', this, d3_event, key, transform);
87079               return this;
87080             },
87081             end: function end(d3_event) {
87082               if (--this.active === 0) {
87083                 _activeGesture = null;
87084                 dispatch.call('end', this, d3_event);
87085               }
87086
87087               return this;
87088             }
87089           };
87090
87091           function wheeled(d3_event) {
87092             if (!filter.apply(this, arguments)) return;
87093             var g = gesture(this, arguments),
87094                 t = _transform,
87095                 k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))),
87096                 p = utilFastMouse(this)(d3_event); // If the mouse is in the same location as before, reuse it.
87097             // If there were recent wheel events, reset the wheel idle timeout.
87098
87099             if (g.wheel) {
87100               if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
87101                 g.mouse[1] = t.invert(g.mouse[0] = p);
87102               }
87103
87104               clearTimeout(g.wheel); // Otherwise, capture the mouse point and location at the start.
87105             } else {
87106               g.mouse = [p, t.invert(p)];
87107               interrupt(this);
87108               g.start(d3_event);
87109             }
87110
87111             d3_event.preventDefault();
87112             d3_event.stopImmediatePropagation();
87113             g.wheel = setTimeout(wheelidled, _wheelDelay);
87114             g.zoom(d3_event, 'mouse', constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent));
87115
87116             function wheelidled() {
87117               g.wheel = null;
87118               g.end(d3_event);
87119             }
87120           }
87121
87122           var _downPointerIDs = new Set();
87123
87124           var _pointerLocGetter;
87125
87126           function pointerdown(d3_event) {
87127             _downPointerIDs.add(d3_event.pointerId);
87128
87129             if (!filter.apply(this, arguments)) return;
87130             var g = gesture(this, arguments, _downPointerIDs.size === 1);
87131             var started;
87132             d3_event.stopImmediatePropagation();
87133             _pointerLocGetter = utilFastMouse(this);
87134
87135             var loc = _pointerLocGetter(d3_event);
87136
87137             var p = [loc, _transform.invert(loc), d3_event.pointerId];
87138
87139             if (!g.pointer0) {
87140               g.pointer0 = p;
87141               started = true;
87142             } else if (!g.pointer1 && g.pointer0[2] !== p[2]) {
87143               g.pointer1 = p;
87144             }
87145
87146             if (started) {
87147               interrupt(this);
87148               g.start(d3_event);
87149             }
87150           }
87151
87152           function pointermove(d3_event) {
87153             if (!_downPointerIDs.has(d3_event.pointerId)) return;
87154             if (!_activeGesture || !_pointerLocGetter) return;
87155             var g = gesture(this, arguments);
87156             var isPointer0 = g.pointer0 && g.pointer0[2] === d3_event.pointerId;
87157             var isPointer1 = !isPointer0 && g.pointer1 && g.pointer1[2] === d3_event.pointerId;
87158
87159             if ((isPointer0 || isPointer1) && 'buttons' in d3_event && !d3_event.buttons) {
87160               // The pointer went up without ending the gesture somehow, e.g.
87161               // a down mouse was moved off the map and released. End it here.
87162               if (g.pointer0) _downPointerIDs["delete"](g.pointer0[2]);
87163               if (g.pointer1) _downPointerIDs["delete"](g.pointer1[2]);
87164               g.end(d3_event);
87165               return;
87166             }
87167
87168             d3_event.preventDefault();
87169             d3_event.stopImmediatePropagation();
87170
87171             var loc = _pointerLocGetter(d3_event);
87172
87173             var t, p, l;
87174             if (isPointer0) g.pointer0[0] = loc;else if (isPointer1) g.pointer1[0] = loc;
87175             t = _transform;
87176
87177             if (g.pointer1) {
87178               var p0 = g.pointer0[0],
87179                   l0 = g.pointer0[1],
87180                   p1 = g.pointer1[0],
87181                   l1 = g.pointer1[1],
87182                   dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
87183                   dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
87184               t = scale(t, Math.sqrt(dp / dl));
87185               p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
87186               l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
87187             } else if (g.pointer0) {
87188               p = g.pointer0[0];
87189               l = g.pointer0[1];
87190             } else {
87191               return;
87192             }
87193
87194             g.zoom(d3_event, 'touch', constrain(translate(t, p, l), g.extent, translateExtent));
87195           }
87196
87197           function pointerup(d3_event) {
87198             if (!_downPointerIDs.has(d3_event.pointerId)) return;
87199
87200             _downPointerIDs["delete"](d3_event.pointerId);
87201
87202             if (!_activeGesture) return;
87203             var g = gesture(this, arguments);
87204             d3_event.stopImmediatePropagation();
87205             if (g.pointer0 && g.pointer0[2] === d3_event.pointerId) delete g.pointer0;else if (g.pointer1 && g.pointer1[2] === d3_event.pointerId) delete g.pointer1;
87206
87207             if (g.pointer1 && !g.pointer0) {
87208               g.pointer0 = g.pointer1;
87209               delete g.pointer1;
87210             }
87211
87212             if (g.pointer0) {
87213               g.pointer0[1] = _transform.invert(g.pointer0[0]);
87214             } else {
87215               g.end(d3_event);
87216             }
87217           }
87218
87219           zoom.wheelDelta = function (_) {
87220             return arguments.length ? (wheelDelta = utilFunctor(+_), zoom) : wheelDelta;
87221           };
87222
87223           zoom.filter = function (_) {
87224             return arguments.length ? (filter = utilFunctor(!!_), zoom) : filter;
87225           };
87226
87227           zoom.extent = function (_) {
87228             return arguments.length ? (extent = utilFunctor([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
87229           };
87230
87231           zoom.scaleExtent = function (_) {
87232             return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]];
87233           };
87234
87235           zoom.translateExtent = function (_) {
87236             return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]];
87237           };
87238
87239           zoom.constrain = function (_) {
87240             return arguments.length ? (constrain = _, zoom) : constrain;
87241           };
87242
87243           zoom.interpolate = function (_) {
87244             return arguments.length ? (interpolate = _, zoom) : interpolate;
87245           };
87246
87247           zoom._transform = function (_) {
87248             return arguments.length ? (_transform = _, zoom) : _transform;
87249           };
87250
87251           return utilRebind(zoom, dispatch, 'on');
87252         }
87253
87254         // if pointer events are supported. Falls back to default `dblclick` event.
87255
87256         function utilDoubleUp() {
87257           var dispatch = dispatch$8('doubleUp');
87258           var _maxTimespan = 500; // milliseconds
87259
87260           var _maxDistance = 20; // web pixels; be somewhat generous to account for touch devices
87261
87262           var _pointer; // object representing the pointer that could trigger double up
87263
87264
87265           function pointerIsValidFor(loc) {
87266             // second pointerup must occur within a small timeframe after the first pointerdown
87267             return new Date().getTime() - _pointer.startTime <= _maxTimespan && // all pointer events must occur within a small distance of the first pointerdown
87268             geoVecLength(_pointer.startLoc, loc) <= _maxDistance;
87269           }
87270
87271           function pointerdown(d3_event) {
87272             // ignore right-click
87273             if (d3_event.ctrlKey || d3_event.button === 2) return;
87274             var loc = [d3_event.clientX, d3_event.clientY]; // Don't rely on pointerId here since it can change between pointerdown
87275             // events on touch devices
87276
87277             if (_pointer && !pointerIsValidFor(loc)) {
87278               // if this pointer is no longer valid, clear it so another can be started
87279               _pointer = undefined;
87280             }
87281
87282             if (!_pointer) {
87283               _pointer = {
87284                 startLoc: loc,
87285                 startTime: new Date().getTime(),
87286                 upCount: 0,
87287                 pointerId: d3_event.pointerId
87288               };
87289             } else {
87290               // double down
87291               _pointer.pointerId = d3_event.pointerId;
87292             }
87293           }
87294
87295           function pointerup(d3_event) {
87296             // ignore right-click
87297             if (d3_event.ctrlKey || d3_event.button === 2) return;
87298             if (!_pointer || _pointer.pointerId !== d3_event.pointerId) return;
87299             _pointer.upCount += 1;
87300
87301             if (_pointer.upCount === 2) {
87302               // double up!
87303               var loc = [d3_event.clientX, d3_event.clientY];
87304
87305               if (pointerIsValidFor(loc)) {
87306                 var locInThis = utilFastMouse(this)(d3_event);
87307                 dispatch.call('doubleUp', this, d3_event, locInThis);
87308               } // clear the pointer info in any case
87309
87310
87311               _pointer = undefined;
87312             }
87313           }
87314
87315           function doubleUp(selection) {
87316             if ('PointerEvent' in window) {
87317               // dblclick isn't well supported on touch devices so manually use
87318               // pointer events if they're available
87319               selection.on('pointerdown.doubleUp', pointerdown).on('pointerup.doubleUp', pointerup);
87320             } else {
87321               // fallback to dblclick
87322               selection.on('dblclick.doubleUp', function (d3_event) {
87323                 dispatch.call('doubleUp', this, d3_event, utilFastMouse(this)(d3_event));
87324               });
87325             }
87326           }
87327
87328           doubleUp.off = function (selection) {
87329             selection.on('pointerdown.doubleUp', null).on('pointerup.doubleUp', null).on('dblclick.doubleUp', null);
87330           };
87331
87332           return utilRebind(doubleUp, dispatch, 'on');
87333         }
87334
87335         var TILESIZE = 256;
87336         var minZoom = 2;
87337         var maxZoom = 24;
87338         var kMin = geoZoomToScale(minZoom, TILESIZE);
87339         var kMax = geoZoomToScale(maxZoom, TILESIZE);
87340
87341         function clamp$1(num, min, max) {
87342           return Math.max(min, Math.min(num, max));
87343         }
87344
87345         function rendererMap(context) {
87346           var dispatch = dispatch$8('move', 'drawn', 'crossEditableZoom', 'hitMinZoom', 'changeHighlighting', 'changeAreaFill');
87347           var projection = context.projection;
87348           var curtainProjection = context.curtainProjection;
87349           var drawLayers;
87350           var drawPoints;
87351           var drawVertices;
87352           var drawLines;
87353           var drawAreas;
87354           var drawMidpoints;
87355           var drawLabels;
87356
87357           var _selection = select(null);
87358
87359           var supersurface = select(null);
87360           var wrapper = select(null);
87361           var surface = select(null);
87362           var _dimensions = [1, 1];
87363           var _dblClickZoomEnabled = true;
87364           var _redrawEnabled = true;
87365
87366           var _gestureTransformStart;
87367
87368           var _transformStart = projection.transform();
87369
87370           var _transformLast;
87371
87372           var _isTransformed = false;
87373           var _minzoom = 0;
87374
87375           var _getMouseCoords;
87376
87377           var _lastPointerEvent;
87378
87379           var _lastWithinEditableZoom; // whether a pointerdown event started the zoom
87380
87381
87382           var _pointerDown = false; // use pointer events on supported platforms; fallback to mouse events
87383
87384           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse'; // use pointer event interaction if supported; fallback to touch/mouse events in d3-zoom
87385
87386
87387           var _zoomerPannerFunction = 'PointerEvent' in window ? utilZoomPan : d3_zoom;
87388
87389           var _zoomerPanner = _zoomerPannerFunction().scaleExtent([kMin, kMax]).interpolate(interpolate$1).filter(zoomEventFilter).on('zoom.map', zoomPan).on('start.map', function (d3_event) {
87390             _pointerDown = d3_event && (d3_event.type === 'pointerdown' || d3_event.sourceEvent && d3_event.sourceEvent.type === 'pointerdown');
87391           }).on('end.map', function () {
87392             _pointerDown = false;
87393           });
87394
87395           var _doubleUpHandler = utilDoubleUp();
87396
87397           var scheduleRedraw = throttle(redraw, 750); // var isRedrawScheduled = false;
87398           // var pendingRedrawCall;
87399           // function scheduleRedraw() {
87400           //     // Only schedule the redraw if one has not already been set.
87401           //     if (isRedrawScheduled) return;
87402           //     isRedrawScheduled = true;
87403           //     var that = this;
87404           //     var args = arguments;
87405           //     pendingRedrawCall = window.requestIdleCallback(function () {
87406           //         // Reset the boolean so future redraws can be set.
87407           //         isRedrawScheduled = false;
87408           //         redraw.apply(that, args);
87409           //     }, { timeout: 1400 });
87410           // }
87411
87412
87413           function cancelPendingRedraw() {
87414             scheduleRedraw.cancel(); // isRedrawScheduled = false;
87415             // window.cancelIdleCallback(pendingRedrawCall);
87416           }
87417
87418           function map(selection) {
87419             _selection = selection;
87420             context.on('change.map', immediateRedraw);
87421             var osm = context.connection();
87422
87423             if (osm) {
87424               osm.on('change.map', immediateRedraw);
87425             }
87426
87427             function didUndoOrRedo(targetTransform) {
87428               var mode = context.mode().id;
87429               if (mode !== 'browse' && mode !== 'select') return;
87430
87431               if (targetTransform) {
87432                 map.transformEase(targetTransform);
87433               }
87434             }
87435
87436             context.history().on('merge.map', function () {
87437               scheduleRedraw();
87438             }).on('change.map', immediateRedraw).on('undone.map', function (stack, fromStack) {
87439               didUndoOrRedo(fromStack.transform);
87440             }).on('redone.map', function (stack) {
87441               didUndoOrRedo(stack.transform);
87442             });
87443             context.background().on('change.map', immediateRedraw);
87444             context.features().on('redraw.map', immediateRedraw);
87445             drawLayers.on('change.map', function () {
87446               context.background().updateImagery();
87447               immediateRedraw();
87448             });
87449             selection.on('wheel.map mousewheel.map', function (d3_event) {
87450               // disable swipe-to-navigate browser pages on trackpad/magic mouse – #5552
87451               d3_event.preventDefault();
87452             }).call(_zoomerPanner).call(_zoomerPanner.transform, projection.transform()).on('dblclick.zoom', null); // override d3-zoom dblclick handling
87453
87454             map.supersurface = supersurface = selection.append('div').attr('class', 'supersurface').call(utilSetTransform, 0, 0); // Need a wrapper div because Opera can't cope with an absolutely positioned
87455             // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
87456
87457             wrapper = supersurface.append('div').attr('class', 'layer layer-data');
87458             map.surface = surface = wrapper.call(drawLayers).selectAll('.surface');
87459             surface.call(drawLabels.observe).call(_doubleUpHandler).on(_pointerPrefix + 'down.zoom', function (d3_event) {
87460               _lastPointerEvent = d3_event;
87461
87462               if (d3_event.button === 2) {
87463                 d3_event.stopPropagation();
87464               }
87465             }, true).on(_pointerPrefix + 'up.zoom', function (d3_event) {
87466               _lastPointerEvent = d3_event;
87467
87468               if (resetTransform()) {
87469                 immediateRedraw();
87470               }
87471             }).on(_pointerPrefix + 'move.map', function (d3_event) {
87472               _lastPointerEvent = d3_event;
87473             }).on(_pointerPrefix + 'over.vertices', function (d3_event) {
87474               if (map.editableDataEnabled() && !_isTransformed) {
87475                 var hover = d3_event.target.__data__;
87476                 surface.call(drawVertices.drawHover, context.graph(), hover, map.extent());
87477                 dispatch.call('drawn', this, {
87478                   full: false
87479                 });
87480               }
87481             }).on(_pointerPrefix + 'out.vertices', function (d3_event) {
87482               if (map.editableDataEnabled() && !_isTransformed) {
87483                 var hover = d3_event.relatedTarget && d3_event.relatedTarget.__data__;
87484                 surface.call(drawVertices.drawHover, context.graph(), hover, map.extent());
87485                 dispatch.call('drawn', this, {
87486                   full: false
87487                 });
87488               }
87489             });
87490             var detected = utilDetect(); // only WebKit supports gesture events
87491
87492             if ('GestureEvent' in window && // Listening for gesture events on iOS 13.4+ breaks double-tapping,
87493             // but we only need to do this on desktop Safari anyway. – #7694
87494             !detected.isMobileWebKit) {
87495               // Desktop Safari sends gesture events for multitouch trackpad pinches.
87496               // We can listen for these and translate them into map zooms.
87497               surface.on('gesturestart.surface', function (d3_event) {
87498                 d3_event.preventDefault();
87499                 _gestureTransformStart = projection.transform();
87500               }).on('gesturechange.surface', gestureChange);
87501             } // must call after surface init
87502
87503
87504             updateAreaFill();
87505
87506             _doubleUpHandler.on('doubleUp.map', function (d3_event, p0) {
87507               if (!_dblClickZoomEnabled) return; // don't zoom if targeting something other than the map itself
87508
87509               if (_typeof(d3_event.target.__data__) === 'object' && // or area fills
87510               !select(d3_event.target).classed('fill')) return;
87511               var zoomOut = d3_event.shiftKey;
87512               var t = projection.transform();
87513               var p1 = t.invert(p0);
87514               t = t.scale(zoomOut ? 0.5 : 2);
87515               t.x = p0[0] - p1[0] * t.k;
87516               t.y = p0[1] - p1[1] * t.k;
87517               map.transformEase(t);
87518             });
87519
87520             context.on('enter.map', function () {
87521               if (!map.editableDataEnabled(true
87522               /* skip zoom check */
87523               )) return;
87524               if (_isTransformed) return; // redraw immediately any objects affected by a change in selectedIDs.
87525
87526               var graph = context.graph();
87527               var selectedAndParents = {};
87528               context.selectedIDs().forEach(function (id) {
87529                 var entity = graph.hasEntity(id);
87530
87531                 if (entity) {
87532                   selectedAndParents[entity.id] = entity;
87533
87534                   if (entity.type === 'node') {
87535                     graph.parentWays(entity).forEach(function (parent) {
87536                       selectedAndParents[parent.id] = parent;
87537                     });
87538                   }
87539                 }
87540               });
87541               var data = Object.values(selectedAndParents);
87542
87543               var filter = function filter(d) {
87544                 return d.id in selectedAndParents;
87545               };
87546
87547               data = context.features().filter(data, graph);
87548               surface.call(drawVertices.drawSelected, graph, map.extent()).call(drawLines, graph, data, filter).call(drawAreas, graph, data, filter).call(drawMidpoints, graph, data, filter, map.trimmedExtent());
87549               dispatch.call('drawn', this, {
87550                 full: false
87551               }); // redraw everything else later
87552
87553               scheduleRedraw();
87554             });
87555             map.dimensions(utilGetDimensions(selection));
87556           }
87557
87558           function zoomEventFilter(d3_event) {
87559             // Fix for #2151, (see also d3/d3-zoom#60, d3/d3-brush#18)
87560             // Intercept `mousedown` and check if there is an orphaned zoom gesture.
87561             // This can happen if a previous `mousedown` occurred without a `mouseup`.
87562             // If we detect this, dispatch `mouseup` to complete the orphaned gesture,
87563             // so that d3-zoom won't stop propagation of new `mousedown` events.
87564             if (d3_event.type === 'mousedown') {
87565               var hasOrphan = false;
87566               var listeners = window.__on;
87567
87568               for (var i = 0; i < listeners.length; i++) {
87569                 var listener = listeners[i];
87570
87571                 if (listener.name === 'zoom' && listener.type === 'mouseup') {
87572                   hasOrphan = true;
87573                   break;
87574                 }
87575               }
87576
87577               if (hasOrphan) {
87578                 var event = window.CustomEvent;
87579
87580                 if (event) {
87581                   event = new event('mouseup');
87582                 } else {
87583                   event = window.document.createEvent('Event');
87584                   event.initEvent('mouseup', false, false);
87585                 } // Event needs to be dispatched with an event.view property.
87586
87587
87588                 event.view = window;
87589                 window.dispatchEvent(event);
87590               }
87591             }
87592
87593             return d3_event.button !== 2; // ignore right clicks
87594           }
87595
87596           function pxCenter() {
87597             return [_dimensions[0] / 2, _dimensions[1] / 2];
87598           }
87599
87600           function drawEditable(difference, extent) {
87601             var mode = context.mode();
87602             var graph = context.graph();
87603             var features = context.features();
87604             var all = context.history().intersects(map.extent());
87605             var fullRedraw = false;
87606             var data;
87607             var set;
87608             var filter;
87609             var applyFeatureLayerFilters = true;
87610
87611             if (map.isInWideSelection()) {
87612               data = [];
87613               utilEntityAndDeepMemberIDs(mode.selectedIDs(), context.graph()).forEach(function (id) {
87614                 var entity = context.hasEntity(id);
87615                 if (entity) data.push(entity);
87616               });
87617               fullRedraw = true;
87618               filter = utilFunctor(true); // selected features should always be visible, so we can skip filtering
87619
87620               applyFeatureLayerFilters = false;
87621             } else if (difference) {
87622               var complete = difference.complete(map.extent());
87623               data = Object.values(complete).filter(Boolean);
87624               set = new Set(Object.keys(complete));
87625
87626               filter = function filter(d) {
87627                 return set.has(d.id);
87628               };
87629
87630               features.clear(data);
87631             } else {
87632               // force a full redraw if gatherStats detects that a feature
87633               // should be auto-hidden (e.g. points or buildings)..
87634               if (features.gatherStats(all, graph, _dimensions)) {
87635                 extent = undefined;
87636               }
87637
87638               if (extent) {
87639                 data = context.history().intersects(map.extent().intersection(extent));
87640                 set = new Set(data.map(function (entity) {
87641                   return entity.id;
87642                 }));
87643
87644                 filter = function filter(d) {
87645                   return set.has(d.id);
87646                 };
87647               } else {
87648                 data = all;
87649                 fullRedraw = true;
87650                 filter = utilFunctor(true);
87651               }
87652             }
87653
87654             if (applyFeatureLayerFilters) {
87655               data = features.filter(data, graph);
87656             } else {
87657               context.features().resetStats();
87658             }
87659
87660             if (mode && mode.id === 'select') {
87661               // update selected vertices - the user might have just double-clicked a way,
87662               // creating a new vertex, triggering a partial redraw without a mode change
87663               surface.call(drawVertices.drawSelected, graph, map.extent());
87664             }
87665
87666             surface.call(drawVertices, graph, data, filter, map.extent(), fullRedraw).call(drawLines, graph, data, filter).call(drawAreas, graph, data, filter).call(drawMidpoints, graph, data, filter, map.trimmedExtent()).call(drawLabels, graph, data, filter, _dimensions, fullRedraw).call(drawPoints, graph, data, filter);
87667             dispatch.call('drawn', this, {
87668               full: true
87669             });
87670           }
87671
87672           map.init = function () {
87673             drawLayers = svgLayers(projection, context);
87674             drawPoints = svgPoints(projection, context);
87675             drawVertices = svgVertices(projection, context);
87676             drawLines = svgLines(projection, context);
87677             drawAreas = svgAreas(projection, context);
87678             drawMidpoints = svgMidpoints(projection, context);
87679             drawLabels = svgLabels(projection, context);
87680           };
87681
87682           function editOff() {
87683             context.features().resetStats();
87684             surface.selectAll('.layer-osm *').remove();
87685             surface.selectAll('.layer-touch:not(.markers) *').remove();
87686             var allowed = {
87687               'browse': true,
87688               'save': true,
87689               'select-note': true,
87690               'select-data': true,
87691               'select-error': true
87692             };
87693             var mode = context.mode();
87694
87695             if (mode && !allowed[mode.id]) {
87696               context.enter(modeBrowse(context));
87697             }
87698
87699             dispatch.call('drawn', this, {
87700               full: true
87701             });
87702           }
87703
87704           function gestureChange(d3_event) {
87705             // Remap Safari gesture events to wheel events - #5492
87706             // We want these disabled most places, but enabled for zoom/unzoom on map surface
87707             // https://developer.mozilla.org/en-US/docs/Web/API/GestureEvent
87708             var e = d3_event;
87709             e.preventDefault();
87710             var props = {
87711               deltaMode: 0,
87712               // dummy values to ignore in zoomPan
87713               deltaY: 1,
87714               // dummy values to ignore in zoomPan
87715               clientX: e.clientX,
87716               clientY: e.clientY,
87717               screenX: e.screenX,
87718               screenY: e.screenY,
87719               x: e.x,
87720               y: e.y
87721             };
87722             var e2 = new WheelEvent('wheel', props);
87723             e2._scale = e.scale; // preserve the original scale
87724
87725             e2._rotation = e.rotation; // preserve the original rotation
87726
87727             _selection.node().dispatchEvent(e2);
87728           }
87729
87730           function zoomPan(event, key, transform) {
87731             var source = event && event.sourceEvent || event;
87732             var eventTransform = transform || event && event.transform;
87733             var x = eventTransform.x;
87734             var y = eventTransform.y;
87735             var k = eventTransform.k; // Special handling of 'wheel' events:
87736             // They might be triggered by the user scrolling the mouse wheel,
87737             // or 2-finger pinch/zoom gestures, the transform may need adjustment.
87738
87739             if (source && source.type === 'wheel') {
87740               // assume that the gesture is already handled by pointer events
87741               if (_pointerDown) return;
87742               var detected = utilDetect();
87743               var dX = source.deltaX;
87744               var dY = source.deltaY;
87745               var x2 = x;
87746               var y2 = y;
87747               var k2 = k;
87748               var t0, p0, p1; // Normalize mousewheel scroll speed (Firefox) - #3029
87749               // If wheel delta is provided in LINE units, recalculate it in PIXEL units
87750               // We are essentially redoing the calculations that occur here:
87751               //   https://github.com/d3/d3-zoom/blob/78563a8348aa4133b07cac92e2595c2227ca7cd7/src/zoom.js#L203
87752               // See this for more info:
87753               //   https://github.com/basilfx/normalize-wheel/blob/master/src/normalizeWheel.js
87754
87755               if (source.deltaMode === 1
87756               /* LINE */
87757               ) {
87758                 // Convert from lines to pixels, more if the user is scrolling fast.
87759                 // (I made up the exp function to roughly match Firefox to what Chrome does)
87760                 // These numbers should be floats, because integers are treated as pan gesture below.
87761                 var lines = Math.abs(source.deltaY);
87762                 var sign = source.deltaY > 0 ? 1 : -1;
87763                 dY = sign * clamp$1(Math.exp((lines - 1) * 0.75) * 4.000244140625, 4.000244140625, // min
87764                 350.000244140625 // max
87765                 ); // On Firefox Windows and Linux we always get +/- the scroll line amount (default 3)
87766                 // There doesn't seem to be any scroll acceleration.
87767                 // This multiplier increases the speed a little bit - #5512
87768
87769                 if (detected.os !== 'mac') {
87770                   dY *= 5;
87771                 } // recalculate x2,y2,k2
87772
87773
87774                 t0 = _isTransformed ? _transformLast : _transformStart;
87775                 p0 = _getMouseCoords(source);
87776                 p1 = t0.invert(p0);
87777                 k2 = t0.k * Math.pow(2, -dY / 500);
87778                 k2 = clamp$1(k2, kMin, kMax);
87779                 x2 = p0[0] - p1[0] * k2;
87780                 y2 = p0[1] - p1[1] * k2; // 2 finger map pinch zooming (Safari) - #5492
87781                 // These are fake `wheel` events we made from Safari `gesturechange` events..
87782               } else if (source._scale) {
87783                 // recalculate x2,y2,k2
87784                 t0 = _gestureTransformStart;
87785                 p0 = _getMouseCoords(source);
87786                 p1 = t0.invert(p0);
87787                 k2 = t0.k * source._scale;
87788                 k2 = clamp$1(k2, kMin, kMax);
87789                 x2 = p0[0] - p1[0] * k2;
87790                 y2 = p0[1] - p1[1] * k2; // 2 finger map pinch zooming (all browsers except Safari) - #5492
87791                 // Pinch zooming via the `wheel` event will always have:
87792                 // - `ctrlKey = true`
87793                 // - `deltaY` is not round integer pixels (ignore `deltaX`)
87794               } else if (source.ctrlKey && !isInteger(dY)) {
87795                 dY *= 6; // slightly scale up whatever the browser gave us
87796                 // recalculate x2,y2,k2
87797
87798                 t0 = _isTransformed ? _transformLast : _transformStart;
87799                 p0 = _getMouseCoords(source);
87800                 p1 = t0.invert(p0);
87801                 k2 = t0.k * Math.pow(2, -dY / 500);
87802                 k2 = clamp$1(k2, kMin, kMax);
87803                 x2 = p0[0] - p1[0] * k2;
87804                 y2 = p0[1] - p1[1] * k2; // Trackpad scroll zooming with shift or alt/option key down
87805               } else if ((source.altKey || source.shiftKey) && isInteger(dY)) {
87806                 // recalculate x2,y2,k2
87807                 t0 = _isTransformed ? _transformLast : _transformStart;
87808                 p0 = _getMouseCoords(source);
87809                 p1 = t0.invert(p0);
87810                 k2 = t0.k * Math.pow(2, -dY / 500);
87811                 k2 = clamp$1(k2, kMin, kMax);
87812                 x2 = p0[0] - p1[0] * k2;
87813                 y2 = p0[1] - p1[1] * k2; // 2 finger map panning (Mac only, all browsers except Firefox #8595) - #5492, #5512
87814                 // Panning via the `wheel` event will always have:
87815                 // - `ctrlKey = false`
87816                 // - `deltaX`,`deltaY` are round integer pixels
87817               } else if (detected.os === 'mac' && detected.browser !== 'Firefox' && !source.ctrlKey && isInteger(dX) && isInteger(dY)) {
87818                 p1 = projection.translate();
87819                 x2 = p1[0] - dX;
87820                 y2 = p1[1] - dY;
87821                 k2 = projection.scale();
87822                 k2 = clamp$1(k2, kMin, kMax);
87823               } // something changed - replace the event transform
87824
87825
87826               if (x2 !== x || y2 !== y || k2 !== k) {
87827                 x = x2;
87828                 y = y2;
87829                 k = k2;
87830                 eventTransform = identity$2.translate(x2, y2).scale(k2);
87831
87832                 if (_zoomerPanner._transform) {
87833                   // utilZoomPan interface
87834                   _zoomerPanner._transform(eventTransform);
87835                 } else {
87836                   // d3_zoom interface
87837                   _selection.node().__zoom = eventTransform;
87838                 }
87839               }
87840             }
87841
87842             if (_transformStart.x === x && _transformStart.y === y && _transformStart.k === k) {
87843               return; // no change
87844             }
87845
87846             if (geoScaleToZoom(k, TILESIZE) < _minzoom) {
87847               surface.interrupt();
87848               dispatch.call('hitMinZoom', this, map);
87849               setCenterZoom(map.center(), context.minEditableZoom(), 0, true);
87850               scheduleRedraw();
87851               dispatch.call('move', this, map);
87852               return;
87853             }
87854
87855             projection.transform(eventTransform);
87856             var withinEditableZoom = map.withinEditableZoom();
87857
87858             if (_lastWithinEditableZoom !== withinEditableZoom) {
87859               if (_lastWithinEditableZoom !== undefined) {
87860                 // notify that the map zoomed in or out over the editable zoom threshold
87861                 dispatch.call('crossEditableZoom', this, withinEditableZoom);
87862               }
87863
87864               _lastWithinEditableZoom = withinEditableZoom;
87865             }
87866
87867             var scale = k / _transformStart.k;
87868             var tX = (x / scale - _transformStart.x) * scale;
87869             var tY = (y / scale - _transformStart.y) * scale;
87870
87871             if (context.inIntro()) {
87872               curtainProjection.transform({
87873                 x: x - tX,
87874                 y: y - tY,
87875                 k: k
87876               });
87877             }
87878
87879             if (source) {
87880               _lastPointerEvent = event;
87881             }
87882
87883             _isTransformed = true;
87884             _transformLast = eventTransform;
87885             utilSetTransform(supersurface, tX, tY, scale);
87886             scheduleRedraw();
87887             dispatch.call('move', this, map);
87888
87889             function isInteger(val) {
87890               return typeof val === 'number' && isFinite(val) && Math.floor(val) === val;
87891             }
87892           }
87893
87894           function resetTransform() {
87895             if (!_isTransformed) return false;
87896             utilSetTransform(supersurface, 0, 0);
87897             _isTransformed = false;
87898
87899             if (context.inIntro()) {
87900               curtainProjection.transform(projection.transform());
87901             }
87902
87903             return true;
87904           }
87905
87906           function redraw(difference, extent) {
87907             if (surface.empty() || !_redrawEnabled) return; // If we are in the middle of a zoom/pan, we can't do differenced redraws.
87908             // It would result in artifacts where differenced entities are redrawn with
87909             // one transform and unchanged entities with another.
87910
87911             if (resetTransform()) {
87912               difference = extent = undefined;
87913             }
87914
87915             var zoom = map.zoom();
87916             var z = String(~~zoom);
87917
87918             if (surface.attr('data-zoom') !== z) {
87919               surface.attr('data-zoom', z);
87920             } // class surface as `lowzoom` around z17-z18.5 (based on latitude)
87921
87922
87923             var lat = map.center()[1];
87924             var lowzoom = linear().domain([-60, 0, 60]).range([17, 18.5, 17]).clamp(true);
87925             surface.classed('low-zoom', zoom <= lowzoom(lat));
87926
87927             if (!difference) {
87928               supersurface.call(context.background());
87929               wrapper.call(drawLayers);
87930             } // OSM
87931
87932
87933             if (map.editableDataEnabled() || map.isInWideSelection()) {
87934               context.loadTiles(projection);
87935               drawEditable(difference, extent);
87936             } else {
87937               editOff();
87938             }
87939
87940             _transformStart = projection.transform();
87941             return map;
87942           }
87943
87944           var immediateRedraw = function immediateRedraw(difference, extent) {
87945             if (!difference && !extent) cancelPendingRedraw();
87946             redraw(difference, extent);
87947           };
87948
87949           map.lastPointerEvent = function () {
87950             return _lastPointerEvent;
87951           };
87952
87953           map.mouse = function (d3_event) {
87954             var event = d3_event || _lastPointerEvent;
87955
87956             if (event) {
87957               var s;
87958
87959               while (s = event.sourceEvent) {
87960                 event = s;
87961               }
87962
87963               return _getMouseCoords(event);
87964             }
87965
87966             return null;
87967           }; // returns Lng/Lat
87968
87969
87970           map.mouseCoordinates = function () {
87971             var coord = map.mouse() || pxCenter();
87972             return projection.invert(coord);
87973           };
87974
87975           map.dblclickZoomEnable = function (val) {
87976             if (!arguments.length) return _dblClickZoomEnabled;
87977             _dblClickZoomEnabled = val;
87978             return map;
87979           };
87980
87981           map.redrawEnable = function (val) {
87982             if (!arguments.length) return _redrawEnabled;
87983             _redrawEnabled = val;
87984             return map;
87985           };
87986
87987           map.isTransformed = function () {
87988             return _isTransformed;
87989           };
87990
87991           function setTransform(t2, duration, force) {
87992             var t = projection.transform();
87993             if (!force && t2.k === t.k && t2.x === t.x && t2.y === t.y) return false;
87994
87995             if (duration) {
87996               _selection.transition().duration(duration).on('start', function () {
87997                 map.startEase();
87998               }).call(_zoomerPanner.transform, identity$2.translate(t2.x, t2.y).scale(t2.k));
87999             } else {
88000               projection.transform(t2);
88001               _transformStart = t2;
88002
88003               _selection.call(_zoomerPanner.transform, _transformStart);
88004             }
88005
88006             return true;
88007           }
88008
88009           function setCenterZoom(loc2, z2, duration, force) {
88010             var c = map.center();
88011             var z = map.zoom();
88012             if (loc2[0] === c[0] && loc2[1] === c[1] && z2 === z && !force) return false;
88013             var proj = geoRawMercator().transform(projection.transform()); // copy projection
88014
88015             var k2 = clamp$1(geoZoomToScale(z2, TILESIZE), kMin, kMax);
88016             proj.scale(k2);
88017             var t = proj.translate();
88018             var point = proj(loc2);
88019             var center = pxCenter();
88020             t[0] += center[0] - point[0];
88021             t[1] += center[1] - point[1];
88022             return setTransform(identity$2.translate(t[0], t[1]).scale(k2), duration, force);
88023           }
88024
88025           map.pan = function (delta, duration) {
88026             var t = projection.translate();
88027             var k = projection.scale();
88028             t[0] += delta[0];
88029             t[1] += delta[1];
88030
88031             if (duration) {
88032               _selection.transition().duration(duration).on('start', function () {
88033                 map.startEase();
88034               }).call(_zoomerPanner.transform, identity$2.translate(t[0], t[1]).scale(k));
88035             } else {
88036               projection.translate(t);
88037               _transformStart = projection.transform();
88038
88039               _selection.call(_zoomerPanner.transform, _transformStart);
88040
88041               dispatch.call('move', this, map);
88042               immediateRedraw();
88043             }
88044
88045             return map;
88046           };
88047
88048           map.dimensions = function (val) {
88049             if (!arguments.length) return _dimensions;
88050             _dimensions = val;
88051             drawLayers.dimensions(_dimensions);
88052             context.background().dimensions(_dimensions);
88053             projection.clipExtent([[0, 0], _dimensions]);
88054             _getMouseCoords = utilFastMouse(supersurface.node());
88055             scheduleRedraw();
88056             return map;
88057           };
88058
88059           function zoomIn(delta) {
88060             setCenterZoom(map.center(), ~~map.zoom() + delta, 250, true);
88061           }
88062
88063           function zoomOut(delta) {
88064             setCenterZoom(map.center(), ~~map.zoom() - delta, 250, true);
88065           }
88066
88067           map.zoomIn = function () {
88068             zoomIn(1);
88069           };
88070
88071           map.zoomInFurther = function () {
88072             zoomIn(4);
88073           };
88074
88075           map.canZoomIn = function () {
88076             return map.zoom() < maxZoom;
88077           };
88078
88079           map.zoomOut = function () {
88080             zoomOut(1);
88081           };
88082
88083           map.zoomOutFurther = function () {
88084             zoomOut(4);
88085           };
88086
88087           map.canZoomOut = function () {
88088             return map.zoom() > minZoom;
88089           };
88090
88091           map.center = function (loc2) {
88092             if (!arguments.length) {
88093               return projection.invert(pxCenter());
88094             }
88095
88096             if (setCenterZoom(loc2, map.zoom())) {
88097               dispatch.call('move', this, map);
88098             }
88099
88100             scheduleRedraw();
88101             return map;
88102           };
88103
88104           map.unobscuredCenterZoomEase = function (loc, zoom) {
88105             var offset = map.unobscuredOffsetPx();
88106             var proj = geoRawMercator().transform(projection.transform()); // copy projection
88107             // use the target zoom to calculate the offset center
88108
88109             proj.scale(geoZoomToScale(zoom, TILESIZE));
88110             var locPx = proj(loc);
88111             var offsetLocPx = [locPx[0] + offset[0], locPx[1] + offset[1]];
88112             var offsetLoc = proj.invert(offsetLocPx);
88113             map.centerZoomEase(offsetLoc, zoom);
88114           };
88115
88116           map.unobscuredOffsetPx = function () {
88117             var openPane = context.container().select('.map-panes .map-pane.shown');
88118
88119             if (!openPane.empty()) {
88120               return [openPane.node().offsetWidth / 2, 0];
88121             }
88122
88123             return [0, 0];
88124           };
88125
88126           map.zoom = function (z2) {
88127             if (!arguments.length) {
88128               return Math.max(geoScaleToZoom(projection.scale(), TILESIZE), 0);
88129             }
88130
88131             if (z2 < _minzoom) {
88132               surface.interrupt();
88133               dispatch.call('hitMinZoom', this, map);
88134               z2 = context.minEditableZoom();
88135             }
88136
88137             if (setCenterZoom(map.center(), z2)) {
88138               dispatch.call('move', this, map);
88139             }
88140
88141             scheduleRedraw();
88142             return map;
88143           };
88144
88145           map.centerZoom = function (loc2, z2) {
88146             if (setCenterZoom(loc2, z2)) {
88147               dispatch.call('move', this, map);
88148             }
88149
88150             scheduleRedraw();
88151             return map;
88152           };
88153
88154           map.zoomTo = function (entity) {
88155             var extent = entity.extent(context.graph());
88156             if (!isFinite(extent.area())) return map;
88157             var z2 = clamp$1(map.trimmedExtentZoom(extent), 0, 20);
88158             return map.centerZoom(extent.center(), z2);
88159           };
88160
88161           map.centerEase = function (loc2, duration) {
88162             duration = duration || 250;
88163             setCenterZoom(loc2, map.zoom(), duration);
88164             return map;
88165           };
88166
88167           map.zoomEase = function (z2, duration) {
88168             duration = duration || 250;
88169             setCenterZoom(map.center(), z2, duration, false);
88170             return map;
88171           };
88172
88173           map.centerZoomEase = function (loc2, z2, duration) {
88174             duration = duration || 250;
88175             setCenterZoom(loc2, z2, duration, false);
88176             return map;
88177           };
88178
88179           map.transformEase = function (t2, duration) {
88180             duration = duration || 250;
88181             setTransform(t2, duration, false
88182             /* don't force */
88183             );
88184             return map;
88185           };
88186
88187           map.zoomToEase = function (obj, duration) {
88188             var extent;
88189
88190             if (Array.isArray(obj)) {
88191               obj.forEach(function (entity) {
88192                 var entityExtent = entity.extent(context.graph());
88193
88194                 if (!extent) {
88195                   extent = entityExtent;
88196                 } else {
88197                   extent = extent.extend(entityExtent);
88198                 }
88199               });
88200             } else {
88201               extent = obj.extent(context.graph());
88202             }
88203
88204             if (!isFinite(extent.area())) return map;
88205             var z2 = clamp$1(map.trimmedExtentZoom(extent), 0, 20);
88206             return map.centerZoomEase(extent.center(), z2, duration);
88207           };
88208
88209           map.startEase = function () {
88210             utilBindOnce(surface, _pointerPrefix + 'down.ease', function () {
88211               map.cancelEase();
88212             });
88213             return map;
88214           };
88215
88216           map.cancelEase = function () {
88217             _selection.interrupt();
88218
88219             return map;
88220           };
88221
88222           map.extent = function (val) {
88223             if (!arguments.length) {
88224               return new geoExtent(projection.invert([0, _dimensions[1]]), projection.invert([_dimensions[0], 0]));
88225             } else {
88226               var extent = geoExtent(val);
88227               map.centerZoom(extent.center(), map.extentZoom(extent));
88228             }
88229           };
88230
88231           map.trimmedExtent = function (val) {
88232             if (!arguments.length) {
88233               var headerY = 71;
88234               var footerY = 30;
88235               var pad = 10;
88236               return new geoExtent(projection.invert([pad, _dimensions[1] - footerY - pad]), projection.invert([_dimensions[0] - pad, headerY + pad]));
88237             } else {
88238               var extent = geoExtent(val);
88239               map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
88240             }
88241           };
88242
88243           function calcExtentZoom(extent, dim) {
88244             var tl = projection([extent[0][0], extent[1][1]]);
88245             var br = projection([extent[1][0], extent[0][1]]); // Calculate maximum zoom that fits extent
88246
88247             var hFactor = (br[0] - tl[0]) / dim[0];
88248             var vFactor = (br[1] - tl[1]) / dim[1];
88249             var hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2;
88250             var vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2;
88251             var newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff);
88252             return newZoom;
88253           }
88254
88255           map.extentZoom = function (val) {
88256             return calcExtentZoom(geoExtent(val), _dimensions);
88257           };
88258
88259           map.trimmedExtentZoom = function (val) {
88260             var trimY = 120;
88261             var trimX = 40;
88262             var trimmed = [_dimensions[0] - trimX, _dimensions[1] - trimY];
88263             return calcExtentZoom(geoExtent(val), trimmed);
88264           };
88265
88266           map.withinEditableZoom = function () {
88267             return map.zoom() >= context.minEditableZoom();
88268           };
88269
88270           map.isInWideSelection = function () {
88271             return !map.withinEditableZoom() && context.selectedIDs().length;
88272           };
88273
88274           map.editableDataEnabled = function (skipZoomCheck) {
88275             var layer = context.layers().layer('osm');
88276             if (!layer || !layer.enabled()) return false;
88277             return skipZoomCheck || map.withinEditableZoom();
88278           };
88279
88280           map.notesEditable = function () {
88281             var layer = context.layers().layer('notes');
88282             if (!layer || !layer.enabled()) return false;
88283             return map.withinEditableZoom();
88284           };
88285
88286           map.minzoom = function (val) {
88287             if (!arguments.length) return _minzoom;
88288             _minzoom = val;
88289             return map;
88290           };
88291
88292           map.toggleHighlightEdited = function () {
88293             surface.classed('highlight-edited', !surface.classed('highlight-edited'));
88294             map.pan([0, 0]); // trigger a redraw
88295
88296             dispatch.call('changeHighlighting', this);
88297           };
88298
88299           map.areaFillOptions = ['wireframe', 'partial', 'full'];
88300
88301           map.activeAreaFill = function (val) {
88302             if (!arguments.length) return corePreferences('area-fill') || 'partial';
88303             corePreferences('area-fill', val);
88304
88305             if (val !== 'wireframe') {
88306               corePreferences('area-fill-toggle', val);
88307             }
88308
88309             updateAreaFill();
88310             map.pan([0, 0]); // trigger a redraw
88311
88312             dispatch.call('changeAreaFill', this);
88313             return map;
88314           };
88315
88316           map.toggleWireframe = function () {
88317             var activeFill = map.activeAreaFill();
88318
88319             if (activeFill === 'wireframe') {
88320               activeFill = corePreferences('area-fill-toggle') || 'partial';
88321             } else {
88322               activeFill = 'wireframe';
88323             }
88324
88325             map.activeAreaFill(activeFill);
88326           };
88327
88328           function updateAreaFill() {
88329             var activeFill = map.activeAreaFill();
88330             map.areaFillOptions.forEach(function (opt) {
88331               surface.classed('fill-' + opt, Boolean(opt === activeFill));
88332             });
88333           }
88334
88335           map.layers = function () {
88336             return drawLayers;
88337           };
88338
88339           map.doubleUpHandler = function () {
88340             return _doubleUpHandler;
88341           };
88342
88343           return utilRebind(map, dispatch, 'on');
88344         }
88345
88346         function rendererPhotos(context) {
88347           var dispatch = dispatch$8('change');
88348           var _layerIDs = ['streetside', 'mapillary', 'mapillary-map-features', 'mapillary-signs', 'kartaview'];
88349           var _allPhotoTypes = ['flat', 'panoramic'];
88350
88351           var _shownPhotoTypes = _allPhotoTypes.slice(); // shallow copy
88352
88353
88354           var _dateFilters = ['fromDate', 'toDate'];
88355
88356           var _fromDate;
88357
88358           var _toDate;
88359
88360           var _usernames;
88361
88362           function photos() {}
88363
88364           function updateStorage() {
88365             if (window.mocha) return;
88366             var hash = utilStringQs(window.location.hash);
88367             var enabled = context.layers().all().filter(function (d) {
88368               return _layerIDs.indexOf(d.id) !== -1 && d.layer && d.layer.supported() && d.layer.enabled();
88369             }).map(function (d) {
88370               return d.id;
88371             });
88372
88373             if (enabled.length) {
88374               hash.photo_overlay = enabled.join(',');
88375             } else {
88376               delete hash.photo_overlay;
88377             }
88378
88379             window.location.replace('#' + utilQsString(hash, true));
88380           }
88381
88382           photos.overlayLayerIDs = function () {
88383             return _layerIDs;
88384           };
88385
88386           photos.allPhotoTypes = function () {
88387             return _allPhotoTypes;
88388           };
88389
88390           photos.dateFilters = function () {
88391             return _dateFilters;
88392           };
88393
88394           photos.dateFilterValue = function (val) {
88395             return val === _dateFilters[0] ? _fromDate : _toDate;
88396           };
88397
88398           photos.setDateFilter = function (type, val, updateUrl) {
88399             // validate the date
88400             var date = val && new Date(val);
88401
88402             if (date && !isNaN(date)) {
88403               val = date.toISOString().substr(0, 10);
88404             } else {
88405               val = null;
88406             }
88407
88408             if (type === _dateFilters[0]) {
88409               _fromDate = val;
88410
88411               if (_fromDate && _toDate && new Date(_toDate) < new Date(_fromDate)) {
88412                 _toDate = _fromDate;
88413               }
88414             }
88415
88416             if (type === _dateFilters[1]) {
88417               _toDate = val;
88418
88419               if (_fromDate && _toDate && new Date(_toDate) < new Date(_fromDate)) {
88420                 _fromDate = _toDate;
88421               }
88422             }
88423
88424             dispatch.call('change', this);
88425
88426             if (updateUrl) {
88427               var rangeString;
88428
88429               if (_fromDate || _toDate) {
88430                 rangeString = (_fromDate || '') + '_' + (_toDate || '');
88431               }
88432
88433               setUrlFilterValue('photo_dates', rangeString);
88434             }
88435           };
88436
88437           photos.setUsernameFilter = function (val, updateUrl) {
88438             if (val && typeof val === 'string') val = val.replace(/;/g, ',').split(',');
88439
88440             if (val) {
88441               val = val.map(function (d) {
88442                 return d.trim();
88443               }).filter(Boolean);
88444
88445               if (!val.length) {
88446                 val = null;
88447               }
88448             }
88449
88450             _usernames = val;
88451             dispatch.call('change', this);
88452
88453             if (updateUrl) {
88454               var hashString;
88455
88456               if (_usernames) {
88457                 hashString = _usernames.join(',');
88458               }
88459
88460               setUrlFilterValue('photo_username', hashString);
88461             }
88462           };
88463
88464           function setUrlFilterValue(property, val) {
88465             if (!window.mocha) {
88466               var hash = utilStringQs(window.location.hash);
88467
88468               if (val) {
88469                 if (hash[property] === val) return;
88470                 hash[property] = val;
88471               } else {
88472                 if (!(property in hash)) return;
88473                 delete hash[property];
88474               }
88475
88476               window.location.replace('#' + utilQsString(hash, true));
88477             }
88478           }
88479
88480           function showsLayer(id) {
88481             var layer = context.layers().layer(id);
88482             return layer && layer.supported() && layer.enabled();
88483           }
88484
88485           photos.shouldFilterByDate = function () {
88486             return showsLayer('mapillary') || showsLayer('kartaview') || showsLayer('streetside');
88487           };
88488
88489           photos.shouldFilterByPhotoType = function () {
88490             return showsLayer('mapillary') || showsLayer('streetside') && showsLayer('kartaview');
88491           };
88492
88493           photos.shouldFilterByUsername = function () {
88494             return !showsLayer('mapillary') && showsLayer('kartaview') && !showsLayer('streetside');
88495           };
88496
88497           photos.showsPhotoType = function (val) {
88498             if (!photos.shouldFilterByPhotoType()) return true;
88499             return _shownPhotoTypes.indexOf(val) !== -1;
88500           };
88501
88502           photos.showsFlat = function () {
88503             return photos.showsPhotoType('flat');
88504           };
88505
88506           photos.showsPanoramic = function () {
88507             return photos.showsPhotoType('panoramic');
88508           };
88509
88510           photos.fromDate = function () {
88511             return _fromDate;
88512           };
88513
88514           photos.toDate = function () {
88515             return _toDate;
88516           };
88517
88518           photos.togglePhotoType = function (val) {
88519             var index = _shownPhotoTypes.indexOf(val);
88520
88521             if (index !== -1) {
88522               _shownPhotoTypes.splice(index, 1);
88523             } else {
88524               _shownPhotoTypes.push(val);
88525             }
88526
88527             dispatch.call('change', this);
88528             return photos;
88529           };
88530
88531           photos.usernames = function () {
88532             return _usernames;
88533           };
88534
88535           photos.init = function () {
88536             var hash = utilStringQs(window.location.hash);
88537
88538             if (hash.photo_dates) {
88539               // expect format like `photo_dates=2019-01-01_2020-12-31`, but allow a couple different separators
88540               var parts = /^(.*)[–_](.*)$/g.exec(hash.photo_dates.trim());
88541               this.setDateFilter('fromDate', parts && parts.length >= 2 && parts[1], false);
88542               this.setDateFilter('toDate', parts && parts.length >= 3 && parts[2], false);
88543             }
88544
88545             if (hash.photo_username) {
88546               this.setUsernameFilter(hash.photo_username, false);
88547             }
88548
88549             if (hash.photo_overlay) {
88550               // support enabling photo layers by default via a URL parameter, e.g. `photo_overlay=kartaview;mapillary;streetside`
88551               var hashOverlayIDs = hash.photo_overlay.replace(/;/g, ',').split(',');
88552               hashOverlayIDs.forEach(function (id) {
88553                 if (id === 'openstreetcam') id = 'kartaview'; // legacy alias
88554
88555                 var layer = _layerIDs.indexOf(id) !== -1 && context.layers().layer(id);
88556                 if (layer && !layer.enabled()) layer.enabled(true);
88557               });
88558             }
88559
88560             if (hash.photo) {
88561               // support opening a photo via a URL parameter, e.g. `photo=mapillary-fztgSDtLpa08ohPZFZjeRQ`
88562               var photoIds = hash.photo.replace(/;/g, ',').split(',');
88563               var photoId = photoIds.length && photoIds[0].trim();
88564               var results = /(.*)\/(.*)/g.exec(photoId);
88565
88566               if (results && results.length >= 3) {
88567                 var serviceId = results[1];
88568                 if (serviceId === 'openstreetcam') serviceId = 'kartaview'; // legacy alias
88569
88570                 var photoKey = results[2];
88571                 var service = services[serviceId];
88572
88573                 if (service && service.ensureViewerLoaded) {
88574                   // if we're showing a photo then make sure its layer is enabled too
88575                   var layer = _layerIDs.indexOf(serviceId) !== -1 && context.layers().layer(serviceId);
88576                   if (layer && !layer.enabled()) layer.enabled(true);
88577                   var baselineTime = Date.now();
88578                   service.on('loadedImages.rendererPhotos', function () {
88579                     // don't open the viewer if too much time has elapsed
88580                     if (Date.now() - baselineTime > 45000) {
88581                       service.on('loadedImages.rendererPhotos', null);
88582                       return;
88583                     }
88584
88585                     if (!service.cachedImage(photoKey)) return;
88586                     service.on('loadedImages.rendererPhotos', null);
88587                     service.ensureViewerLoaded(context).then(function () {
88588                       service.selectImage(context, photoKey).showViewer(context);
88589                     });
88590                   });
88591                 }
88592               }
88593             }
88594
88595             context.layers().on('change.rendererPhotos', updateStorage);
88596           };
88597
88598           return utilRebind(photos, dispatch, 'on');
88599         }
88600
88601         function uiAccount(context) {
88602           var osm = context.connection();
88603
88604           function update(selection) {
88605             if (!osm) return;
88606
88607             if (!osm.authenticated()) {
88608               selection.selectAll('.userLink, .logoutLink').classed('hide', true);
88609               return;
88610             }
88611
88612             osm.userDetails(function (err, details) {
88613               var userLink = selection.select('.userLink'),
88614                   logoutLink = selection.select('.logoutLink');
88615               userLink.html('');
88616               logoutLink.html('');
88617               if (err || !details) return;
88618               selection.selectAll('.userLink, .logoutLink').classed('hide', false); // Link
88619
88620               var userLinkA = userLink.append('a').attr('href', osm.userURL(details.display_name)).attr('target', '_blank'); // Add thumbnail or dont
88621
88622               if (details.image_url) {
88623                 userLinkA.append('img').attr('class', 'icon pre-text user-icon').attr('src', details.image_url);
88624               } else {
88625                 userLinkA.call(svgIcon('#iD-icon-avatar', 'pre-text light'));
88626               } // Add user name
88627
88628
88629               userLinkA.append('span').attr('class', 'label').html(details.display_name);
88630               logoutLink.append('a').attr('class', 'logout').attr('href', '#').call(_t.append('logout')).on('click.logout', function (d3_event) {
88631                 d3_event.preventDefault();
88632                 osm.logout();
88633               });
88634             });
88635           }
88636
88637           return function (selection) {
88638             selection.append('li').attr('class', 'userLink').classed('hide', true);
88639             selection.append('li').attr('class', 'logoutLink').classed('hide', true);
88640
88641             if (osm) {
88642               osm.on('change.account', function () {
88643                 update(selection);
88644               });
88645               update(selection);
88646             }
88647           };
88648         }
88649
88650         function uiAttribution(context) {
88651           var _selection = select(null);
88652
88653           function render(selection, data, klass) {
88654             var div = selection.selectAll(".".concat(klass)).data([0]);
88655             div = div.enter().append('div').attr('class', klass).merge(div);
88656             var attributions = div.selectAll('.attribution').data(data, function (d) {
88657               return d.id;
88658             });
88659             attributions.exit().remove();
88660             attributions = attributions.enter().append('span').attr('class', 'attribution').each(function (d, i, nodes) {
88661               var attribution = select(nodes[i]);
88662
88663               if (d.terms_html) {
88664                 attribution.html(d.terms_html);
88665                 return;
88666               }
88667
88668               if (d.terms_url) {
88669                 attribution = attribution.append('a').attr('href', d.terms_url).attr('target', '_blank');
88670               }
88671
88672               var sourceID = d.id.replace(/\./g, '<TX_DOT>');
88673               var terms_text = _t("imagery.".concat(sourceID, ".attribution.text"), {
88674                 "default": d.terms_text || d.id || d.name()
88675               });
88676
88677               if (d.icon && !d.overlay) {
88678                 attribution.append('img').attr('class', 'source-image').attr('src', d.icon);
88679               }
88680
88681               attribution.append('span').attr('class', 'attribution-text').text(terms_text);
88682             }).merge(attributions);
88683             var copyright = attributions.selectAll('.copyright-notice').data(function (d) {
88684               var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
88685               return notice ? [notice] : [];
88686             });
88687             copyright.exit().remove();
88688             copyright = copyright.enter().append('span').attr('class', 'copyright-notice').merge(copyright);
88689             copyright.text(String);
88690           }
88691
88692           function update() {
88693             var baselayer = context.background().baseLayerSource();
88694
88695             _selection.call(render, baselayer ? [baselayer] : [], 'base-layer-attribution');
88696
88697             var z = context.map().zoom();
88698             var overlays = context.background().overlayLayerSources() || [];
88699
88700             _selection.call(render, overlays.filter(function (s) {
88701               return s.validZoom(z);
88702             }), 'overlay-layer-attribution');
88703           }
88704
88705           return function (selection) {
88706             _selection = selection;
88707             context.background().on('change.attribution', update);
88708             context.map().on('move.attribution', throttle(update, 400, {
88709               leading: false
88710             }));
88711             update();
88712           };
88713         }
88714
88715         function uiContributors(context) {
88716           var osm = context.connection(),
88717               debouncedUpdate = debounce(function () {
88718             update();
88719           }, 1000),
88720               limit = 4,
88721               hidden = false,
88722               wrap = select(null);
88723
88724           function update() {
88725             if (!osm) return;
88726             var users = {},
88727                 entities = context.history().intersects(context.map().extent());
88728             entities.forEach(function (entity) {
88729               if (entity && entity.user) users[entity.user] = true;
88730             });
88731             var u = Object.keys(users),
88732                 subset = u.slice(0, u.length > limit ? limit - 1 : limit);
88733             wrap.html('').call(svgIcon('#iD-icon-nearby', 'pre-text light'));
88734             var userList = select(document.createElement('span'));
88735             userList.selectAll().data(subset).enter().append('a').attr('class', 'user-link').attr('href', function (d) {
88736               return osm.userURL(d);
88737             }).attr('target', '_blank').text(String);
88738
88739             if (u.length > limit) {
88740               var count = select(document.createElement('span'));
88741               var othersNum = u.length - limit + 1;
88742               count.append('a').attr('target', '_blank').attr('href', function () {
88743                 return osm.changesetsURL(context.map().center(), context.map().zoom());
88744               }).text(othersNum);
88745               wrap.append('span').html(_t.html('contributors.truncated_list', {
88746                 n: othersNum,
88747                 users: {
88748                   html: userList.html()
88749                 },
88750                 count: {
88751                   html: count.html()
88752                 }
88753               }));
88754             } else {
88755               wrap.append('span').html(_t.html('contributors.list', {
88756                 users: {
88757                   html: userList.html()
88758                 }
88759               }));
88760             }
88761
88762             if (!u.length) {
88763               hidden = true;
88764               wrap.transition().style('opacity', 0);
88765             } else if (hidden) {
88766               wrap.transition().style('opacity', 1);
88767             }
88768           }
88769
88770           return function (selection) {
88771             if (!osm) return;
88772             wrap = selection;
88773             update();
88774             osm.on('loaded.contributors', debouncedUpdate);
88775             context.map().on('move.contributors', debouncedUpdate);
88776           };
88777         }
88778
88779         var _popoverID = 0;
88780         function uiPopover(klass) {
88781           var _id = _popoverID++;
88782
88783           var _anchorSelection = select(null);
88784
88785           var popover = function popover(selection) {
88786             _anchorSelection = selection;
88787             selection.each(setup);
88788           };
88789
88790           var _animation = utilFunctor(false);
88791
88792           var _placement = utilFunctor('top'); // top, bottom, left, right
88793
88794
88795           var _alignment = utilFunctor('center'); // leading, center, trailing
88796
88797
88798           var _scrollContainer = utilFunctor(select(null));
88799
88800           var _content;
88801
88802           var _displayType = utilFunctor('');
88803
88804           var _hasArrow = utilFunctor(true); // use pointer events on supported platforms; fallback to mouse events
88805
88806
88807           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
88808
88809           popover.displayType = function (val) {
88810             if (arguments.length) {
88811               _displayType = utilFunctor(val);
88812               return popover;
88813             } else {
88814               return _displayType;
88815             }
88816           };
88817
88818           popover.hasArrow = function (val) {
88819             if (arguments.length) {
88820               _hasArrow = utilFunctor(val);
88821               return popover;
88822             } else {
88823               return _hasArrow;
88824             }
88825           };
88826
88827           popover.placement = function (val) {
88828             if (arguments.length) {
88829               _placement = utilFunctor(val);
88830               return popover;
88831             } else {
88832               return _placement;
88833             }
88834           };
88835
88836           popover.alignment = function (val) {
88837             if (arguments.length) {
88838               _alignment = utilFunctor(val);
88839               return popover;
88840             } else {
88841               return _alignment;
88842             }
88843           };
88844
88845           popover.scrollContainer = function (val) {
88846             if (arguments.length) {
88847               _scrollContainer = utilFunctor(val);
88848               return popover;
88849             } else {
88850               return _scrollContainer;
88851             }
88852           };
88853
88854           popover.content = function (val) {
88855             if (arguments.length) {
88856               _content = val;
88857               return popover;
88858             } else {
88859               return _content;
88860             }
88861           };
88862
88863           popover.isShown = function () {
88864             var popoverSelection = _anchorSelection.select('.popover-' + _id);
88865
88866             return !popoverSelection.empty() && popoverSelection.classed('in');
88867           };
88868
88869           popover.show = function () {
88870             _anchorSelection.each(show);
88871           };
88872
88873           popover.updateContent = function () {
88874             _anchorSelection.each(updateContent);
88875           };
88876
88877           popover.hide = function () {
88878             _anchorSelection.each(hide);
88879           };
88880
88881           popover.toggle = function () {
88882             _anchorSelection.each(toggle);
88883           };
88884
88885           popover.destroy = function (selection, selector) {
88886             // by default, just destroy the current popover
88887             selector = selector || '.popover-' + _id;
88888             selection.on(_pointerPrefix + 'enter.popover', null).on(_pointerPrefix + 'leave.popover', null).on(_pointerPrefix + 'up.popover', null).on(_pointerPrefix + 'down.popover', null).on('click.popover', null).attr('title', function () {
88889               return this.getAttribute('data-original-title') || this.getAttribute('title');
88890             }).attr('data-original-title', null).selectAll(selector).remove();
88891           };
88892
88893           popover.destroyAny = function (selection) {
88894             selection.call(popover.destroy, '.popover');
88895           };
88896
88897           function setup() {
88898             var anchor = select(this);
88899
88900             var animate = _animation.apply(this, arguments);
88901
88902             var popoverSelection = anchor.selectAll('.popover-' + _id).data([0]);
88903             var enter = popoverSelection.enter().append('div').attr('class', 'popover popover-' + _id + ' ' + (klass ? klass : '')).classed('arrowed', _hasArrow.apply(this, arguments));
88904             enter.append('div').attr('class', 'popover-arrow');
88905             enter.append('div').attr('class', 'popover-inner');
88906             popoverSelection = enter.merge(popoverSelection);
88907
88908             if (animate) {
88909               popoverSelection.classed('fade', true);
88910             }
88911
88912             var display = _displayType.apply(this, arguments);
88913
88914             if (display === 'hover') {
88915               var _lastNonMouseEnterTime;
88916
88917               anchor.on(_pointerPrefix + 'enter.popover', function (d3_event) {
88918                 if (d3_event.pointerType) {
88919                   if (d3_event.pointerType !== 'mouse') {
88920                     _lastNonMouseEnterTime = d3_event.timeStamp; // only allow hover behavior for mouse input
88921
88922                     return;
88923                   } else if (_lastNonMouseEnterTime && d3_event.timeStamp - _lastNonMouseEnterTime < 1500) {
88924                     // HACK: iOS 13.4 sends an erroneous `mouse` type pointerenter
88925                     // event for non-mouse interactions right after sending
88926                     // the correct type pointerenter event. Workaround by discarding
88927                     // any mouse event that occurs immediately after a non-mouse event.
88928                     return;
88929                   }
88930                 } // don't show if buttons are pressed, e.g. during click and drag of map
88931
88932
88933                 if (d3_event.buttons !== 0) return;
88934                 show.apply(this, arguments);
88935               }).on(_pointerPrefix + 'leave.popover', function () {
88936                 hide.apply(this, arguments);
88937               }) // show on focus too for better keyboard navigation support
88938               .on('focus.popover', function () {
88939                 show.apply(this, arguments);
88940               }).on('blur.popover', function () {
88941                 hide.apply(this, arguments);
88942               });
88943             } else if (display === 'clickFocus') {
88944               anchor.on(_pointerPrefix + 'down.popover', function (d3_event) {
88945                 d3_event.preventDefault();
88946                 d3_event.stopPropagation();
88947               }).on(_pointerPrefix + 'up.popover', function (d3_event) {
88948                 d3_event.preventDefault();
88949                 d3_event.stopPropagation();
88950               }).on('click.popover', toggle);
88951               popoverSelection // This attribute lets the popover take focus
88952               .attr('tabindex', 0).on('blur.popover', function () {
88953                 anchor.each(function () {
88954                   hide.apply(this, arguments);
88955                 });
88956               });
88957             }
88958           }
88959
88960           function show() {
88961             var anchor = select(this);
88962             var popoverSelection = anchor.selectAll('.popover-' + _id);
88963
88964             if (popoverSelection.empty()) {
88965               // popover was removed somehow, put it back
88966               anchor.call(popover.destroy);
88967               anchor.each(setup);
88968               popoverSelection = anchor.selectAll('.popover-' + _id);
88969             }
88970
88971             popoverSelection.classed('in', true);
88972
88973             var displayType = _displayType.apply(this, arguments);
88974
88975             if (displayType === 'clickFocus') {
88976               anchor.classed('active', true);
88977               popoverSelection.node().focus();
88978             }
88979
88980             anchor.each(updateContent);
88981           }
88982
88983           function updateContent() {
88984             var anchor = select(this);
88985
88986             if (_content) {
88987               anchor.selectAll('.popover-' + _id + ' > .popover-inner').call(_content.apply(this, arguments));
88988             }
88989
88990             updatePosition.apply(this, arguments); // hack: update multiple times to fix instances where the absolute offset is
88991             // set before the dynamic popover size is calculated by the browser
88992
88993             updatePosition.apply(this, arguments);
88994             updatePosition.apply(this, arguments);
88995           }
88996
88997           function updatePosition() {
88998             var anchor = select(this);
88999             var popoverSelection = anchor.selectAll('.popover-' + _id);
89000
89001             var scrollContainer = _scrollContainer && _scrollContainer.apply(this, arguments);
89002
89003             var scrollNode = scrollContainer && !scrollContainer.empty() && scrollContainer.node();
89004             var scrollLeft = scrollNode ? scrollNode.scrollLeft : 0;
89005             var scrollTop = scrollNode ? scrollNode.scrollTop : 0;
89006
89007             var placement = _placement.apply(this, arguments);
89008
89009             popoverSelection.classed('left', false).classed('right', false).classed('top', false).classed('bottom', false).classed(placement, true);
89010
89011             var alignment = _alignment.apply(this, arguments);
89012
89013             var alignFactor = 0.5;
89014
89015             if (alignment === 'leading') {
89016               alignFactor = 0;
89017             } else if (alignment === 'trailing') {
89018               alignFactor = 1;
89019             }
89020
89021             var anchorFrame = getFrame(anchor.node());
89022             var popoverFrame = getFrame(popoverSelection.node());
89023             var position;
89024
89025             switch (placement) {
89026               case 'top':
89027                 position = {
89028                   x: anchorFrame.x + (anchorFrame.w - popoverFrame.w) * alignFactor,
89029                   y: anchorFrame.y - popoverFrame.h
89030                 };
89031                 break;
89032
89033               case 'bottom':
89034                 position = {
89035                   x: anchorFrame.x + (anchorFrame.w - popoverFrame.w) * alignFactor,
89036                   y: anchorFrame.y + anchorFrame.h
89037                 };
89038                 break;
89039
89040               case 'left':
89041                 position = {
89042                   x: anchorFrame.x - popoverFrame.w,
89043                   y: anchorFrame.y + (anchorFrame.h - popoverFrame.h) * alignFactor
89044                 };
89045                 break;
89046
89047               case 'right':
89048                 position = {
89049                   x: anchorFrame.x + anchorFrame.w,
89050                   y: anchorFrame.y + (anchorFrame.h - popoverFrame.h) * alignFactor
89051                 };
89052                 break;
89053             }
89054
89055             if (position) {
89056               if (scrollNode && (placement === 'top' || placement === 'bottom')) {
89057                 var initialPosX = position.x;
89058
89059                 if (position.x + popoverFrame.w > scrollNode.offsetWidth - 10) {
89060                   position.x = scrollNode.offsetWidth - 10 - popoverFrame.w;
89061                 } else if (position.x < 10) {
89062                   position.x = 10;
89063                 }
89064
89065                 var arrow = anchor.selectAll('.popover-' + _id + ' > .popover-arrow'); // keep the arrow centered on the button, or as close as possible
89066
89067                 var arrowPosX = Math.min(Math.max(popoverFrame.w / 2 - (position.x - initialPosX), 10), popoverFrame.w - 10);
89068                 arrow.style('left', ~~arrowPosX + 'px');
89069               }
89070
89071               popoverSelection.style('left', ~~position.x + 'px').style('top', ~~position.y + 'px');
89072             } else {
89073               popoverSelection.style('left', null).style('top', null);
89074             }
89075
89076             function getFrame(node) {
89077               var positionStyle = select(node).style('position');
89078
89079               if (positionStyle === 'absolute' || positionStyle === 'static') {
89080                 return {
89081                   x: node.offsetLeft - scrollLeft,
89082                   y: node.offsetTop - scrollTop,
89083                   w: node.offsetWidth,
89084                   h: node.offsetHeight
89085                 };
89086               } else {
89087                 return {
89088                   x: 0,
89089                   y: 0,
89090                   w: node.offsetWidth,
89091                   h: node.offsetHeight
89092                 };
89093               }
89094             }
89095           }
89096
89097           function hide() {
89098             var anchor = select(this);
89099
89100             if (_displayType.apply(this, arguments) === 'clickFocus') {
89101               anchor.classed('active', false);
89102             }
89103
89104             anchor.selectAll('.popover-' + _id).classed('in', false);
89105           }
89106
89107           function toggle() {
89108             if (select(this).select('.popover-' + _id).classed('in')) {
89109               hide.apply(this, arguments);
89110             } else {
89111               show.apply(this, arguments);
89112             }
89113           }
89114
89115           return popover;
89116         }
89117
89118         function uiTooltip(klass) {
89119           var tooltip = uiPopover((klass || '') + ' tooltip').displayType('hover');
89120
89121           var _title = function _title() {
89122             var title = this.getAttribute('data-original-title');
89123
89124             if (title) {
89125               return title;
89126             } else {
89127               title = this.getAttribute('title');
89128               this.removeAttribute('title');
89129               this.setAttribute('data-original-title', title);
89130             }
89131
89132             return title;
89133           };
89134
89135           var _heading = utilFunctor(null);
89136
89137           var _keys = utilFunctor(null);
89138
89139           tooltip.title = function (val) {
89140             if (!arguments.length) return _title;
89141             _title = utilFunctor(val);
89142             return tooltip;
89143           };
89144
89145           tooltip.heading = function (val) {
89146             if (!arguments.length) return _heading;
89147             _heading = utilFunctor(val);
89148             return tooltip;
89149           };
89150
89151           tooltip.keys = function (val) {
89152             if (!arguments.length) return _keys;
89153             _keys = utilFunctor(val);
89154             return tooltip;
89155           };
89156
89157           tooltip.content(function () {
89158             var heading = _heading.apply(this, arguments);
89159
89160             var text = _title.apply(this, arguments);
89161
89162             var keys = _keys.apply(this, arguments);
89163
89164             return function (selection) {
89165               var headingSelect = selection.selectAll('.tooltip-heading').data(heading ? [heading] : []);
89166               headingSelect.exit().remove();
89167               headingSelect.enter().append('div').attr('class', 'tooltip-heading').merge(headingSelect).html(heading);
89168               var textSelect = selection.selectAll('.tooltip-text').data(text ? [text] : []);
89169               textSelect.exit().remove();
89170               textSelect.enter().append('div').attr('class', 'tooltip-text').merge(textSelect).html(text);
89171               var keyhintWrap = selection.selectAll('.keyhint-wrap').data(keys && keys.length ? [0] : []);
89172               keyhintWrap.exit().remove();
89173               var keyhintWrapEnter = keyhintWrap.enter().append('div').attr('class', 'keyhint-wrap');
89174               keyhintWrapEnter.append('span').call(_t.append('tooltip_keyhint'));
89175               keyhintWrap = keyhintWrapEnter.merge(keyhintWrap);
89176               keyhintWrap.selectAll('kbd.shortcut').data(keys && keys.length ? keys : []).enter().append('kbd').attr('class', 'shortcut').html(function (d) {
89177                 return d;
89178               });
89179             };
89180           });
89181           return tooltip;
89182         }
89183
89184         function uiEditMenu(context) {
89185           var dispatch = dispatch$8('toggled');
89186
89187           var _menu = select(null);
89188
89189           var _operations = []; // the position the menu should be displayed relative to
89190
89191           var _anchorLoc = [0, 0];
89192           var _anchorLocLonLat = [0, 0]; // a string indicating how the menu was opened
89193
89194           var _triggerType = '';
89195           var _vpTopMargin = 85; // viewport top margin
89196
89197           var _vpBottomMargin = 45; // viewport bottom margin
89198
89199           var _vpSideMargin = 35; // viewport side margin
89200
89201           var _menuTop = false;
89202
89203           var _menuHeight;
89204
89205           var _menuWidth; // hardcode these values to make menu positioning easier
89206
89207
89208           var _verticalPadding = 4; // see also `.edit-menu .tooltip` CSS; include margin
89209
89210           var _tooltipWidth = 210; // offset the menu slightly from the target location
89211
89212           var _menuSideMargin = 10;
89213           var _tooltips = [];
89214
89215           var editMenu = function editMenu(selection) {
89216             var isTouchMenu = _triggerType.includes('touch') || _triggerType.includes('pen');
89217
89218             var ops = _operations.filter(function (op) {
89219               return !isTouchMenu || !op.mouseOnly;
89220             });
89221
89222             if (!ops.length) return;
89223             _tooltips = []; // Position the menu above the anchor for stylus and finger input
89224             // since the mapper's hand likely obscures the screen below the anchor
89225
89226             _menuTop = isTouchMenu; // Show labels for touch input since there aren't hover tooltips
89227
89228             var showLabels = isTouchMenu;
89229             var buttonHeight = showLabels ? 32 : 34;
89230
89231             if (showLabels) {
89232               // Get a general idea of the width based on the length of the label
89233               _menuWidth = 52 + Math.min(120, 6 * Math.max.apply(Math, ops.map(function (op) {
89234                 return op.title.length;
89235               })));
89236             } else {
89237               _menuWidth = 44;
89238             }
89239
89240             _menuHeight = _verticalPadding * 2 + ops.length * buttonHeight;
89241             _menu = selection.append('div').attr('class', 'edit-menu').classed('touch-menu', isTouchMenu).style('padding', _verticalPadding + 'px 0');
89242
89243             var buttons = _menu.selectAll('.edit-menu-item').data(ops); // enter
89244
89245
89246             var buttonsEnter = buttons.enter().append('button').attr('class', function (d) {
89247               return 'edit-menu-item edit-menu-item-' + d.id;
89248             }).style('height', buttonHeight + 'px').on('click', click) // don't listen for `mouseup` because we only care about non-mouse pointer types
89249             .on('pointerup', pointerup).on('pointerdown mousedown', function pointerdown(d3_event) {
89250               // don't let button presses also act as map input - #1869
89251               d3_event.stopPropagation();
89252             }).on('mouseenter.highlight', function (d3_event, d) {
89253               if (!d.relatedEntityIds || select(this).classed('disabled')) return;
89254               utilHighlightEntities(d.relatedEntityIds(), true, context);
89255             }).on('mouseleave.highlight', function (d3_event, d) {
89256               if (!d.relatedEntityIds) return;
89257               utilHighlightEntities(d.relatedEntityIds(), false, context);
89258             });
89259             buttonsEnter.each(function (d) {
89260               var tooltip = uiTooltip().heading(d.title).title(d.tooltip()).keys([d.keys[0]]);
89261
89262               _tooltips.push(tooltip);
89263
89264               select(this).call(tooltip).append('div').attr('class', 'icon-wrap').call(svgIcon(d.icon && d.icon() || '#iD-operation-' + d.id, 'operation'));
89265             });
89266
89267             if (showLabels) {
89268               buttonsEnter.append('span').attr('class', 'label').html(function (d) {
89269                 return d.title;
89270               });
89271             } // update
89272
89273
89274             buttonsEnter.merge(buttons).classed('disabled', function (d) {
89275               return d.disabled();
89276             });
89277             updatePosition();
89278             var initialScale = context.projection.scale();
89279             context.map().on('move.edit-menu', function () {
89280               if (initialScale !== context.projection.scale()) {
89281                 editMenu.close();
89282               }
89283             }).on('drawn.edit-menu', function (info) {
89284               if (info.full) updatePosition();
89285             });
89286             var lastPointerUpType; // `pointerup` is always called before `click`
89287
89288             function pointerup(d3_event) {
89289               lastPointerUpType = d3_event.pointerType;
89290             }
89291
89292             function click(d3_event, operation) {
89293               d3_event.stopPropagation();
89294
89295               if (operation.relatedEntityIds) {
89296                 utilHighlightEntities(operation.relatedEntityIds(), false, context);
89297               }
89298
89299               if (operation.disabled()) {
89300                 if (lastPointerUpType === 'touch' || lastPointerUpType === 'pen') {
89301                   // there are no tooltips for touch interactions so flash feedback instead
89302                   context.ui().flash.duration(4000).iconName('#iD-operation-' + operation.id).iconClass('operation disabled').label(operation.tooltip)();
89303                 }
89304               } else {
89305                 if (lastPointerUpType === 'touch' || lastPointerUpType === 'pen') {
89306                   context.ui().flash.duration(2000).iconName('#iD-operation-' + operation.id).iconClass('operation').label(operation.annotation() || operation.title)();
89307                 }
89308
89309                 operation();
89310                 editMenu.close();
89311               }
89312
89313               lastPointerUpType = null;
89314             }
89315
89316             dispatch.call('toggled', this, true);
89317           };
89318
89319           function updatePosition() {
89320             if (!_menu || _menu.empty()) return;
89321             var anchorLoc = context.projection(_anchorLocLonLat);
89322             var viewport = context.surfaceRect();
89323
89324             if (anchorLoc[0] < 0 || anchorLoc[0] > viewport.width || anchorLoc[1] < 0 || anchorLoc[1] > viewport.height) {
89325               // close the menu if it's gone offscreen
89326               editMenu.close();
89327               return;
89328             }
89329
89330             var menuLeft = displayOnLeft(viewport);
89331             var offset = [0, 0];
89332             offset[0] = menuLeft ? -1 * (_menuSideMargin + _menuWidth) : _menuSideMargin;
89333
89334             if (_menuTop) {
89335               if (anchorLoc[1] - _menuHeight < _vpTopMargin) {
89336                 // menu is near top viewport edge, shift downward
89337                 offset[1] = -anchorLoc[1] + _vpTopMargin;
89338               } else {
89339                 offset[1] = -_menuHeight;
89340               }
89341             } else {
89342               if (anchorLoc[1] + _menuHeight > viewport.height - _vpBottomMargin) {
89343                 // menu is near bottom viewport edge, shift upwards
89344                 offset[1] = -anchorLoc[1] - _menuHeight + viewport.height - _vpBottomMargin;
89345               } else {
89346                 offset[1] = 0;
89347               }
89348             }
89349
89350             var origin = geoVecAdd(anchorLoc, offset);
89351
89352             _menu.style('left', origin[0] + 'px').style('top', origin[1] + 'px');
89353
89354             var tooltipSide = tooltipPosition(viewport, menuLeft);
89355
89356             _tooltips.forEach(function (tooltip) {
89357               tooltip.placement(tooltipSide);
89358             });
89359
89360             function displayOnLeft(viewport) {
89361               if (_mainLocalizer.textDirection() === 'ltr') {
89362                 if (anchorLoc[0] + _menuSideMargin + _menuWidth > viewport.width - _vpSideMargin) {
89363                   // right menu would be too close to the right viewport edge, go left
89364                   return true;
89365                 } // prefer right menu
89366
89367
89368                 return false;
89369               } else {
89370                 // rtl
89371                 if (anchorLoc[0] - _menuSideMargin - _menuWidth < _vpSideMargin) {
89372                   // left menu would be too close to the left viewport edge, go right
89373                   return false;
89374                 } // prefer left menu
89375
89376
89377                 return true;
89378               }
89379             }
89380
89381             function tooltipPosition(viewport, menuLeft) {
89382               if (_mainLocalizer.textDirection() === 'ltr') {
89383                 if (menuLeft) {
89384                   // if there's not room for a right-side menu then there definitely
89385                   // isn't room for right-side tooltips
89386                   return 'left';
89387                 }
89388
89389                 if (anchorLoc[0] + _menuSideMargin + _menuWidth + _tooltipWidth > viewport.width - _vpSideMargin) {
89390                   // right tooltips would be too close to the right viewport edge, go left
89391                   return 'left';
89392                 } // prefer right tooltips
89393
89394
89395                 return 'right';
89396               } else {
89397                 // rtl
89398                 if (!menuLeft) {
89399                   return 'right';
89400                 }
89401
89402                 if (anchorLoc[0] - _menuSideMargin - _menuWidth - _tooltipWidth < _vpSideMargin) {
89403                   // left tooltips would be too close to the left viewport edge, go right
89404                   return 'right';
89405                 } // prefer left tooltips
89406
89407
89408                 return 'left';
89409               }
89410             }
89411           }
89412
89413           editMenu.close = function () {
89414             context.map().on('move.edit-menu', null).on('drawn.edit-menu', null);
89415
89416             _menu.remove();
89417
89418             _tooltips = [];
89419             dispatch.call('toggled', this, false);
89420           };
89421
89422           editMenu.anchorLoc = function (val) {
89423             if (!arguments.length) return _anchorLoc;
89424             _anchorLoc = val;
89425             _anchorLocLonLat = context.projection.invert(_anchorLoc);
89426             return editMenu;
89427           };
89428
89429           editMenu.triggerType = function (val) {
89430             if (!arguments.length) return _triggerType;
89431             _triggerType = val;
89432             return editMenu;
89433           };
89434
89435           editMenu.operations = function (val) {
89436             if (!arguments.length) return _operations;
89437             _operations = val;
89438             return editMenu;
89439           };
89440
89441           return utilRebind(editMenu, dispatch, 'on');
89442         }
89443
89444         function uiFeatureInfo(context) {
89445           function update(selection) {
89446             var features = context.features();
89447             var stats = features.stats();
89448             var count = 0;
89449             var hiddenList = features.hidden().map(function (k) {
89450               if (stats[k]) {
89451                 count += stats[k];
89452                 return _t.html('inspector.title_count', {
89453                   title: {
89454                     html: _t.html('feature.' + k + '.description')
89455                   },
89456                   count: stats[k]
89457                 });
89458               }
89459
89460               return null;
89461             }).filter(Boolean);
89462             selection.html('');
89463
89464             if (hiddenList.length) {
89465               var tooltipBehavior = uiTooltip().placement('top').title(function () {
89466                 return hiddenList.join('<br/>');
89467               });
89468               selection.append('a').attr('class', 'chip').attr('href', '#').call(_t.append('feature_info.hidden_warning', {
89469                 count: count
89470               })).call(tooltipBehavior).on('click', function (d3_event) {
89471                 tooltipBehavior.hide();
89472                 d3_event.preventDefault(); // open the Map Data pane
89473
89474                 context.ui().togglePanes(context.container().select('.map-panes .map-data-pane'));
89475               });
89476             }
89477
89478             selection.classed('hide', !hiddenList.length);
89479           }
89480
89481           return function (selection) {
89482             update(selection);
89483             context.features().on('change.feature_info', function () {
89484               update(selection);
89485             });
89486           };
89487         }
89488
89489         function uiFlash(context) {
89490           var _flashTimer;
89491
89492           var _duration = 2000;
89493           var _iconName = '#iD-icon-no';
89494           var _iconClass = 'disabled';
89495           var _label = '';
89496
89497           function flash() {
89498             if (_flashTimer) {
89499               _flashTimer.stop();
89500             }
89501
89502             context.container().select('.main-footer-wrap').classed('footer-hide', true).classed('footer-show', false);
89503             context.container().select('.flash-wrap').classed('footer-hide', false).classed('footer-show', true);
89504             var content = context.container().select('.flash-wrap').selectAll('.flash-content').data([0]); // Enter
89505
89506             var contentEnter = content.enter().append('div').attr('class', 'flash-content');
89507             var iconEnter = contentEnter.append('svg').attr('class', 'flash-icon icon').append('g').attr('transform', 'translate(10,10)');
89508             iconEnter.append('circle').attr('r', 9);
89509             iconEnter.append('use').attr('transform', 'translate(-7,-7)').attr('width', '14').attr('height', '14');
89510             contentEnter.append('div').attr('class', 'flash-text'); // Update
89511
89512             content = content.merge(contentEnter);
89513             content.selectAll('.flash-icon').attr('class', 'icon flash-icon ' + (_iconClass || ''));
89514             content.selectAll('.flash-icon use').attr('xlink:href', _iconName);
89515             content.selectAll('.flash-text').attr('class', 'flash-text').html(_label);
89516             _flashTimer = d3_timeout(function () {
89517               _flashTimer = null;
89518               context.container().select('.main-footer-wrap').classed('footer-hide', false).classed('footer-show', true);
89519               context.container().select('.flash-wrap').classed('footer-hide', true).classed('footer-show', false);
89520             }, _duration);
89521             return content;
89522           }
89523
89524           flash.duration = function (_) {
89525             if (!arguments.length) return _duration;
89526             _duration = _;
89527             return flash;
89528           };
89529
89530           flash.label = function (_) {
89531             if (!arguments.length) return _label;
89532             _label = _;
89533             return flash;
89534           };
89535
89536           flash.iconName = function (_) {
89537             if (!arguments.length) return _iconName;
89538             _iconName = _;
89539             return flash;
89540           };
89541
89542           flash.iconClass = function (_) {
89543             if (!arguments.length) return _iconClass;
89544             _iconClass = _;
89545             return flash;
89546           };
89547
89548           return flash;
89549         }
89550
89551         function uiFullScreen(context) {
89552           var element = context.container().node(); // var button = d3_select(null);
89553
89554           function getFullScreenFn() {
89555             if (element.requestFullscreen) {
89556               return element.requestFullscreen;
89557             } else if (element.msRequestFullscreen) {
89558               return element.msRequestFullscreen;
89559             } else if (element.mozRequestFullScreen) {
89560               return element.mozRequestFullScreen;
89561             } else if (element.webkitRequestFullscreen) {
89562               return element.webkitRequestFullscreen;
89563             }
89564           }
89565
89566           function getExitFullScreenFn() {
89567             if (document.exitFullscreen) {
89568               return document.exitFullscreen;
89569             } else if (document.msExitFullscreen) {
89570               return document.msExitFullscreen;
89571             } else if (document.mozCancelFullScreen) {
89572               return document.mozCancelFullScreen;
89573             } else if (document.webkitExitFullscreen) {
89574               return document.webkitExitFullscreen;
89575             }
89576           }
89577
89578           function isFullScreen() {
89579             return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement;
89580           }
89581
89582           function isSupported() {
89583             return !!getFullScreenFn();
89584           }
89585
89586           function fullScreen(d3_event) {
89587             d3_event.preventDefault();
89588
89589             if (!isFullScreen()) {
89590               // button.classed('active', true);
89591               getFullScreenFn().apply(element);
89592             } else {
89593               // button.classed('active', false);
89594               getExitFullScreenFn().apply(document);
89595             }
89596           }
89597
89598           return function () {
89599             // selection) {
89600             if (!isSupported()) return; // button = selection.append('button')
89601             //     .attr('title', t('full_screen'))
89602             //     .on('click', fullScreen)
89603             //     .call(tooltip);
89604             // button.append('span')
89605             //     .attr('class', 'icon full-screen');
89606
89607             var detected = utilDetect();
89608             var keys = detected.os === 'mac' ? [uiCmd('⌃⌘F'), 'f11'] : ['f11'];
89609             context.keybinding().on(keys, fullScreen);
89610           };
89611         }
89612
89613         function uiGeolocate(context) {
89614           var _geolocationOptions = {
89615             // prioritize speed and power usage over precision
89616             enableHighAccuracy: false,
89617             // don't hang indefinitely getting the location
89618             timeout: 6000 // 6sec
89619
89620           };
89621
89622           var _locating = uiLoading(context).message(_t.html('geolocate.locating')).blocking(true);
89623
89624           var _layer = context.layers().layer('geolocate');
89625
89626           var _position;
89627
89628           var _extent;
89629
89630           var _timeoutID;
89631
89632           var _button = select(null);
89633
89634           function click() {
89635             if (context.inIntro()) return;
89636
89637             if (!_layer.enabled() && !_locating.isShown()) {
89638               // This timeout ensures that we still call finish() even if
89639               // the user declines to share their location in Firefox
89640               _timeoutID = setTimeout(error, 10000
89641               /* 10sec */
89642               );
89643               context.container().call(_locating); // get the latest position even if we already have one
89644
89645               navigator.geolocation.getCurrentPosition(success, error, _geolocationOptions);
89646             } else {
89647               _locating.close();
89648
89649               _layer.enabled(null, false);
89650
89651               updateButtonState();
89652             }
89653           }
89654
89655           function zoomTo() {
89656             context.enter(modeBrowse(context));
89657             var map = context.map();
89658
89659             _layer.enabled(_position, true);
89660
89661             updateButtonState();
89662             map.centerZoomEase(_extent.center(), Math.min(20, map.extentZoom(_extent)));
89663           }
89664
89665           function success(geolocation) {
89666             _position = geolocation;
89667             var coords = _position.coords;
89668             _extent = geoExtent([coords.longitude, coords.latitude]).padByMeters(coords.accuracy);
89669             zoomTo();
89670             finish();
89671           }
89672
89673           function error() {
89674             if (_position) {
89675               // use the position from a previous call if we have one
89676               zoomTo();
89677             } else {
89678               context.ui().flash.label(_t.html('geolocate.location_unavailable')).iconName('#iD-icon-geolocate')();
89679             }
89680
89681             finish();
89682           }
89683
89684           function finish() {
89685             _locating.close(); // unblock ui
89686
89687
89688             if (_timeoutID) {
89689               clearTimeout(_timeoutID);
89690             }
89691
89692             _timeoutID = undefined;
89693           }
89694
89695           function updateButtonState() {
89696             _button.classed('active', _layer.enabled());
89697
89698             _button.attr('aria-pressed', _layer.enabled());
89699           }
89700
89701           return function (selection) {
89702             if (!navigator.geolocation || !navigator.geolocation.getCurrentPosition) return;
89703             _button = selection.append('button').on('click', click).attr('aria-pressed', false).call(svgIcon('#iD-icon-geolocate', 'light')).call(uiTooltip().placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left').title(_t.html('geolocate.title')).keys([_t('geolocate.key')]));
89704             context.keybinding().on(_t('geolocate.key'), click);
89705           };
89706         }
89707
89708         function uiPanelBackground(context) {
89709           var background = context.background();
89710           var _currSourceName = null;
89711           var _metadata = {};
89712           var _metadataKeys = ['zoom', 'vintage', 'source', 'description', 'resolution', 'accuracy'];
89713
89714           var debouncedRedraw = debounce(redraw, 250);
89715
89716           function redraw(selection) {
89717             var source = background.baseLayerSource();
89718             if (!source) return;
89719             var isDG = source.id.match(/^DigitalGlobe/i) !== null;
89720             var sourceLabel = source.label();
89721
89722             if (_currSourceName !== sourceLabel) {
89723               _currSourceName = sourceLabel;
89724               _metadata = {};
89725             }
89726
89727             selection.html('');
89728             var list = selection.append('ul').attr('class', 'background-info');
89729             list.append('li').html(_currSourceName);
89730
89731             _metadataKeys.forEach(function (k) {
89732               // DigitalGlobe vintage is available in raster layers for now.
89733               if (isDG && k === 'vintage') return;
89734               list.append('li').attr('class', 'background-info-list-' + k).classed('hide', !_metadata[k]).call(_t.append('info_panels.background.' + k, {
89735                 suffix: ':'
89736               })).append('span').attr('class', 'background-info-span-' + k).text(_metadata[k]);
89737             });
89738
89739             debouncedGetMetadata(selection);
89740             var toggleTiles = context.getDebug('tile') ? 'hide_tiles' : 'show_tiles';
89741             selection.append('a').call(_t.append('info_panels.background.' + toggleTiles)).attr('href', '#').attr('class', 'button button-toggle-tiles').on('click', function (d3_event) {
89742               d3_event.preventDefault();
89743               context.setDebug('tile', !context.getDebug('tile'));
89744               selection.call(redraw);
89745             });
89746
89747             if (isDG) {
89748               var key = source.id + '-vintage';
89749               var sourceVintage = context.background().findSource(key);
89750               var showsVintage = context.background().showsLayer(sourceVintage);
89751               var toggleVintage = showsVintage ? 'hide_vintage' : 'show_vintage';
89752               selection.append('a').call(_t.append('info_panels.background.' + toggleVintage)).attr('href', '#').attr('class', 'button button-toggle-vintage').on('click', function (d3_event) {
89753                 d3_event.preventDefault();
89754                 context.background().toggleOverlayLayer(sourceVintage);
89755                 selection.call(redraw);
89756               });
89757             } // disable if necessary
89758
89759
89760             ['DigitalGlobe-Premium', 'DigitalGlobe-Standard'].forEach(function (layerId) {
89761               if (source.id !== layerId) {
89762                 var key = layerId + '-vintage';
89763                 var sourceVintage = context.background().findSource(key);
89764
89765                 if (context.background().showsLayer(sourceVintage)) {
89766                   context.background().toggleOverlayLayer(sourceVintage);
89767                 }
89768               }
89769             });
89770           }
89771
89772           var debouncedGetMetadata = debounce(getMetadata, 250);
89773
89774           function getMetadata(selection) {
89775             var tile = context.container().select('.layer-background img.tile-center'); // tile near viewport center
89776
89777             if (tile.empty()) return;
89778             var sourceName = _currSourceName;
89779             var d = tile.datum();
89780             var zoom = d && d.length >= 3 && d[2] || Math.floor(context.map().zoom());
89781             var center = context.map().center(); // update zoom
89782
89783             _metadata.zoom = String(zoom);
89784             selection.selectAll('.background-info-list-zoom').classed('hide', false).selectAll('.background-info-span-zoom').text(_metadata.zoom);
89785             if (!d || !d.length >= 3) return;
89786             background.baseLayerSource().getMetadata(center, d, function (err, result) {
89787               if (err || _currSourceName !== sourceName) return; // update vintage
89788
89789               var vintage = result.vintage;
89790               _metadata.vintage = vintage && vintage.range || _t('info_panels.background.unknown');
89791               selection.selectAll('.background-info-list-vintage').classed('hide', false).selectAll('.background-info-span-vintage').text(_metadata.vintage); // update other _metadata
89792
89793               _metadataKeys.forEach(function (k) {
89794                 if (k === 'zoom' || k === 'vintage') return; // done already
89795
89796                 var val = result[k];
89797                 _metadata[k] = val;
89798                 selection.selectAll('.background-info-list-' + k).classed('hide', !val).selectAll('.background-info-span-' + k).text(val);
89799               });
89800             });
89801           }
89802
89803           var panel = function panel(selection) {
89804             selection.call(redraw);
89805             context.map().on('drawn.info-background', function () {
89806               selection.call(debouncedRedraw);
89807             }).on('move.info-background', function () {
89808               selection.call(debouncedGetMetadata);
89809             });
89810           };
89811
89812           panel.off = function () {
89813             context.map().on('drawn.info-background', null).on('move.info-background', null);
89814           };
89815
89816           panel.id = 'background';
89817           panel.label = _t.html('info_panels.background.title');
89818           panel.key = _t('info_panels.background.key');
89819           return panel;
89820         }
89821
89822         function uiPanelHistory(context) {
89823           var osm;
89824
89825           function displayTimestamp(timestamp) {
89826             if (!timestamp) return _t('info_panels.history.unknown');
89827             var options = {
89828               day: 'numeric',
89829               month: 'short',
89830               year: 'numeric',
89831               hour: 'numeric',
89832               minute: 'numeric',
89833               second: 'numeric'
89834             };
89835             var d = new Date(timestamp);
89836             if (isNaN(d.getTime())) return _t('info_panels.history.unknown');
89837             return d.toLocaleString(_mainLocalizer.localeCode(), options);
89838           }
89839
89840           function displayUser(selection, userName) {
89841             if (!userName) {
89842               selection.append('span').call(_t.append('info_panels.history.unknown'));
89843               return;
89844             }
89845
89846             selection.append('span').attr('class', 'user-name').text(userName);
89847             var links = selection.append('div').attr('class', 'links');
89848
89849             if (osm) {
89850               links.append('a').attr('class', 'user-osm-link').attr('href', osm.userURL(userName)).attr('target', '_blank').call(_t.append('info_panels.history.profile_link'));
89851             }
89852
89853             links.append('a').attr('class', 'user-hdyc-link').attr('href', 'https://hdyc.neis-one.org/?' + userName).attr('target', '_blank').attr('tabindex', -1).text('HDYC');
89854           }
89855
89856           function displayChangeset(selection, changeset) {
89857             if (!changeset) {
89858               selection.append('span').call(_t.append('info_panels.history.unknown'));
89859               return;
89860             }
89861
89862             selection.append('span').attr('class', 'changeset-id').text(changeset);
89863             var links = selection.append('div').attr('class', 'links');
89864
89865             if (osm) {
89866               links.append('a').attr('class', 'changeset-osm-link').attr('href', osm.changesetURL(changeset)).attr('target', '_blank').call(_t.append('info_panels.history.changeset_link'));
89867             }
89868
89869             links.append('a').attr('class', 'changeset-osmcha-link').attr('href', 'https://osmcha.org/changesets/' + changeset).attr('target', '_blank').text('OSMCha');
89870             links.append('a').attr('class', 'changeset-achavi-link').attr('href', 'https://overpass-api.de/achavi/?changeset=' + changeset).attr('target', '_blank').text('Achavi');
89871           }
89872
89873           function redraw(selection) {
89874             var selectedNoteID = context.selectedNoteID();
89875             osm = context.connection();
89876             var selected, note, entity;
89877
89878             if (selectedNoteID && osm) {
89879               // selected 1 note
89880               selected = [_t.html('note.note') + ' ' + selectedNoteID];
89881               note = osm.getNote(selectedNoteID);
89882             } else {
89883               // selected 1..n entities
89884               selected = context.selectedIDs().filter(function (e) {
89885                 return context.hasEntity(e);
89886               });
89887
89888               if (selected.length) {
89889                 entity = context.entity(selected[0]);
89890               }
89891             }
89892
89893             var singular = selected.length === 1 ? selected[0] : null;
89894             selection.html('');
89895
89896             if (singular) {
89897               selection.append('h4').attr('class', 'history-heading').html(singular);
89898             } else {
89899               selection.append('h4').attr('class', 'history-heading').call(_t.append('info_panels.selected', {
89900                 n: selected.length
89901               }));
89902             }
89903
89904             if (!singular) return;
89905
89906             if (entity) {
89907               selection.call(redrawEntity, entity);
89908             } else if (note) {
89909               selection.call(redrawNote, note);
89910             }
89911           }
89912
89913           function redrawNote(selection, note) {
89914             if (!note || note.isNew()) {
89915               selection.append('div').call(_t.append('info_panels.history.note_no_history'));
89916               return;
89917             }
89918
89919             var list = selection.append('ul');
89920             list.append('li').call(_t.append('info_panels.history.note_comments', {
89921               suffix: ':'
89922             })).append('span').text(note.comments.length);
89923
89924             if (note.comments.length) {
89925               list.append('li').call(_t.append('info_panels.history.note_created_date', {
89926                 suffix: ':'
89927               })).append('span').text(displayTimestamp(note.comments[0].date));
89928               list.append('li').call(_t.append('info_panels.history.note_created_user', {
89929                 suffix: ':'
89930               })).call(displayUser, note.comments[0].user);
89931             }
89932
89933             if (osm) {
89934               selection.append('a').attr('class', 'view-history-on-osm').attr('target', '_blank').attr('href', osm.noteURL(note)).call(svgIcon('#iD-icon-out-link', 'inline')).append('span').call(_t.append('info_panels.history.note_link_text'));
89935             }
89936           }
89937
89938           function redrawEntity(selection, entity) {
89939             if (!entity || entity.isNew()) {
89940               selection.append('div').call(_t.append('info_panels.history.no_history'));
89941               return;
89942             }
89943
89944             var links = selection.append('div').attr('class', 'links');
89945
89946             if (osm) {
89947               links.append('a').attr('class', 'view-history-on-osm').attr('href', osm.historyURL(entity)).attr('target', '_blank').call(_t.append('info_panels.history.history_link'));
89948             }
89949
89950             links.append('a').attr('class', 'pewu-history-viewer-link').attr('href', 'https://pewu.github.io/osm-history/#/' + entity.type + '/' + entity.osmId()).attr('target', '_blank').attr('tabindex', -1).text('PeWu');
89951             var list = selection.append('ul');
89952             list.append('li').call(_t.append('info_panels.history.version', {
89953               suffix: ':'
89954             })).append('span').text(entity.version);
89955             list.append('li').call(_t.append('info_panels.history.last_edit', {
89956               suffix: ':'
89957             })).append('span').text(displayTimestamp(entity.timestamp));
89958             list.append('li').call(_t.append('info_panels.history.edited_by', {
89959               suffix: ':'
89960             })).call(displayUser, entity.user);
89961             list.append('li').call(_t.append('info_panels.history.changeset', {
89962               suffix: ':'
89963             })).call(displayChangeset, entity.changeset);
89964           }
89965
89966           var panel = function panel(selection) {
89967             selection.call(redraw);
89968             context.map().on('drawn.info-history', function () {
89969               selection.call(redraw);
89970             });
89971             context.on('enter.info-history', function () {
89972               selection.call(redraw);
89973             });
89974           };
89975
89976           panel.off = function () {
89977             context.map().on('drawn.info-history', null);
89978             context.on('enter.info-history', null);
89979           };
89980
89981           panel.id = 'history';
89982           panel.label = _t.html('info_panels.history.title');
89983           panel.key = _t('info_panels.history.key');
89984           return panel;
89985         }
89986
89987         var OSM_PRECISION = 7;
89988         /**
89989          * Returns a localized representation of the given length measurement.
89990          *
89991          * @param {Number} m area in meters
89992          * @param {Boolean} isImperial true for U.S. customary units; false for metric
89993          */
89994
89995         function displayLength(m, isImperial) {
89996           var d = m * (isImperial ? 3.28084 : 1);
89997           var unit;
89998
89999           if (isImperial) {
90000             if (d >= 5280) {
90001               d /= 5280;
90002               unit = 'miles';
90003             } else {
90004               unit = 'feet';
90005             }
90006           } else {
90007             if (d >= 1000) {
90008               d /= 1000;
90009               unit = 'kilometers';
90010             } else {
90011               unit = 'meters';
90012             }
90013           }
90014
90015           return _t('units.' + unit, {
90016             quantity: d.toLocaleString(_mainLocalizer.localeCode(), {
90017               maximumSignificantDigits: 4
90018             })
90019           });
90020         }
90021         /**
90022          * Returns a localized representation of the given area measurement.
90023          *
90024          * @param {Number} m2 area in square meters
90025          * @param {Boolean} isImperial true for U.S. customary units; false for metric
90026          */
90027
90028         function displayArea(m2, isImperial) {
90029           var locale = _mainLocalizer.localeCode();
90030           var d = m2 * (isImperial ? 10.7639111056 : 1);
90031           var d1, d2, area;
90032           var unit1 = '';
90033           var unit2 = '';
90034
90035           if (isImperial) {
90036             if (d >= 6969600) {
90037               // > 0.25mi² show mi²
90038               d1 = d / 27878400;
90039               unit1 = 'square_miles';
90040             } else {
90041               d1 = d;
90042               unit1 = 'square_feet';
90043             }
90044
90045             if (d > 4356 && d < 43560000) {
90046               // 0.1 - 1000 acres
90047               d2 = d / 43560;
90048               unit2 = 'acres';
90049             }
90050           } else {
90051             if (d >= 250000) {
90052               // > 0.25km² show km²
90053               d1 = d / 1000000;
90054               unit1 = 'square_kilometers';
90055             } else {
90056               d1 = d;
90057               unit1 = 'square_meters';
90058             }
90059
90060             if (d > 1000 && d < 10000000) {
90061               // 0.1 - 1000 hectares
90062               d2 = d / 10000;
90063               unit2 = 'hectares';
90064             }
90065           }
90066
90067           area = _t('units.' + unit1, {
90068             quantity: d1.toLocaleString(locale, {
90069               maximumSignificantDigits: 4
90070             })
90071           });
90072
90073           if (d2) {
90074             return _t('units.area_pair', {
90075               area1: area,
90076               area2: _t('units.' + unit2, {
90077                 quantity: d2.toLocaleString(locale, {
90078                   maximumSignificantDigits: 2
90079                 })
90080               })
90081             });
90082           } else {
90083             return area;
90084           }
90085         }
90086
90087         function wrap(x, min, max) {
90088           var d = max - min;
90089           return ((x - min) % d + d) % d + min;
90090         }
90091
90092         function clamp(x, min, max) {
90093           return Math.max(min, Math.min(x, max));
90094         }
90095
90096         function displayCoordinate(deg, pos, neg) {
90097           var locale = _mainLocalizer.localeCode();
90098           var min = (Math.abs(deg) - Math.floor(Math.abs(deg))) * 60;
90099           var sec = (min - Math.floor(min)) * 60;
90100           var displayDegrees = _t('units.arcdegrees', {
90101             quantity: Math.floor(Math.abs(deg)).toLocaleString(locale)
90102           });
90103           var displayCoordinate;
90104
90105           if (Math.floor(sec) > 0) {
90106             displayCoordinate = displayDegrees + _t('units.arcminutes', {
90107               quantity: Math.floor(min).toLocaleString(locale)
90108             }) + _t('units.arcseconds', {
90109               quantity: Math.round(sec).toLocaleString(locale)
90110             });
90111           } else if (Math.floor(min) > 0) {
90112             displayCoordinate = displayDegrees + _t('units.arcminutes', {
90113               quantity: Math.round(min).toLocaleString(locale)
90114             });
90115           } else {
90116             displayCoordinate = _t('units.arcdegrees', {
90117               quantity: Math.round(Math.abs(deg)).toLocaleString(locale)
90118             });
90119           }
90120
90121           if (deg === 0) {
90122             return displayCoordinate;
90123           } else {
90124             return _t('units.coordinate', {
90125               coordinate: displayCoordinate,
90126               direction: _t('units.' + (deg > 0 ? pos : neg))
90127             });
90128           }
90129         }
90130         /**
90131          * Returns given coordinate pair in degree-minute-second format.
90132          *
90133          * @param {Array<Number>} coord longitude and latitude
90134          */
90135
90136
90137         function dmsCoordinatePair(coord) {
90138           return _t('units.coordinate_pair', {
90139             latitude: displayCoordinate(clamp(coord[1], -90, 90), 'north', 'south'),
90140             longitude: displayCoordinate(wrap(coord[0], -180, 180), 'east', 'west')
90141           });
90142         }
90143         /**
90144          * Returns the given coordinate pair in decimal format.
90145          * note: unlocalized to avoid comma ambiguity - see #4765
90146          *
90147          * @param {Array<Number>} coord longitude and latitude
90148          */
90149
90150         function decimalCoordinatePair(coord) {
90151           return _t('units.coordinate_pair', {
90152             latitude: clamp(coord[1], -90, 90).toFixed(OSM_PRECISION),
90153             longitude: wrap(coord[0], -180, 180).toFixed(OSM_PRECISION)
90154           });
90155         }
90156
90157         function uiPanelLocation(context) {
90158           var currLocation = '';
90159
90160           function redraw(selection) {
90161             selection.html('');
90162             var list = selection.append('ul'); // Mouse coordinates
90163
90164             var coord = context.map().mouseCoordinates();
90165
90166             if (coord.some(isNaN)) {
90167               coord = context.map().center();
90168             }
90169
90170             list.append('li').text(dmsCoordinatePair(coord)).append('li').text(decimalCoordinatePair(coord)); // Location Info
90171
90172             selection.append('div').attr('class', 'location-info').text(currLocation || ' ');
90173             debouncedGetLocation(selection, coord);
90174           }
90175
90176           var debouncedGetLocation = debounce(getLocation, 250);
90177
90178           function getLocation(selection, coord) {
90179             if (!services.geocoder) {
90180               currLocation = _t('info_panels.location.unknown_location');
90181               selection.selectAll('.location-info').text(currLocation);
90182             } else {
90183               services.geocoder.reverse(coord, function (err, result) {
90184                 currLocation = result ? result.display_name : _t('info_panels.location.unknown_location');
90185                 selection.selectAll('.location-info').text(currLocation);
90186               });
90187             }
90188           }
90189
90190           var panel = function panel(selection) {
90191             selection.call(redraw);
90192             context.surface().on(('PointerEvent' in window ? 'pointer' : 'mouse') + 'move.info-location', function () {
90193               selection.call(redraw);
90194             });
90195           };
90196
90197           panel.off = function () {
90198             context.surface().on('.info-location', null);
90199           };
90200
90201           panel.id = 'location';
90202           panel.label = _t.html('info_panels.location.title');
90203           panel.key = _t('info_panels.location.key');
90204           return panel;
90205         }
90206
90207         function uiPanelMeasurement(context) {
90208           function radiansToMeters(r) {
90209             // using WGS84 authalic radius (6371007.1809 m)
90210             return r * 6371007.1809;
90211           }
90212
90213           function steradiansToSqmeters(r) {
90214             // http://gis.stackexchange.com/a/124857/40446
90215             return r / (4 * Math.PI) * 510065621724000;
90216           }
90217
90218           function toLineString(feature) {
90219             if (feature.type === 'LineString') return feature;
90220             var result = {
90221               type: 'LineString',
90222               coordinates: []
90223             };
90224
90225             if (feature.type === 'Polygon') {
90226               result.coordinates = feature.coordinates[0];
90227             } else if (feature.type === 'MultiPolygon') {
90228               result.coordinates = feature.coordinates[0][0];
90229             }
90230
90231             return result;
90232           }
90233
90234           var _isImperial = !_mainLocalizer.usesMetric();
90235
90236           function redraw(selection) {
90237             var graph = context.graph();
90238             var selectedNoteID = context.selectedNoteID();
90239             var osm = services.osm;
90240             var localeCode = _mainLocalizer.localeCode();
90241             var heading;
90242             var center, location, centroid;
90243             var closed, geometry;
90244             var totalNodeCount,
90245                 length = 0,
90246                 area = 0,
90247                 distance;
90248
90249             if (selectedNoteID && osm) {
90250               // selected 1 note
90251               var note = osm.getNote(selectedNoteID);
90252               heading = _t.html('note.note') + ' ' + selectedNoteID;
90253               location = note.loc;
90254               geometry = 'note';
90255             } else {
90256               // selected 1..n entities
90257               var selectedIDs = context.selectedIDs().filter(function (id) {
90258                 return context.hasEntity(id);
90259               });
90260               var selected = selectedIDs.map(function (id) {
90261                 return context.entity(id);
90262               });
90263               heading = selected.length === 1 ? selected[0].id : _t.html('info_panels.selected', {
90264                 n: selected.length
90265               });
90266
90267               if (selected.length) {
90268                 var extent = geoExtent();
90269
90270                 for (var i in selected) {
90271                   var entity = selected[i];
90272
90273                   extent._extend(entity.extent(graph));
90274
90275                   geometry = entity.geometry(graph);
90276
90277                   if (geometry === 'line' || geometry === 'area') {
90278                     closed = entity.type === 'relation' || entity.isClosed() && !entity.isDegenerate();
90279                     var feature = entity.asGeoJSON(graph);
90280                     length += radiansToMeters(d3_geoLength(toLineString(feature)));
90281                     centroid = d3_geoPath(context.projection).centroid(entity.asGeoJSON(graph));
90282                     centroid = centroid && context.projection.invert(centroid);
90283
90284                     if (!centroid || !isFinite(centroid[0]) || !isFinite(centroid[1])) {
90285                       centroid = entity.extent(graph).center();
90286                     }
90287
90288                     if (closed) {
90289                       area += steradiansToSqmeters(entity.area(graph));
90290                     }
90291                   }
90292                 }
90293
90294                 if (selected.length > 1) {
90295                   geometry = null;
90296                   closed = null;
90297                   centroid = null;
90298                 }
90299
90300                 if (selected.length === 2 && selected[0].type === 'node' && selected[1].type === 'node') {
90301                   distance = geoSphericalDistance(selected[0].loc, selected[1].loc);
90302                 }
90303
90304                 if (selected.length === 1 && selected[0].type === 'node') {
90305                   location = selected[0].loc;
90306                 } else {
90307                   totalNodeCount = utilGetAllNodes(selectedIDs, context.graph()).length;
90308                 }
90309
90310                 if (!location && !centroid) {
90311                   center = extent.center();
90312                 }
90313               }
90314             }
90315
90316             selection.html('');
90317
90318             if (heading) {
90319               selection.append('h4').attr('class', 'measurement-heading').html(heading);
90320             }
90321
90322             var list = selection.append('ul');
90323             var coordItem;
90324
90325             if (geometry) {
90326               list.append('li').call(_t.append('info_panels.measurement.geometry', {
90327                 suffix: ':'
90328               })).append('span').html(closed ? _t.html('info_panels.measurement.closed_' + geometry) : _t.html('geometry.' + geometry));
90329             }
90330
90331             if (totalNodeCount) {
90332               list.append('li').call(_t.append('info_panels.measurement.node_count', {
90333                 suffix: ':'
90334               })).append('span').text(totalNodeCount.toLocaleString(localeCode));
90335             }
90336
90337             if (area) {
90338               list.append('li').call(_t.append('info_panels.measurement.area', {
90339                 suffix: ':'
90340               })).append('span').text(displayArea(area, _isImperial));
90341             }
90342
90343             if (length) {
90344               list.append('li').call(_t.append('info_panels.measurement.' + (closed ? 'perimeter' : 'length'), {
90345                 suffix: ':'
90346               })).append('span').text(displayLength(length, _isImperial));
90347             }
90348
90349             if (typeof distance === 'number') {
90350               list.append('li').call(_t.append('info_panels.measurement.distance', {
90351                 suffix: ':'
90352               })).append('span').text(displayLength(distance, _isImperial));
90353             }
90354
90355             if (location) {
90356               coordItem = list.append('li').call(_t.append('info_panels.measurement.location', {
90357                 suffix: ':'
90358               }));
90359               coordItem.append('span').text(dmsCoordinatePair(location));
90360               coordItem.append('span').text(decimalCoordinatePair(location));
90361             }
90362
90363             if (centroid) {
90364               coordItem = list.append('li').call(_t.append('info_panels.measurement.centroid', {
90365                 suffix: ':'
90366               }));
90367               coordItem.append('span').text(dmsCoordinatePair(centroid));
90368               coordItem.append('span').text(decimalCoordinatePair(centroid));
90369             }
90370
90371             if (center) {
90372               coordItem = list.append('li').call(_t.append('info_panels.measurement.center', {
90373                 suffix: ':'
90374               }));
90375               coordItem.append('span').text(dmsCoordinatePair(center));
90376               coordItem.append('span').text(decimalCoordinatePair(center));
90377             }
90378
90379             if (length || area || typeof distance === 'number') {
90380               var toggle = _isImperial ? 'imperial' : 'metric';
90381               selection.append('a').call(_t.append('info_panels.measurement.' + toggle)).attr('href', '#').attr('class', 'button button-toggle-units').on('click', function (d3_event) {
90382                 d3_event.preventDefault();
90383                 _isImperial = !_isImperial;
90384                 selection.call(redraw);
90385               });
90386             }
90387           }
90388
90389           var panel = function panel(selection) {
90390             selection.call(redraw);
90391             context.map().on('drawn.info-measurement', function () {
90392               selection.call(redraw);
90393             });
90394             context.on('enter.info-measurement', function () {
90395               selection.call(redraw);
90396             });
90397           };
90398
90399           panel.off = function () {
90400             context.map().on('drawn.info-measurement', null);
90401             context.on('enter.info-measurement', null);
90402           };
90403
90404           panel.id = 'measurement';
90405           panel.label = _t.html('info_panels.measurement.title');
90406           panel.key = _t('info_panels.measurement.key');
90407           return panel;
90408         }
90409
90410         var uiInfoPanels = {
90411           background: uiPanelBackground,
90412           history: uiPanelHistory,
90413           location: uiPanelLocation,
90414           measurement: uiPanelMeasurement
90415         };
90416
90417         function uiInfo(context) {
90418           var ids = Object.keys(uiInfoPanels);
90419           var wasActive = ['measurement'];
90420           var panels = {};
90421           var active = {}; // create panels
90422
90423           ids.forEach(function (k) {
90424             if (!panels[k]) {
90425               panels[k] = uiInfoPanels[k](context);
90426               active[k] = false;
90427             }
90428           });
90429
90430           function info(selection) {
90431             function redraw() {
90432               var activeids = ids.filter(function (k) {
90433                 return active[k];
90434               }).sort();
90435               var containers = infoPanels.selectAll('.panel-container').data(activeids, function (k) {
90436                 return k;
90437               });
90438               containers.exit().style('opacity', 1).transition().duration(200).style('opacity', 0).on('end', function (d) {
90439                 select(this).call(panels[d].off).remove();
90440               });
90441               var enter = containers.enter().append('div').attr('class', function (d) {
90442                 return 'fillD2 panel-container panel-container-' + d;
90443               });
90444               enter.style('opacity', 0).transition().duration(200).style('opacity', 1);
90445               var title = enter.append('div').attr('class', 'panel-title fillD2');
90446               title.append('h3').html(function (d) {
90447                 return panels[d].label;
90448               });
90449               title.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function (d3_event, d) {
90450                 d3_event.stopImmediatePropagation();
90451                 d3_event.preventDefault();
90452                 info.toggle(d);
90453               }).call(svgIcon('#iD-icon-close'));
90454               enter.append('div').attr('class', function (d) {
90455                 return 'panel-content panel-content-' + d;
90456               }); // redraw the panels
90457
90458               infoPanels.selectAll('.panel-content').each(function (d) {
90459                 select(this).call(panels[d]);
90460               });
90461             }
90462
90463             info.toggle = function (which) {
90464               var activeids = ids.filter(function (k) {
90465                 return active[k];
90466               });
90467
90468               if (which) {
90469                 // toggle one
90470                 active[which] = !active[which];
90471
90472                 if (activeids.length === 1 && activeids[0] === which) {
90473                   // none active anymore
90474                   wasActive = [which];
90475                 }
90476
90477                 context.container().select('.' + which + '-panel-toggle-item').classed('active', active[which]).select('input').property('checked', active[which]);
90478               } else {
90479                 // toggle all
90480                 if (activeids.length) {
90481                   wasActive = activeids;
90482                   activeids.forEach(function (k) {
90483                     active[k] = false;
90484                   });
90485                 } else {
90486                   wasActive.forEach(function (k) {
90487                     active[k] = true;
90488                   });
90489                 }
90490               }
90491
90492               redraw();
90493             };
90494
90495             var infoPanels = selection.selectAll('.info-panels').data([0]);
90496             infoPanels = infoPanels.enter().append('div').attr('class', 'info-panels').merge(infoPanels);
90497             redraw();
90498             context.keybinding().on(uiCmd('⌘' + _t('info_panels.key')), function (d3_event) {
90499               d3_event.stopImmediatePropagation();
90500               d3_event.preventDefault();
90501               info.toggle();
90502             });
90503             ids.forEach(function (k) {
90504               var key = _t('info_panels.' + k + '.key', {
90505                 "default": null
90506               });
90507               if (!key) return;
90508               context.keybinding().on(uiCmd('⌘⇧' + key), function (d3_event) {
90509                 d3_event.stopImmediatePropagation();
90510                 d3_event.preventDefault();
90511                 info.toggle(k);
90512               });
90513             });
90514           }
90515
90516           return info;
90517         }
90518
90519         function pointBox(loc, context) {
90520           var rect = context.surfaceRect();
90521           var point = context.curtainProjection(loc);
90522           return {
90523             left: point[0] + rect.left - 40,
90524             top: point[1] + rect.top - 60,
90525             width: 80,
90526             height: 90
90527           };
90528         }
90529         function pad(locOrBox, padding, context) {
90530           var box;
90531
90532           if (locOrBox instanceof Array) {
90533             var rect = context.surfaceRect();
90534             var point = context.curtainProjection(locOrBox);
90535             box = {
90536               left: point[0] + rect.left,
90537               top: point[1] + rect.top
90538             };
90539           } else {
90540             box = locOrBox;
90541           }
90542
90543           return {
90544             left: box.left - padding,
90545             top: box.top - padding,
90546             width: (box.width || 0) + 2 * padding,
90547             height: (box.width || 0) + 2 * padding
90548           };
90549         }
90550         function icon(name, svgklass, useklass) {
90551           return '<svg class="icon ' + (svgklass || '') + '">' + '<use xlink:href="' + name + '"' + (useklass ? ' class="' + useklass + '"' : '') + '></use></svg>';
90552         }
90553         var helpStringReplacements; // Returns the localized HTML element for `id` with a standardized set of icon, key, and
90554         // label replacements suitable for tutorials and documentation. Optionally supplemented
90555         // with custom `replacements`
90556
90557         function helpHtml(id, replacements) {
90558           // only load these the first time
90559           if (!helpStringReplacements) {
90560             helpStringReplacements = {
90561               // insert icons corresponding to various UI elements
90562               point_icon: icon('#iD-icon-point', 'inline'),
90563               line_icon: icon('#iD-icon-line', 'inline'),
90564               area_icon: icon('#iD-icon-area', 'inline'),
90565               note_icon: icon('#iD-icon-note', 'inline add-note'),
90566               plus: icon('#iD-icon-plus', 'inline'),
90567               minus: icon('#iD-icon-minus', 'inline'),
90568               layers_icon: icon('#iD-icon-layers', 'inline'),
90569               data_icon: icon('#iD-icon-data', 'inline'),
90570               inspect: icon('#iD-icon-inspect', 'inline'),
90571               help_icon: icon('#iD-icon-help', 'inline'),
90572               undo_icon: icon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-redo' : '#iD-icon-undo', 'inline'),
90573               redo_icon: icon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-undo' : '#iD-icon-redo', 'inline'),
90574               save_icon: icon('#iD-icon-save', 'inline'),
90575               // operation icons
90576               circularize_icon: icon('#iD-operation-circularize', 'inline operation'),
90577               continue_icon: icon('#iD-operation-continue', 'inline operation'),
90578               copy_icon: icon('#iD-operation-copy', 'inline operation'),
90579               delete_icon: icon('#iD-operation-delete', 'inline operation'),
90580               disconnect_icon: icon('#iD-operation-disconnect', 'inline operation'),
90581               downgrade_icon: icon('#iD-operation-downgrade', 'inline operation'),
90582               extract_icon: icon('#iD-operation-extract', 'inline operation'),
90583               merge_icon: icon('#iD-operation-merge', 'inline operation'),
90584               move_icon: icon('#iD-operation-move', 'inline operation'),
90585               orthogonalize_icon: icon('#iD-operation-orthogonalize', 'inline operation'),
90586               paste_icon: icon('#iD-operation-paste', 'inline operation'),
90587               reflect_long_icon: icon('#iD-operation-reflect-long', 'inline operation'),
90588               reflect_short_icon: icon('#iD-operation-reflect-short', 'inline operation'),
90589               reverse_icon: icon('#iD-operation-reverse', 'inline operation'),
90590               rotate_icon: icon('#iD-operation-rotate', 'inline operation'),
90591               split_icon: icon('#iD-operation-split', 'inline operation'),
90592               straighten_icon: icon('#iD-operation-straighten', 'inline operation'),
90593               // interaction icons
90594               leftclick: icon('#iD-walkthrough-mouse-left', 'inline operation'),
90595               rightclick: icon('#iD-walkthrough-mouse-right', 'inline operation'),
90596               mousewheel_icon: icon('#iD-walkthrough-mousewheel', 'inline operation'),
90597               tap_icon: icon('#iD-walkthrough-tap', 'inline operation'),
90598               doubletap_icon: icon('#iD-walkthrough-doubletap', 'inline operation'),
90599               longpress_icon: icon('#iD-walkthrough-longpress', 'inline operation'),
90600               touchdrag_icon: icon('#iD-walkthrough-touchdrag', 'inline operation'),
90601               pinch_icon: icon('#iD-walkthrough-pinch-apart', 'inline operation'),
90602               // insert keys; may be localized and platform-dependent
90603               shift: uiCmd.display('⇧'),
90604               alt: uiCmd.display('⌥'),
90605               "return": uiCmd.display('↵'),
90606               esc: _t.html('shortcuts.key.esc'),
90607               space: _t.html('shortcuts.key.space'),
90608               add_note_key: _t.html('modes.add_note.key'),
90609               help_key: _t.html('help.key'),
90610               shortcuts_key: _t.html('shortcuts.toggle.key'),
90611               // reference localized UI labels directly so that they'll always match
90612               save: _t.html('save.title'),
90613               undo: _t.html('undo.title'),
90614               redo: _t.html('redo.title'),
90615               upload: _t.html('commit.save'),
90616               point: _t.html('modes.add_point.title'),
90617               line: _t.html('modes.add_line.title'),
90618               area: _t.html('modes.add_area.title'),
90619               note: _t.html('modes.add_note.label'),
90620               circularize: _t.html('operations.circularize.title'),
90621               "continue": _t.html('operations.continue.title'),
90622               copy: _t.html('operations.copy.title'),
90623               "delete": _t.html('operations.delete.title'),
90624               disconnect: _t.html('operations.disconnect.title'),
90625               downgrade: _t.html('operations.downgrade.title'),
90626               extract: _t.html('operations.extract.title'),
90627               merge: _t.html('operations.merge.title'),
90628               move: _t.html('operations.move.title'),
90629               orthogonalize: _t.html('operations.orthogonalize.title'),
90630               paste: _t.html('operations.paste.title'),
90631               reflect_long: _t.html('operations.reflect.title.long'),
90632               reflect_short: _t.html('operations.reflect.title.short'),
90633               reverse: _t.html('operations.reverse.title'),
90634               rotate: _t.html('operations.rotate.title'),
90635               split: _t.html('operations.split.title'),
90636               straighten: _t.html('operations.straighten.title'),
90637               map_data: _t.html('map_data.title'),
90638               osm_notes: _t.html('map_data.layers.notes.title'),
90639               fields: _t.html('inspector.fields'),
90640               tags: _t.html('inspector.tags'),
90641               relations: _t.html('inspector.relations'),
90642               new_relation: _t.html('inspector.new_relation'),
90643               turn_restrictions: _t.html('_tagging.presets.fields.restrictions.label'),
90644               background_settings: _t.html('background.description'),
90645               imagery_offset: _t.html('background.fix_misalignment'),
90646               start_the_walkthrough: _t.html('splash.walkthrough'),
90647               help: _t.html('help.title'),
90648               ok: _t.html('intro.ok')
90649             };
90650
90651             for (var key in helpStringReplacements) {
90652               helpStringReplacements[key] = {
90653                 html: helpStringReplacements[key]
90654               };
90655             }
90656           }
90657
90658           var reps;
90659
90660           if (replacements) {
90661             reps = Object.assign(replacements, helpStringReplacements);
90662           } else {
90663             reps = helpStringReplacements;
90664           }
90665
90666           return _t.html(id, reps) // use keyboard key styling for shortcuts
90667           .replace(/\`(.*?)\`/g, '<kbd>$1</kbd>');
90668         }
90669
90670         function slugify(text) {
90671           return text.toString().toLowerCase().replace(/\s+/g, '-') // Replace spaces with -
90672           .replace(/[^\w\-]+/g, '') // Remove all non-word chars
90673           .replace(/\-\-+/g, '-') // Replace multiple - with single -
90674           .replace(/^-+/, '') // Trim - from start of text
90675           .replace(/-+$/, ''); // Trim - from end of text
90676         } // console warning for missing walkthrough names
90677
90678
90679         var missingStrings = {};
90680
90681         function checkKey(key, text) {
90682           if (_t(key, {
90683             "default": undefined
90684           }) === undefined) {
90685             if (missingStrings.hasOwnProperty(key)) return; // warn once
90686
90687             missingStrings[key] = text;
90688             var missing = key + ': ' + text;
90689             if (typeof console !== 'undefined') console.log(missing); // eslint-disable-line
90690           }
90691         }
90692
90693         function localize(obj) {
90694           var key; // Assign name if entity has one..
90695
90696           var name = obj.tags && obj.tags.name;
90697
90698           if (name) {
90699             key = 'intro.graph.name.' + slugify(name);
90700             obj.tags.name = _t(key, {
90701               "default": name
90702             });
90703             checkKey(key, name);
90704           } // Assign street name if entity has one..
90705
90706
90707           var street = obj.tags && obj.tags['addr:street'];
90708
90709           if (street) {
90710             key = 'intro.graph.name.' + slugify(street);
90711             obj.tags['addr:street'] = _t(key, {
90712               "default": street
90713             });
90714             checkKey(key, street); // Add address details common across walkthrough..
90715
90716             var addrTags = ['block_number', 'city', 'county', 'district', 'hamlet', 'neighbourhood', 'postcode', 'province', 'quarter', 'state', 'subdistrict', 'suburb'];
90717             addrTags.forEach(function (k) {
90718               var key = 'intro.graph.' + k;
90719               var tag = 'addr:' + k;
90720               var val = obj.tags && obj.tags[tag];
90721               var str = _t(key, {
90722                 "default": val
90723               });
90724
90725               if (str) {
90726                 if (str.match(/^<.*>$/) !== null) {
90727                   delete obj.tags[tag];
90728                 } else {
90729                   obj.tags[tag] = str;
90730                 }
90731               }
90732             });
90733           }
90734
90735           return obj;
90736         } // Used to detect squareness.. some duplicataion of code from actionOrthogonalize.
90737
90738         function isMostlySquare(points) {
90739           // note: uses 15 here instead of the 12 from actionOrthogonalize because
90740           // actionOrthogonalize can actually straighten some larger angles as it iterates
90741           var threshold = 15; // degrees within right or straight
90742
90743           var lowerBound = Math.cos((90 - threshold) * Math.PI / 180); // near right
90744
90745           var upperBound = Math.cos(threshold * Math.PI / 180); // near straight
90746
90747           for (var i = 0; i < points.length; i++) {
90748             var a = points[(i - 1 + points.length) % points.length];
90749             var origin = points[i];
90750             var b = points[(i + 1) % points.length];
90751             var dotp = geoVecNormalizedDot(a, b, origin);
90752             var mag = Math.abs(dotp);
90753
90754             if (mag > lowerBound && mag < upperBound) {
90755               return false;
90756             }
90757           }
90758
90759           return true;
90760         }
90761         function selectMenuItem(context, operation) {
90762           return context.container().select('.edit-menu .edit-menu-item-' + operation);
90763         }
90764         function transitionTime(point1, point2) {
90765           var distance = geoSphericalDistance(point1, point2);
90766
90767           if (distance === 0) {
90768             return 0;
90769           } else if (distance < 80) {
90770             return 500;
90771           } else {
90772             return 1000;
90773           }
90774         }
90775
90776         // hide class, which sets display=none, and a d3 transition for opacity.
90777         // this will cause blinking when called repeatedly, so check that the
90778         // value actually changes between calls.
90779
90780         function uiToggle(show, callback) {
90781           return function (selection) {
90782             selection.style('opacity', show ? 0 : 1).classed('hide', false).transition().style('opacity', show ? 1 : 0).on('end', function () {
90783               select(this).classed('hide', !show).style('opacity', null);
90784               if (callback) callback.apply(this);
90785             });
90786           };
90787         }
90788
90789         function uiCurtain(containerNode) {
90790           var surface = select(null),
90791               tooltip = select(null),
90792               darkness = select(null);
90793
90794           function curtain(selection) {
90795             surface = selection.append('svg').attr('class', 'curtain').style('top', 0).style('left', 0);
90796             darkness = surface.append('path').attr('x', 0).attr('y', 0).attr('class', 'curtain-darkness');
90797             select(window).on('resize.curtain', resize);
90798             tooltip = selection.append('div').attr('class', 'tooltip');
90799             tooltip.append('div').attr('class', 'popover-arrow');
90800             tooltip.append('div').attr('class', 'popover-inner');
90801             resize();
90802
90803             function resize() {
90804               surface.attr('width', containerNode.clientWidth).attr('height', containerNode.clientHeight);
90805               curtain.cut(darkness.datum());
90806             }
90807           }
90808           /**
90809            * Reveal cuts the curtain to highlight the given box,
90810            * and shows a tooltip with instructions next to the box.
90811            *
90812            * @param  {String|ClientRect} [box]   box used to cut the curtain
90813            * @param  {String}    [text]          text for a tooltip
90814            * @param  {Object}    [options]
90815            * @param  {string}    [options.tooltipClass]    optional class to add to the tooltip
90816            * @param  {integer}   [options.duration]        transition time in milliseconds
90817            * @param  {string}    [options.buttonText]      if set, create a button with this text label
90818            * @param  {function}  [options.buttonCallback]  if set, the callback for the button
90819            * @param  {function}  [options.padding]         extra margin in px to put around bbox
90820            * @param  {String|ClientRect} [options.tooltipBox]  box for tooltip position, if different from box for the curtain
90821            */
90822
90823
90824           curtain.reveal = function (box, html, options) {
90825             options = options || {};
90826
90827             if (typeof box === 'string') {
90828               box = select(box).node();
90829             }
90830
90831             if (box && box.getBoundingClientRect) {
90832               box = copyBox(box.getBoundingClientRect());
90833               var containerRect = containerNode.getBoundingClientRect();
90834               box.top -= containerRect.top;
90835               box.left -= containerRect.left;
90836             }
90837
90838             if (box && options.padding) {
90839               box.top -= options.padding;
90840               box.left -= options.padding;
90841               box.bottom += options.padding;
90842               box.right += options.padding;
90843               box.height += options.padding * 2;
90844               box.width += options.padding * 2;
90845             }
90846
90847             var tooltipBox;
90848
90849             if (options.tooltipBox) {
90850               tooltipBox = options.tooltipBox;
90851
90852               if (typeof tooltipBox === 'string') {
90853                 tooltipBox = select(tooltipBox).node();
90854               }
90855
90856               if (tooltipBox && tooltipBox.getBoundingClientRect) {
90857                 tooltipBox = copyBox(tooltipBox.getBoundingClientRect());
90858               }
90859             } else {
90860               tooltipBox = box;
90861             }
90862
90863             if (tooltipBox && html) {
90864               if (html.indexOf('**') !== -1) {
90865                 if (html.indexOf('<span') === 0) {
90866                   html = html.replace(/^(<span.*?>)(.+?)(\*\*)/, '$1<span>$2</span>$3');
90867                 } else {
90868                   html = html.replace(/^(.+?)(\*\*)/, '<span>$1</span>$2');
90869                 } // pseudo markdown bold text for the instruction section..
90870
90871
90872                 html = html.replace(/\*\*(.*?)\*\*/g, '<span class="instruction">$1</span>');
90873               }
90874
90875               html = html.replace(/\*(.*?)\*/g, '<em>$1</em>'); // emphasis
90876
90877               html = html.replace(/\{br\}/g, '<br/><br/>'); // linebreak
90878
90879               if (options.buttonText && options.buttonCallback) {
90880                 html += '<div class="button-section">' + '<button href="#" class="button action">' + options.buttonText + '</button></div>';
90881               }
90882
90883               var classes = 'curtain-tooltip popover tooltip arrowed in ' + (options.tooltipClass || '');
90884               tooltip.classed(classes, true).selectAll('.popover-inner').html(html);
90885
90886               if (options.buttonText && options.buttonCallback) {
90887                 var button = tooltip.selectAll('.button-section .button.action');
90888                 button.on('click', function (d3_event) {
90889                   d3_event.preventDefault();
90890                   options.buttonCallback();
90891                 });
90892               }
90893
90894               var tip = copyBox(tooltip.node().getBoundingClientRect()),
90895                   w = containerNode.clientWidth,
90896                   h = containerNode.clientHeight,
90897                   tooltipWidth = 200,
90898                   tooltipArrow = 5,
90899                   side,
90900                   pos; // hack: this will have bottom placement,
90901               // so need to reserve extra space for the tooltip illustration.
90902
90903               if (options.tooltipClass === 'intro-mouse') {
90904                 tip.height += 80;
90905               } // trim box dimensions to just the portion that fits in the container..
90906
90907
90908               if (tooltipBox.top + tooltipBox.height > h) {
90909                 tooltipBox.height -= tooltipBox.top + tooltipBox.height - h;
90910               }
90911
90912               if (tooltipBox.left + tooltipBox.width > w) {
90913                 tooltipBox.width -= tooltipBox.left + tooltipBox.width - w;
90914               } // determine tooltip placement..
90915
90916
90917               if (tooltipBox.top + tooltipBox.height < 100) {
90918                 // tooltip below box..
90919                 side = 'bottom';
90920                 pos = [tooltipBox.left + tooltipBox.width / 2 - tip.width / 2, tooltipBox.top + tooltipBox.height];
90921               } else if (tooltipBox.top > h - 140) {
90922                 // tooltip above box..
90923                 side = 'top';
90924                 pos = [tooltipBox.left + tooltipBox.width / 2 - tip.width / 2, tooltipBox.top - tip.height];
90925               } else {
90926                 // tooltip to the side of the tooltipBox..
90927                 var tipY = tooltipBox.top + tooltipBox.height / 2 - tip.height / 2;
90928
90929                 if (_mainLocalizer.textDirection() === 'rtl') {
90930                   if (tooltipBox.left - tooltipWidth - tooltipArrow < 70) {
90931                     side = 'right';
90932                     pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
90933                   } else {
90934                     side = 'left';
90935                     pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
90936                   }
90937                 } else {
90938                   if (tooltipBox.left + tooltipBox.width + tooltipArrow + tooltipWidth > w - 70) {
90939                     side = 'left';
90940                     pos = [tooltipBox.left - tooltipWidth - tooltipArrow, tipY];
90941                   } else {
90942                     side = 'right';
90943                     pos = [tooltipBox.left + tooltipBox.width + tooltipArrow, tipY];
90944                   }
90945                 }
90946               }
90947
90948               if (options.duration !== 0 || !tooltip.classed(side)) {
90949                 tooltip.call(uiToggle(true));
90950               }
90951
90952               tooltip.style('top', pos[1] + 'px').style('left', pos[0] + 'px').attr('class', classes + ' ' + side); // shift popover-inner if it is very close to the top or bottom edge
90953               // (doesn't affect the placement of the popover-arrow)
90954
90955               var shiftY = 0;
90956
90957               if (side === 'left' || side === 'right') {
90958                 if (pos[1] < 60) {
90959                   shiftY = 60 - pos[1];
90960                 } else if (pos[1] + tip.height > h - 100) {
90961                   shiftY = h - pos[1] - tip.height - 100;
90962                 }
90963               }
90964
90965               tooltip.selectAll('.popover-inner').style('top', shiftY + 'px');
90966             } else {
90967               tooltip.classed('in', false).call(uiToggle(false));
90968             }
90969
90970             curtain.cut(box, options.duration);
90971             return tooltip;
90972           };
90973
90974           curtain.cut = function (datum, duration) {
90975             darkness.datum(datum).interrupt();
90976             var selection;
90977
90978             if (duration === 0) {
90979               selection = darkness;
90980             } else {
90981               selection = darkness.transition().duration(duration || 600).ease(linear$1);
90982             }
90983
90984             selection.attr('d', function (d) {
90985               var containerWidth = containerNode.clientWidth;
90986               var containerHeight = containerNode.clientHeight;
90987               var string = 'M 0,0 L 0,' + containerHeight + ' L ' + containerWidth + ',' + containerHeight + 'L' + containerWidth + ',0 Z';
90988               if (!d) return string;
90989               return string + 'M' + d.left + ',' + d.top + 'L' + d.left + ',' + (d.top + d.height) + 'L' + (d.left + d.width) + ',' + (d.top + d.height) + 'L' + (d.left + d.width) + ',' + d.top + 'Z';
90990             });
90991           };
90992
90993           curtain.remove = function () {
90994             surface.remove();
90995             tooltip.remove();
90996             select(window).on('resize.curtain', null);
90997           }; // ClientRects are immutable, so copy them to an object,
90998           // in case we need to trim the height/width.
90999
91000
91001           function copyBox(src) {
91002             return {
91003               top: src.top,
91004               right: src.right,
91005               bottom: src.bottom,
91006               left: src.left,
91007               width: src.width,
91008               height: src.height
91009             };
91010           }
91011
91012           return curtain;
91013         }
91014
91015         function uiIntroWelcome(context, reveal) {
91016           var dispatch = dispatch$8('done');
91017           var chapter = {
91018             title: 'intro.welcome.title'
91019           };
91020
91021           function welcome() {
91022             context.map().centerZoom([-85.63591, 41.94285], 19);
91023             reveal('.intro-nav-wrap .chapter-welcome', helpHtml('intro.welcome.welcome'), {
91024               buttonText: _t.html('intro.ok'),
91025               buttonCallback: practice
91026             });
91027           }
91028
91029           function practice() {
91030             reveal('.intro-nav-wrap .chapter-welcome', helpHtml('intro.welcome.practice'), {
91031               buttonText: _t.html('intro.ok'),
91032               buttonCallback: words
91033             });
91034           }
91035
91036           function words() {
91037             reveal('.intro-nav-wrap .chapter-welcome', helpHtml('intro.welcome.words'), {
91038               buttonText: _t.html('intro.ok'),
91039               buttonCallback: chapters
91040             });
91041           }
91042
91043           function chapters() {
91044             dispatch.call('done');
91045             reveal('.intro-nav-wrap .chapter-navigation', helpHtml('intro.welcome.chapters', {
91046               next: _t('intro.navigation.title')
91047             }));
91048           }
91049
91050           chapter.enter = function () {
91051             welcome();
91052           };
91053
91054           chapter.exit = function () {
91055             context.container().select('.curtain-tooltip.intro-mouse').selectAll('.counter').remove();
91056           };
91057
91058           chapter.restart = function () {
91059             chapter.exit();
91060             chapter.enter();
91061           };
91062
91063           return utilRebind(chapter, dispatch, 'on');
91064         }
91065
91066         function uiIntroNavigation(context, reveal) {
91067           var dispatch = dispatch$8('done');
91068           var timeouts = [];
91069           var hallId = 'n2061';
91070           var townHall = [-85.63591, 41.94285];
91071           var springStreetId = 'w397';
91072           var springStreetEndId = 'n1834';
91073           var springStreet = [-85.63582, 41.94255];
91074           var onewayField = _mainPresetIndex.field('oneway');
91075           var maxspeedField = _mainPresetIndex.field('maxspeed');
91076           var chapter = {
91077             title: 'intro.navigation.title'
91078           };
91079
91080           function timeout(f, t) {
91081             timeouts.push(window.setTimeout(f, t));
91082           }
91083
91084           function eventCancel(d3_event) {
91085             d3_event.stopPropagation();
91086             d3_event.preventDefault();
91087           }
91088
91089           function isTownHallSelected() {
91090             var ids = context.selectedIDs();
91091             return ids.length === 1 && ids[0] === hallId;
91092           }
91093
91094           function dragMap() {
91095             context.enter(modeBrowse(context));
91096             context.history().reset('initial');
91097             var msec = transitionTime(townHall, context.map().center());
91098
91099             if (msec) {
91100               reveal(null, null, {
91101                 duration: 0
91102               });
91103             }
91104
91105             context.map().centerZoomEase(townHall, 19, msec);
91106             timeout(function () {
91107               var centerStart = context.map().center();
91108               var textId = context.lastPointerType() === 'mouse' ? 'drag' : 'drag_touch';
91109               var dragString = helpHtml('intro.navigation.map_info') + '{br}' + helpHtml('intro.navigation.' + textId);
91110               reveal('.surface', dragString);
91111               context.map().on('drawn.intro', function () {
91112                 reveal('.surface', dragString, {
91113                   duration: 0
91114                 });
91115               });
91116               context.map().on('move.intro', function () {
91117                 var centerNow = context.map().center();
91118
91119                 if (centerStart[0] !== centerNow[0] || centerStart[1] !== centerNow[1]) {
91120                   context.map().on('move.intro', null);
91121                   timeout(function () {
91122                     continueTo(zoomMap);
91123                   }, 3000);
91124                 }
91125               });
91126             }, msec + 100);
91127
91128             function continueTo(nextStep) {
91129               context.map().on('move.intro drawn.intro', null);
91130               nextStep();
91131             }
91132           }
91133
91134           function zoomMap() {
91135             var zoomStart = context.map().zoom();
91136             var textId = context.lastPointerType() === 'mouse' ? 'zoom' : 'zoom_touch';
91137             var zoomString = helpHtml('intro.navigation.' + textId);
91138             reveal('.surface', zoomString);
91139             context.map().on('drawn.intro', function () {
91140               reveal('.surface', zoomString, {
91141                 duration: 0
91142               });
91143             });
91144             context.map().on('move.intro', function () {
91145               if (context.map().zoom() !== zoomStart) {
91146                 context.map().on('move.intro', null);
91147                 timeout(function () {
91148                   continueTo(features);
91149                 }, 3000);
91150               }
91151             });
91152
91153             function continueTo(nextStep) {
91154               context.map().on('move.intro drawn.intro', null);
91155               nextStep();
91156             }
91157           }
91158
91159           function features() {
91160             var onClick = function onClick() {
91161               continueTo(pointsLinesAreas);
91162             };
91163
91164             reveal('.surface', helpHtml('intro.navigation.features'), {
91165               buttonText: _t.html('intro.ok'),
91166               buttonCallback: onClick
91167             });
91168             context.map().on('drawn.intro', function () {
91169               reveal('.surface', helpHtml('intro.navigation.features'), {
91170                 duration: 0,
91171                 buttonText: _t.html('intro.ok'),
91172                 buttonCallback: onClick
91173               });
91174             });
91175
91176             function continueTo(nextStep) {
91177               context.map().on('drawn.intro', null);
91178               nextStep();
91179             }
91180           }
91181
91182           function pointsLinesAreas() {
91183             var onClick = function onClick() {
91184               continueTo(nodesWays);
91185             };
91186
91187             reveal('.surface', helpHtml('intro.navigation.points_lines_areas'), {
91188               buttonText: _t.html('intro.ok'),
91189               buttonCallback: onClick
91190             });
91191             context.map().on('drawn.intro', function () {
91192               reveal('.surface', helpHtml('intro.navigation.points_lines_areas'), {
91193                 duration: 0,
91194                 buttonText: _t.html('intro.ok'),
91195                 buttonCallback: onClick
91196               });
91197             });
91198
91199             function continueTo(nextStep) {
91200               context.map().on('drawn.intro', null);
91201               nextStep();
91202             }
91203           }
91204
91205           function nodesWays() {
91206             var onClick = function onClick() {
91207               continueTo(clickTownHall);
91208             };
91209
91210             reveal('.surface', helpHtml('intro.navigation.nodes_ways'), {
91211               buttonText: _t.html('intro.ok'),
91212               buttonCallback: onClick
91213             });
91214             context.map().on('drawn.intro', function () {
91215               reveal('.surface', helpHtml('intro.navigation.nodes_ways'), {
91216                 duration: 0,
91217                 buttonText: _t.html('intro.ok'),
91218                 buttonCallback: onClick
91219               });
91220             });
91221
91222             function continueTo(nextStep) {
91223               context.map().on('drawn.intro', null);
91224               nextStep();
91225             }
91226           }
91227
91228           function clickTownHall() {
91229             context.enter(modeBrowse(context));
91230             context.history().reset('initial');
91231             var entity = context.hasEntity(hallId);
91232             if (!entity) return;
91233             reveal(null, null, {
91234               duration: 0
91235             });
91236             context.map().centerZoomEase(entity.loc, 19, 500);
91237             timeout(function () {
91238               var entity = context.hasEntity(hallId);
91239               if (!entity) return;
91240               var box = pointBox(entity.loc, context);
91241               var textId = context.lastPointerType() === 'mouse' ? 'click_townhall' : 'tap_townhall';
91242               reveal(box, helpHtml('intro.navigation.' + textId));
91243               context.map().on('move.intro drawn.intro', function () {
91244                 var entity = context.hasEntity(hallId);
91245                 if (!entity) return;
91246                 var box = pointBox(entity.loc, context);
91247                 reveal(box, helpHtml('intro.navigation.' + textId), {
91248                   duration: 0
91249                 });
91250               });
91251               context.on('enter.intro', function () {
91252                 if (isTownHallSelected()) continueTo(selectedTownHall);
91253               });
91254             }, 550); // after centerZoomEase
91255
91256             context.history().on('change.intro', function () {
91257               if (!context.hasEntity(hallId)) {
91258                 continueTo(clickTownHall);
91259               }
91260             });
91261
91262             function continueTo(nextStep) {
91263               context.on('enter.intro', null);
91264               context.map().on('move.intro drawn.intro', null);
91265               context.history().on('change.intro', null);
91266               nextStep();
91267             }
91268           }
91269
91270           function selectedTownHall() {
91271             if (!isTownHallSelected()) return clickTownHall();
91272             var entity = context.hasEntity(hallId);
91273             if (!entity) return clickTownHall();
91274             var box = pointBox(entity.loc, context);
91275
91276             var onClick = function onClick() {
91277               continueTo(editorTownHall);
91278             };
91279
91280             reveal(box, helpHtml('intro.navigation.selected_townhall'), {
91281               buttonText: _t.html('intro.ok'),
91282               buttonCallback: onClick
91283             });
91284             context.map().on('move.intro drawn.intro', function () {
91285               var entity = context.hasEntity(hallId);
91286               if (!entity) return;
91287               var box = pointBox(entity.loc, context);
91288               reveal(box, helpHtml('intro.navigation.selected_townhall'), {
91289                 duration: 0,
91290                 buttonText: _t.html('intro.ok'),
91291                 buttonCallback: onClick
91292               });
91293             });
91294             context.history().on('change.intro', function () {
91295               if (!context.hasEntity(hallId)) {
91296                 continueTo(clickTownHall);
91297               }
91298             });
91299
91300             function continueTo(nextStep) {
91301               context.map().on('move.intro drawn.intro', null);
91302               context.history().on('change.intro', null);
91303               nextStep();
91304             }
91305           }
91306
91307           function editorTownHall() {
91308             if (!isTownHallSelected()) return clickTownHall(); // disallow scrolling
91309
91310             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91311
91312             var onClick = function onClick() {
91313               continueTo(presetTownHall);
91314             };
91315
91316             reveal('.entity-editor-pane', helpHtml('intro.navigation.editor_townhall'), {
91317               buttonText: _t.html('intro.ok'),
91318               buttonCallback: onClick
91319             });
91320             context.on('exit.intro', function () {
91321               continueTo(clickTownHall);
91322             });
91323             context.history().on('change.intro', function () {
91324               if (!context.hasEntity(hallId)) {
91325                 continueTo(clickTownHall);
91326               }
91327             });
91328
91329             function continueTo(nextStep) {
91330               context.on('exit.intro', null);
91331               context.history().on('change.intro', null);
91332               context.container().select('.inspector-wrap').on('wheel.intro', null);
91333               nextStep();
91334             }
91335           }
91336
91337           function presetTownHall() {
91338             if (!isTownHallSelected()) return clickTownHall(); // reset pane, in case user happened to change it..
91339
91340             context.container().select('.inspector-wrap .panewrap').style('right', '0%'); // disallow scrolling
91341
91342             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel); // preset match, in case the user happened to change it.
91343
91344             var entity = context.entity(context.selectedIDs()[0]);
91345             var preset = _mainPresetIndex.match(entity, context.graph());
91346
91347             var onClick = function onClick() {
91348               continueTo(fieldsTownHall);
91349             };
91350
91351             reveal('.entity-editor-pane .section-feature-type', helpHtml('intro.navigation.preset_townhall', {
91352               preset: preset.name()
91353             }), {
91354               buttonText: _t.html('intro.ok'),
91355               buttonCallback: onClick
91356             });
91357             context.on('exit.intro', function () {
91358               continueTo(clickTownHall);
91359             });
91360             context.history().on('change.intro', function () {
91361               if (!context.hasEntity(hallId)) {
91362                 continueTo(clickTownHall);
91363               }
91364             });
91365
91366             function continueTo(nextStep) {
91367               context.on('exit.intro', null);
91368               context.history().on('change.intro', null);
91369               context.container().select('.inspector-wrap').on('wheel.intro', null);
91370               nextStep();
91371             }
91372           }
91373
91374           function fieldsTownHall() {
91375             if (!isTownHallSelected()) return clickTownHall(); // reset pane, in case user happened to change it..
91376
91377             context.container().select('.inspector-wrap .panewrap').style('right', '0%'); // disallow scrolling
91378
91379             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91380
91381             var onClick = function onClick() {
91382               continueTo(closeTownHall);
91383             };
91384
91385             reveal('.entity-editor-pane .section-preset-fields', helpHtml('intro.navigation.fields_townhall'), {
91386               buttonText: _t.html('intro.ok'),
91387               buttonCallback: onClick
91388             });
91389             context.on('exit.intro', function () {
91390               continueTo(clickTownHall);
91391             });
91392             context.history().on('change.intro', function () {
91393               if (!context.hasEntity(hallId)) {
91394                 continueTo(clickTownHall);
91395               }
91396             });
91397
91398             function continueTo(nextStep) {
91399               context.on('exit.intro', null);
91400               context.history().on('change.intro', null);
91401               context.container().select('.inspector-wrap').on('wheel.intro', null);
91402               nextStep();
91403             }
91404           }
91405
91406           function closeTownHall() {
91407             if (!isTownHallSelected()) return clickTownHall();
91408             var selector = '.entity-editor-pane button.close svg use';
91409             var href = select(selector).attr('href') || '#iD-icon-close';
91410             reveal('.entity-editor-pane', helpHtml('intro.navigation.close_townhall', {
91411               button: {
91412                 html: icon(href, 'inline')
91413               }
91414             }));
91415             context.on('exit.intro', function () {
91416               continueTo(searchStreet);
91417             });
91418             context.history().on('change.intro', function () {
91419               // update the close icon in the tooltip if the user edits something.
91420               var selector = '.entity-editor-pane button.close svg use';
91421               var href = select(selector).attr('href') || '#iD-icon-close';
91422               reveal('.entity-editor-pane', helpHtml('intro.navigation.close_townhall', {
91423                 button: {
91424                   html: icon(href, 'inline')
91425                 }
91426               }), {
91427                 duration: 0
91428               });
91429             });
91430
91431             function continueTo(nextStep) {
91432               context.on('exit.intro', null);
91433               context.history().on('change.intro', null);
91434               nextStep();
91435             }
91436           }
91437
91438           function searchStreet() {
91439             context.enter(modeBrowse(context));
91440             context.history().reset('initial'); // ensure spring street exists
91441
91442             var msec = transitionTime(springStreet, context.map().center());
91443
91444             if (msec) {
91445               reveal(null, null, {
91446                 duration: 0
91447               });
91448             }
91449
91450             context.map().centerZoomEase(springStreet, 19, msec); // ..and user can see it
91451
91452             timeout(function () {
91453               reveal('.search-header input', helpHtml('intro.navigation.search_street', {
91454                 name: _t('intro.graph.name.spring-street')
91455               }));
91456               context.container().select('.search-header input').on('keyup.intro', checkSearchResult);
91457             }, msec + 100);
91458           }
91459
91460           function checkSearchResult() {
91461             var first = context.container().select('.feature-list-item:nth-child(0n+2)'); // skip "No Results" item
91462
91463             var firstName = first.select('.entity-name');
91464             var name = _t('intro.graph.name.spring-street');
91465
91466             if (!firstName.empty() && firstName.html() === name) {
91467               reveal(first.node(), helpHtml('intro.navigation.choose_street', {
91468                 name: name
91469               }), {
91470                 duration: 300
91471               });
91472               context.on('exit.intro', function () {
91473                 continueTo(selectedStreet);
91474               });
91475               context.container().select('.search-header input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
91476             }
91477
91478             function continueTo(nextStep) {
91479               context.on('exit.intro', null);
91480               context.container().select('.search-header input').on('keydown.intro', null).on('keyup.intro', null);
91481               nextStep();
91482             }
91483           }
91484
91485           function selectedStreet() {
91486             if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
91487               return searchStreet();
91488             }
91489
91490             var onClick = function onClick() {
91491               continueTo(editorStreet);
91492             };
91493
91494             var entity = context.entity(springStreetEndId);
91495             var box = pointBox(entity.loc, context);
91496             box.height = 500;
91497             reveal(box, helpHtml('intro.navigation.selected_street', {
91498               name: _t('intro.graph.name.spring-street')
91499             }), {
91500               duration: 600,
91501               buttonText: _t.html('intro.ok'),
91502               buttonCallback: onClick
91503             });
91504             timeout(function () {
91505               context.map().on('move.intro drawn.intro', function () {
91506                 var entity = context.hasEntity(springStreetEndId);
91507                 if (!entity) return;
91508                 var box = pointBox(entity.loc, context);
91509                 box.height = 500;
91510                 reveal(box, helpHtml('intro.navigation.selected_street', {
91511                   name: _t('intro.graph.name.spring-street')
91512                 }), {
91513                   duration: 0,
91514                   buttonText: _t.html('intro.ok'),
91515                   buttonCallback: onClick
91516                 });
91517               });
91518             }, 600); // after reveal.
91519
91520             context.on('enter.intro', function (mode) {
91521               if (!context.hasEntity(springStreetId)) {
91522                 return continueTo(searchStreet);
91523               }
91524
91525               var ids = context.selectedIDs();
91526
91527               if (mode.id !== 'select' || !ids.length || ids[0] !== springStreetId) {
91528                 // keep Spring Street selected..
91529                 context.enter(modeSelect(context, [springStreetId]));
91530               }
91531             });
91532             context.history().on('change.intro', function () {
91533               if (!context.hasEntity(springStreetEndId) || !context.hasEntity(springStreetId)) {
91534                 timeout(function () {
91535                   continueTo(searchStreet);
91536                 }, 300); // after any transition (e.g. if user deleted intersection)
91537               }
91538             });
91539
91540             function continueTo(nextStep) {
91541               context.map().on('move.intro drawn.intro', null);
91542               context.on('enter.intro', null);
91543               context.history().on('change.intro', null);
91544               nextStep();
91545             }
91546           }
91547
91548           function editorStreet() {
91549             var selector = '.entity-editor-pane button.close svg use';
91550             var href = select(selector).attr('href') || '#iD-icon-close';
91551             reveal('.entity-editor-pane', helpHtml('intro.navigation.street_different_fields') + '{br}' + helpHtml('intro.navigation.editor_street', {
91552               button: {
91553                 html: icon(href, 'inline')
91554               },
91555               field1: {
91556                 html: onewayField.label()
91557               },
91558               field2: {
91559                 html: maxspeedField.label()
91560               }
91561             }));
91562             context.on('exit.intro', function () {
91563               continueTo(play);
91564             });
91565             context.history().on('change.intro', function () {
91566               // update the close icon in the tooltip if the user edits something.
91567               var selector = '.entity-editor-pane button.close svg use';
91568               var href = select(selector).attr('href') || '#iD-icon-close';
91569               reveal('.entity-editor-pane', helpHtml('intro.navigation.street_different_fields') + '{br}' + helpHtml('intro.navigation.editor_street', {
91570                 button: {
91571                   html: icon(href, 'inline')
91572                 },
91573                 field1: {
91574                   html: onewayField.label()
91575                 },
91576                 field2: {
91577                   html: maxspeedField.label()
91578                 }
91579               }), {
91580                 duration: 0
91581               });
91582             });
91583
91584             function continueTo(nextStep) {
91585               context.on('exit.intro', null);
91586               context.history().on('change.intro', null);
91587               nextStep();
91588             }
91589           }
91590
91591           function play() {
91592             dispatch.call('done');
91593             reveal('.ideditor', helpHtml('intro.navigation.play', {
91594               next: _t('intro.points.title')
91595             }), {
91596               tooltipBox: '.intro-nav-wrap .chapter-point',
91597               buttonText: _t.html('intro.ok'),
91598               buttonCallback: function buttonCallback() {
91599                 reveal('.ideditor');
91600               }
91601             });
91602           }
91603
91604           chapter.enter = function () {
91605             dragMap();
91606           };
91607
91608           chapter.exit = function () {
91609             timeouts.forEach(window.clearTimeout);
91610             context.on('enter.intro exit.intro', null);
91611             context.map().on('move.intro drawn.intro', null);
91612             context.history().on('change.intro', null);
91613             context.container().select('.inspector-wrap').on('wheel.intro', null);
91614             context.container().select('.search-header input').on('keydown.intro keyup.intro', null);
91615           };
91616
91617           chapter.restart = function () {
91618             chapter.exit();
91619             chapter.enter();
91620           };
91621
91622           return utilRebind(chapter, dispatch, 'on');
91623         }
91624
91625         function uiIntroPoint(context, reveal) {
91626           var dispatch = dispatch$8('done');
91627           var timeouts = [];
91628           var intersection = [-85.63279, 41.94394];
91629           var building = [-85.632422, 41.944045];
91630           var cafePreset = _mainPresetIndex.item('amenity/cafe');
91631           var _pointID = null;
91632           var chapter = {
91633             title: 'intro.points.title'
91634           };
91635
91636           function timeout(f, t) {
91637             timeouts.push(window.setTimeout(f, t));
91638           }
91639
91640           function eventCancel(d3_event) {
91641             d3_event.stopPropagation();
91642             d3_event.preventDefault();
91643           }
91644
91645           function addPoint() {
91646             context.enter(modeBrowse(context));
91647             context.history().reset('initial');
91648             var msec = transitionTime(intersection, context.map().center());
91649
91650             if (msec) {
91651               reveal(null, null, {
91652                 duration: 0
91653               });
91654             }
91655
91656             context.map().centerZoomEase(intersection, 19, msec);
91657             timeout(function () {
91658               var tooltip = reveal('button.add-point', helpHtml('intro.points.points_info') + '{br}' + helpHtml('intro.points.add_point'));
91659               _pointID = null;
91660               tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-points');
91661               context.on('enter.intro', function (mode) {
91662                 if (mode.id !== 'add-point') return;
91663                 continueTo(placePoint);
91664               });
91665             }, msec + 100);
91666
91667             function continueTo(nextStep) {
91668               context.on('enter.intro', null);
91669               nextStep();
91670             }
91671           }
91672
91673           function placePoint() {
91674             if (context.mode().id !== 'add-point') {
91675               return chapter.restart();
91676             }
91677
91678             var pointBox = pad(building, 150, context);
91679             var textId = context.lastPointerType() === 'mouse' ? 'place_point' : 'place_point_touch';
91680             reveal(pointBox, helpHtml('intro.points.' + textId));
91681             context.map().on('move.intro drawn.intro', function () {
91682               pointBox = pad(building, 150, context);
91683               reveal(pointBox, helpHtml('intro.points.' + textId), {
91684                 duration: 0
91685               });
91686             });
91687             context.on('enter.intro', function (mode) {
91688               if (mode.id !== 'select') return chapter.restart();
91689               _pointID = context.mode().selectedIDs()[0];
91690               continueTo(searchPreset);
91691             });
91692
91693             function continueTo(nextStep) {
91694               context.map().on('move.intro drawn.intro', null);
91695               context.on('enter.intro', null);
91696               nextStep();
91697             }
91698           }
91699
91700           function searchPreset() {
91701             if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91702               return addPoint();
91703             } // disallow scrolling
91704
91705
91706             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91707             context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
91708             reveal('.preset-search-input', helpHtml('intro.points.search_cafe', {
91709               preset: cafePreset.name()
91710             }));
91711             context.on('enter.intro', function (mode) {
91712               if (!_pointID || !context.hasEntity(_pointID)) {
91713                 return continueTo(addPoint);
91714               }
91715
91716               var ids = context.selectedIDs();
91717
91718               if (mode.id !== 'select' || !ids.length || ids[0] !== _pointID) {
91719                 // keep the user's point selected..
91720                 context.enter(modeSelect(context, [_pointID])); // disallow scrolling
91721
91722                 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
91723                 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
91724                 reveal('.preset-search-input', helpHtml('intro.points.search_cafe', {
91725                   preset: cafePreset.name()
91726                 }));
91727                 context.history().on('change.intro', null);
91728               }
91729             });
91730
91731             function checkPresetSearch() {
91732               var first = context.container().select('.preset-list-item:first-child');
91733
91734               if (first.classed('preset-amenity-cafe')) {
91735                 context.container().select('.preset-search-input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
91736                 reveal(first.select('.preset-list-button').node(), helpHtml('intro.points.choose_cafe', {
91737                   preset: cafePreset.name()
91738                 }), {
91739                   duration: 300
91740                 });
91741                 context.history().on('change.intro', function () {
91742                   continueTo(aboutFeatureEditor);
91743                 });
91744               }
91745             }
91746
91747             function continueTo(nextStep) {
91748               context.on('enter.intro', null);
91749               context.history().on('change.intro', null);
91750               context.container().select('.inspector-wrap').on('wheel.intro', null);
91751               context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
91752               nextStep();
91753             }
91754           }
91755
91756           function aboutFeatureEditor() {
91757             if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91758               return addPoint();
91759             }
91760
91761             timeout(function () {
91762               reveal('.entity-editor-pane', helpHtml('intro.points.feature_editor'), {
91763                 tooltipClass: 'intro-points-describe',
91764                 buttonText: _t.html('intro.ok'),
91765                 buttonCallback: function buttonCallback() {
91766                   continueTo(addName);
91767                 }
91768               });
91769             }, 400);
91770             context.on('exit.intro', function () {
91771               // if user leaves select mode here, just continue with the tutorial.
91772               continueTo(reselectPoint);
91773             });
91774
91775             function continueTo(nextStep) {
91776               context.on('exit.intro', null);
91777               nextStep();
91778             }
91779           }
91780
91781           function addName() {
91782             if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91783               return addPoint();
91784             } // reset pane, in case user happened to change it..
91785
91786
91787             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91788             var addNameString = helpHtml('intro.points.fields_info') + '{br}' + helpHtml('intro.points.add_name');
91789             timeout(function () {
91790               // It's possible for the user to add a name in a previous step..
91791               // If so, don't tell them to add the name in this step.
91792               // Give them an OK button instead.
91793               var entity = context.entity(_pointID);
91794
91795               if (entity.tags.name) {
91796                 var tooltip = reveal('.entity-editor-pane', addNameString, {
91797                   tooltipClass: 'intro-points-describe',
91798                   buttonText: _t.html('intro.ok'),
91799                   buttonCallback: function buttonCallback() {
91800                     continueTo(addCloseEditor);
91801                   }
91802                 });
91803                 tooltip.select('.instruction').style('display', 'none');
91804               } else {
91805                 reveal('.entity-editor-pane', addNameString, {
91806                   tooltipClass: 'intro-points-describe'
91807                 });
91808               }
91809             }, 400);
91810             context.history().on('change.intro', function () {
91811               continueTo(addCloseEditor);
91812             });
91813             context.on('exit.intro', function () {
91814               // if user leaves select mode here, just continue with the tutorial.
91815               continueTo(reselectPoint);
91816             });
91817
91818             function continueTo(nextStep) {
91819               context.on('exit.intro', null);
91820               context.history().on('change.intro', null);
91821               nextStep();
91822             }
91823           }
91824
91825           function addCloseEditor() {
91826             // reset pane, in case user happened to change it..
91827             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91828             var selector = '.entity-editor-pane button.close svg use';
91829             var href = select(selector).attr('href') || '#iD-icon-close';
91830             context.on('exit.intro', function () {
91831               continueTo(reselectPoint);
91832             });
91833             reveal('.entity-editor-pane', helpHtml('intro.points.add_close', {
91834               button: {
91835                 html: icon(href, 'inline')
91836               }
91837             }));
91838
91839             function continueTo(nextStep) {
91840               context.on('exit.intro', null);
91841               nextStep();
91842             }
91843           }
91844
91845           function reselectPoint() {
91846             if (!_pointID) return chapter.restart();
91847             var entity = context.hasEntity(_pointID);
91848             if (!entity) return chapter.restart(); // make sure it's still a cafe, in case user somehow changed it..
91849
91850             var oldPreset = _mainPresetIndex.match(entity, context.graph());
91851             context.replace(actionChangePreset(_pointID, oldPreset, cafePreset));
91852             context.enter(modeBrowse(context));
91853             var msec = transitionTime(entity.loc, context.map().center());
91854
91855             if (msec) {
91856               reveal(null, null, {
91857                 duration: 0
91858               });
91859             }
91860
91861             context.map().centerEase(entity.loc, msec);
91862             timeout(function () {
91863               var box = pointBox(entity.loc, context);
91864               reveal(box, helpHtml('intro.points.reselect'), {
91865                 duration: 600
91866               });
91867               timeout(function () {
91868                 context.map().on('move.intro drawn.intro', function () {
91869                   var entity = context.hasEntity(_pointID);
91870                   if (!entity) return chapter.restart();
91871                   var box = pointBox(entity.loc, context);
91872                   reveal(box, helpHtml('intro.points.reselect'), {
91873                     duration: 0
91874                   });
91875                 });
91876               }, 600); // after reveal..
91877
91878               context.on('enter.intro', function (mode) {
91879                 if (mode.id !== 'select') return;
91880                 continueTo(updatePoint);
91881               });
91882             }, msec + 100);
91883
91884             function continueTo(nextStep) {
91885               context.map().on('move.intro drawn.intro', null);
91886               context.on('enter.intro', null);
91887               nextStep();
91888             }
91889           }
91890
91891           function updatePoint() {
91892             if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91893               return continueTo(reselectPoint);
91894             } // reset pane, in case user happened to untag the point..
91895
91896
91897             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91898             context.on('exit.intro', function () {
91899               continueTo(reselectPoint);
91900             });
91901             context.history().on('change.intro', function () {
91902               continueTo(updateCloseEditor);
91903             });
91904             timeout(function () {
91905               reveal('.entity-editor-pane', helpHtml('intro.points.update'), {
91906                 tooltipClass: 'intro-points-describe'
91907               });
91908             }, 400);
91909
91910             function continueTo(nextStep) {
91911               context.on('exit.intro', null);
91912               context.history().on('change.intro', null);
91913               nextStep();
91914             }
91915           }
91916
91917           function updateCloseEditor() {
91918             if (context.mode().id !== 'select' || !_pointID || !context.hasEntity(_pointID)) {
91919               return continueTo(reselectPoint);
91920             } // reset pane, in case user happened to change it..
91921
91922
91923             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
91924             context.on('exit.intro', function () {
91925               continueTo(rightClickPoint);
91926             });
91927             timeout(function () {
91928               reveal('.entity-editor-pane', helpHtml('intro.points.update_close', {
91929                 button: {
91930                   html: icon('#iD-icon-close', 'inline')
91931                 }
91932               }));
91933             }, 500);
91934
91935             function continueTo(nextStep) {
91936               context.on('exit.intro', null);
91937               nextStep();
91938             }
91939           }
91940
91941           function rightClickPoint() {
91942             if (!_pointID) return chapter.restart();
91943             var entity = context.hasEntity(_pointID);
91944             if (!entity) return chapter.restart();
91945             context.enter(modeBrowse(context));
91946             var box = pointBox(entity.loc, context);
91947             var textId = context.lastPointerType() === 'mouse' ? 'rightclick' : 'edit_menu_touch';
91948             reveal(box, helpHtml('intro.points.' + textId), {
91949               duration: 600
91950             });
91951             timeout(function () {
91952               context.map().on('move.intro', function () {
91953                 var entity = context.hasEntity(_pointID);
91954                 if (!entity) return chapter.restart();
91955                 var box = pointBox(entity.loc, context);
91956                 reveal(box, helpHtml('intro.points.' + textId), {
91957                   duration: 0
91958                 });
91959               });
91960             }, 600); // after reveal
91961
91962             context.on('enter.intro', function (mode) {
91963               if (mode.id !== 'select') return;
91964               var ids = context.selectedIDs();
91965               if (ids.length !== 1 || ids[0] !== _pointID) return;
91966               timeout(function () {
91967                 var node = selectMenuItem(context, 'delete').node();
91968                 if (!node) return;
91969                 continueTo(enterDelete);
91970               }, 50); // after menu visible
91971             });
91972
91973             function continueTo(nextStep) {
91974               context.on('enter.intro', null);
91975               context.map().on('move.intro', null);
91976               nextStep();
91977             }
91978           }
91979
91980           function enterDelete() {
91981             if (!_pointID) return chapter.restart();
91982             var entity = context.hasEntity(_pointID);
91983             if (!entity) return chapter.restart();
91984             var node = selectMenuItem(context, 'delete').node();
91985
91986             if (!node) {
91987               return continueTo(rightClickPoint);
91988             }
91989
91990             reveal('.edit-menu', helpHtml('intro.points.delete'), {
91991               padding: 50
91992             });
91993             timeout(function () {
91994               context.map().on('move.intro', function () {
91995                 reveal('.edit-menu', helpHtml('intro.points.delete'), {
91996                   duration: 0,
91997                   padding: 50
91998                 });
91999               });
92000             }, 300); // after menu visible
92001
92002             context.on('exit.intro', function () {
92003               if (!_pointID) return chapter.restart();
92004               var entity = context.hasEntity(_pointID);
92005               if (entity) return continueTo(rightClickPoint); // point still exists
92006             });
92007             context.history().on('change.intro', function (changed) {
92008               if (changed.deleted().length) {
92009                 continueTo(undo);
92010               }
92011             });
92012
92013             function continueTo(nextStep) {
92014               context.map().on('move.intro', null);
92015               context.history().on('change.intro', null);
92016               context.on('exit.intro', null);
92017               nextStep();
92018             }
92019           }
92020
92021           function undo() {
92022             context.history().on('change.intro', function () {
92023               continueTo(play);
92024             });
92025             reveal('.top-toolbar button.undo-button', helpHtml('intro.points.undo'));
92026
92027             function continueTo(nextStep) {
92028               context.history().on('change.intro', null);
92029               nextStep();
92030             }
92031           }
92032
92033           function play() {
92034             dispatch.call('done');
92035             reveal('.ideditor', helpHtml('intro.points.play', {
92036               next: _t('intro.areas.title')
92037             }), {
92038               tooltipBox: '.intro-nav-wrap .chapter-area',
92039               buttonText: _t.html('intro.ok'),
92040               buttonCallback: function buttonCallback() {
92041                 reveal('.ideditor');
92042               }
92043             });
92044           }
92045
92046           chapter.enter = function () {
92047             addPoint();
92048           };
92049
92050           chapter.exit = function () {
92051             timeouts.forEach(window.clearTimeout);
92052             context.on('enter.intro exit.intro', null);
92053             context.map().on('move.intro drawn.intro', null);
92054             context.history().on('change.intro', null);
92055             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92056             context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
92057           };
92058
92059           chapter.restart = function () {
92060             chapter.exit();
92061             chapter.enter();
92062           };
92063
92064           return utilRebind(chapter, dispatch, 'on');
92065         }
92066
92067         function uiIntroArea(context, reveal) {
92068           var dispatch = dispatch$8('done');
92069           var playground = [-85.63552, 41.94159];
92070           var playgroundPreset = _mainPresetIndex.item('leisure/playground');
92071           var nameField = _mainPresetIndex.field('name');
92072           var descriptionField = _mainPresetIndex.field('description');
92073           var timeouts = [];
92074
92075           var _areaID;
92076
92077           var chapter = {
92078             title: 'intro.areas.title'
92079           };
92080
92081           function timeout(f, t) {
92082             timeouts.push(window.setTimeout(f, t));
92083           }
92084
92085           function eventCancel(d3_event) {
92086             d3_event.stopPropagation();
92087             d3_event.preventDefault();
92088           }
92089
92090           function revealPlayground(center, text, options) {
92091             var padding = 180 * Math.pow(2, context.map().zoom() - 19.5);
92092             var box = pad(center, padding, context);
92093             reveal(box, text, options);
92094           }
92095
92096           function addArea() {
92097             context.enter(modeBrowse(context));
92098             context.history().reset('initial');
92099             _areaID = null;
92100             var msec = transitionTime(playground, context.map().center());
92101
92102             if (msec) {
92103               reveal(null, null, {
92104                 duration: 0
92105               });
92106             }
92107
92108             context.map().centerZoomEase(playground, 19, msec);
92109             timeout(function () {
92110               var tooltip = reveal('button.add-area', helpHtml('intro.areas.add_playground'));
92111               tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-areas');
92112               context.on('enter.intro', function (mode) {
92113                 if (mode.id !== 'add-area') return;
92114                 continueTo(startPlayground);
92115               });
92116             }, msec + 100);
92117
92118             function continueTo(nextStep) {
92119               context.on('enter.intro', null);
92120               nextStep();
92121             }
92122           }
92123
92124           function startPlayground() {
92125             if (context.mode().id !== 'add-area') {
92126               return chapter.restart();
92127             }
92128
92129             _areaID = null;
92130             context.map().zoomEase(19.5, 500);
92131             timeout(function () {
92132               var textId = context.lastPointerType() === 'mouse' ? 'starting_node_click' : 'starting_node_tap';
92133               var startDrawString = helpHtml('intro.areas.start_playground') + helpHtml('intro.areas.' + textId);
92134               revealPlayground(playground, startDrawString, {
92135                 duration: 250
92136               });
92137               timeout(function () {
92138                 context.map().on('move.intro drawn.intro', function () {
92139                   revealPlayground(playground, startDrawString, {
92140                     duration: 0
92141                   });
92142                 });
92143                 context.on('enter.intro', function (mode) {
92144                   if (mode.id !== 'draw-area') return chapter.restart();
92145                   continueTo(continuePlayground);
92146                 });
92147               }, 250); // after reveal
92148             }, 550); // after easing
92149
92150             function continueTo(nextStep) {
92151               context.map().on('move.intro drawn.intro', null);
92152               context.on('enter.intro', null);
92153               nextStep();
92154             }
92155           }
92156
92157           function continuePlayground() {
92158             if (context.mode().id !== 'draw-area') {
92159               return chapter.restart();
92160             }
92161
92162             _areaID = null;
92163             revealPlayground(playground, helpHtml('intro.areas.continue_playground'), {
92164               duration: 250
92165             });
92166             timeout(function () {
92167               context.map().on('move.intro drawn.intro', function () {
92168                 revealPlayground(playground, helpHtml('intro.areas.continue_playground'), {
92169                   duration: 0
92170                 });
92171               });
92172             }, 250); // after reveal
92173
92174             context.on('enter.intro', function (mode) {
92175               if (mode.id === 'draw-area') {
92176                 var entity = context.hasEntity(context.selectedIDs()[0]);
92177
92178                 if (entity && entity.nodes.length >= 6) {
92179                   return continueTo(finishPlayground);
92180                 } else {
92181                   return;
92182                 }
92183               } else if (mode.id === 'select') {
92184                 _areaID = context.selectedIDs()[0];
92185                 return continueTo(searchPresets);
92186               } else {
92187                 return chapter.restart();
92188               }
92189             });
92190
92191             function continueTo(nextStep) {
92192               context.map().on('move.intro drawn.intro', null);
92193               context.on('enter.intro', null);
92194               nextStep();
92195             }
92196           }
92197
92198           function finishPlayground() {
92199             if (context.mode().id !== 'draw-area') {
92200               return chapter.restart();
92201             }
92202
92203             _areaID = null;
92204             var finishString = helpHtml('intro.areas.finish_area_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.areas.finish_playground');
92205             revealPlayground(playground, finishString, {
92206               duration: 250
92207             });
92208             timeout(function () {
92209               context.map().on('move.intro drawn.intro', function () {
92210                 revealPlayground(playground, finishString, {
92211                   duration: 0
92212                 });
92213               });
92214             }, 250); // after reveal
92215
92216             context.on('enter.intro', function (mode) {
92217               if (mode.id === 'draw-area') {
92218                 return;
92219               } else if (mode.id === 'select') {
92220                 _areaID = context.selectedIDs()[0];
92221                 return continueTo(searchPresets);
92222               } else {
92223                 return chapter.restart();
92224               }
92225             });
92226
92227             function continueTo(nextStep) {
92228               context.map().on('move.intro drawn.intro', null);
92229               context.on('enter.intro', null);
92230               nextStep();
92231             }
92232           }
92233
92234           function searchPresets() {
92235             if (!_areaID || !context.hasEntity(_areaID)) {
92236               return addArea();
92237             }
92238
92239             var ids = context.selectedIDs();
92240
92241             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92242               context.enter(modeSelect(context, [_areaID]));
92243             } // disallow scrolling
92244
92245
92246             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92247             timeout(function () {
92248               // reset pane, in case user somehow happened to change it..
92249               context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
92250               context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
92251               reveal('.preset-search-input', helpHtml('intro.areas.search_playground', {
92252                 preset: playgroundPreset.name()
92253               }));
92254             }, 400); // after preset list pane visible..
92255
92256             context.on('enter.intro', function (mode) {
92257               if (!_areaID || !context.hasEntity(_areaID)) {
92258                 return continueTo(addArea);
92259               }
92260
92261               var ids = context.selectedIDs();
92262
92263               if (mode.id !== 'select' || !ids.length || ids[0] !== _areaID) {
92264                 // keep the user's area selected..
92265                 context.enter(modeSelect(context, [_areaID])); // reset pane, in case user somehow happened to change it..
92266
92267                 context.container().select('.inspector-wrap .panewrap').style('right', '-100%'); // disallow scrolling
92268
92269                 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92270                 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
92271                 reveal('.preset-search-input', helpHtml('intro.areas.search_playground', {
92272                   preset: playgroundPreset.name()
92273                 }));
92274                 context.history().on('change.intro', null);
92275               }
92276             });
92277
92278             function checkPresetSearch() {
92279               var first = context.container().select('.preset-list-item:first-child');
92280
92281               if (first.classed('preset-leisure-playground')) {
92282                 reveal(first.select('.preset-list-button').node(), helpHtml('intro.areas.choose_playground', {
92283                   preset: playgroundPreset.name()
92284                 }), {
92285                   duration: 300
92286                 });
92287                 context.container().select('.preset-search-input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
92288                 context.history().on('change.intro', function () {
92289                   continueTo(clickAddField);
92290                 });
92291               }
92292             }
92293
92294             function continueTo(nextStep) {
92295               context.container().select('.inspector-wrap').on('wheel.intro', null);
92296               context.on('enter.intro', null);
92297               context.history().on('change.intro', null);
92298               context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
92299               nextStep();
92300             }
92301           }
92302
92303           function clickAddField() {
92304             if (!_areaID || !context.hasEntity(_areaID)) {
92305               return addArea();
92306             }
92307
92308             var ids = context.selectedIDs();
92309
92310             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92311               return searchPresets();
92312             }
92313
92314             if (!context.container().select('.form-field-description').empty()) {
92315               return continueTo(describePlayground);
92316             } // disallow scrolling
92317
92318
92319             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92320             timeout(function () {
92321               // reset pane, in case user somehow happened to change it..
92322               context.container().select('.inspector-wrap .panewrap').style('right', '0%'); // It's possible for the user to add a description in a previous step..
92323               // If they did this already, just continue to next step.
92324
92325               var entity = context.entity(_areaID);
92326
92327               if (entity.tags.description) {
92328                 return continueTo(play);
92329               } // scroll "Add field" into view
92330
92331
92332               var box = context.container().select('.more-fields').node().getBoundingClientRect();
92333
92334               if (box.top > 300) {
92335                 var pane = context.container().select('.entity-editor-pane .inspector-body');
92336                 var start = pane.node().scrollTop;
92337                 var end = start + (box.top - 300);
92338                 pane.transition().duration(250).tween('scroll.inspector', function () {
92339                   var node = this;
92340                   var i = d3_interpolateNumber(start, end);
92341                   return function (t) {
92342                     node.scrollTop = i(t);
92343                   };
92344                 });
92345               }
92346
92347               timeout(function () {
92348                 reveal('.more-fields .combobox-input', helpHtml('intro.areas.add_field', {
92349                   name: {
92350                     html: nameField.label()
92351                   },
92352                   description: {
92353                     html: descriptionField.label()
92354                   }
92355                 }), {
92356                   duration: 300
92357                 });
92358                 context.container().select('.more-fields .combobox-input').on('click.intro', function () {
92359                   // Watch for the combobox to appear...
92360                   var watcher;
92361                   watcher = window.setInterval(function () {
92362                     if (!context.container().select('div.combobox').empty()) {
92363                       window.clearInterval(watcher);
92364                       continueTo(chooseDescriptionField);
92365                     }
92366                   }, 300);
92367                 });
92368               }, 300); // after "Add Field" visible
92369             }, 400); // after editor pane visible
92370
92371             context.on('exit.intro', function () {
92372               return continueTo(searchPresets);
92373             });
92374
92375             function continueTo(nextStep) {
92376               context.container().select('.inspector-wrap').on('wheel.intro', null);
92377               context.container().select('.more-fields .combobox-input').on('click.intro', null);
92378               context.on('exit.intro', null);
92379               nextStep();
92380             }
92381           }
92382
92383           function chooseDescriptionField() {
92384             if (!_areaID || !context.hasEntity(_areaID)) {
92385               return addArea();
92386             }
92387
92388             var ids = context.selectedIDs();
92389
92390             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92391               return searchPresets();
92392             }
92393
92394             if (!context.container().select('.form-field-description').empty()) {
92395               return continueTo(describePlayground);
92396             } // Make sure combobox is ready..
92397
92398
92399             if (context.container().select('div.combobox').empty()) {
92400               return continueTo(clickAddField);
92401             } // Watch for the combobox to go away..
92402
92403
92404             var watcher;
92405             watcher = window.setInterval(function () {
92406               if (context.container().select('div.combobox').empty()) {
92407                 window.clearInterval(watcher);
92408                 timeout(function () {
92409                   if (context.container().select('.form-field-description').empty()) {
92410                     continueTo(retryChooseDescription);
92411                   } else {
92412                     continueTo(describePlayground);
92413                   }
92414                 }, 300); // after description field added.
92415               }
92416             }, 300);
92417             reveal('div.combobox', helpHtml('intro.areas.choose_field', {
92418               field: {
92419                 html: descriptionField.label()
92420               }
92421             }), {
92422               duration: 300
92423             });
92424             context.on('exit.intro', function () {
92425               return continueTo(searchPresets);
92426             });
92427
92428             function continueTo(nextStep) {
92429               if (watcher) window.clearInterval(watcher);
92430               context.on('exit.intro', null);
92431               nextStep();
92432             }
92433           }
92434
92435           function describePlayground() {
92436             if (!_areaID || !context.hasEntity(_areaID)) {
92437               return addArea();
92438             }
92439
92440             var ids = context.selectedIDs();
92441
92442             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92443               return searchPresets();
92444             } // reset pane, in case user happened to change it..
92445
92446
92447             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
92448
92449             if (context.container().select('.form-field-description').empty()) {
92450               return continueTo(retryChooseDescription);
92451             }
92452
92453             context.on('exit.intro', function () {
92454               continueTo(play);
92455             });
92456             reveal('.entity-editor-pane', helpHtml('intro.areas.describe_playground', {
92457               button: {
92458                 html: icon('#iD-icon-close', 'inline')
92459               }
92460             }), {
92461               duration: 300
92462             });
92463
92464             function continueTo(nextStep) {
92465               context.on('exit.intro', null);
92466               nextStep();
92467             }
92468           }
92469
92470           function retryChooseDescription() {
92471             if (!_areaID || !context.hasEntity(_areaID)) {
92472               return addArea();
92473             }
92474
92475             var ids = context.selectedIDs();
92476
92477             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _areaID) {
92478               return searchPresets();
92479             } // reset pane, in case user happened to change it..
92480
92481
92482             context.container().select('.inspector-wrap .panewrap').style('right', '0%');
92483             reveal('.entity-editor-pane', helpHtml('intro.areas.retry_add_field', {
92484               field: {
92485                 html: descriptionField.label()
92486               }
92487             }), {
92488               buttonText: _t.html('intro.ok'),
92489               buttonCallback: function buttonCallback() {
92490                 continueTo(clickAddField);
92491               }
92492             });
92493             context.on('exit.intro', function () {
92494               return continueTo(searchPresets);
92495             });
92496
92497             function continueTo(nextStep) {
92498               context.on('exit.intro', null);
92499               nextStep();
92500             }
92501           }
92502
92503           function play() {
92504             dispatch.call('done');
92505             reveal('.ideditor', helpHtml('intro.areas.play', {
92506               next: _t('intro.lines.title')
92507             }), {
92508               tooltipBox: '.intro-nav-wrap .chapter-line',
92509               buttonText: _t.html('intro.ok'),
92510               buttonCallback: function buttonCallback() {
92511                 reveal('.ideditor');
92512               }
92513             });
92514           }
92515
92516           chapter.enter = function () {
92517             addArea();
92518           };
92519
92520           chapter.exit = function () {
92521             timeouts.forEach(window.clearTimeout);
92522             context.on('enter.intro exit.intro', null);
92523             context.map().on('move.intro drawn.intro', null);
92524             context.history().on('change.intro', null);
92525             context.container().select('.inspector-wrap').on('wheel.intro', null);
92526             context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
92527             context.container().select('.more-fields .combobox-input').on('click.intro', null);
92528           };
92529
92530           chapter.restart = function () {
92531             chapter.exit();
92532             chapter.enter();
92533           };
92534
92535           return utilRebind(chapter, dispatch, 'on');
92536         }
92537
92538         function uiIntroLine(context, reveal) {
92539           var dispatch = dispatch$8('done');
92540           var timeouts = [];
92541           var _tulipRoadID = null;
92542           var flowerRoadID = 'w646';
92543           var tulipRoadStart = [-85.6297754121684, 41.95805253325314];
92544           var tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204];
92545           var tulipRoadIntersection = [-85.62974496187628, 41.95742515554585];
92546           var roadCategory = _mainPresetIndex.item('category-road_minor');
92547           var residentialPreset = _mainPresetIndex.item('highway/residential');
92548           var woodRoadID = 'w525';
92549           var woodRoadEndID = 'n2862';
92550           var woodRoadAddNode = [-85.62390110349587, 41.95397111462291];
92551           var woodRoadDragEndpoint = [-85.623867390213, 41.95466987786487];
92552           var woodRoadDragMidpoint = [-85.62386254803509, 41.95430395953872];
92553           var washingtonStreetID = 'w522';
92554           var twelfthAvenueID = 'w1';
92555           var eleventhAvenueEndID = 'n3550';
92556           var twelfthAvenueEndID = 'n5';
92557           var _washingtonSegmentID = null;
92558           var eleventhAvenueEnd = context.entity(eleventhAvenueEndID).loc;
92559           var twelfthAvenueEnd = context.entity(twelfthAvenueEndID).loc;
92560           var deleteLinesLoc = [-85.6219395542764, 41.95228033922477];
92561           var twelfthAvenue = [-85.62219310052491, 41.952505413152956];
92562           var chapter = {
92563             title: 'intro.lines.title'
92564           };
92565
92566           function timeout(f, t) {
92567             timeouts.push(window.setTimeout(f, t));
92568           }
92569
92570           function eventCancel(d3_event) {
92571             d3_event.stopPropagation();
92572             d3_event.preventDefault();
92573           }
92574
92575           function addLine() {
92576             context.enter(modeBrowse(context));
92577             context.history().reset('initial');
92578             var msec = transitionTime(tulipRoadStart, context.map().center());
92579
92580             if (msec) {
92581               reveal(null, null, {
92582                 duration: 0
92583               });
92584             }
92585
92586             context.map().centerZoomEase(tulipRoadStart, 18.5, msec);
92587             timeout(function () {
92588               var tooltip = reveal('button.add-line', helpHtml('intro.lines.add_line'));
92589               tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-lines');
92590               context.on('enter.intro', function (mode) {
92591                 if (mode.id !== 'add-line') return;
92592                 continueTo(startLine);
92593               });
92594             }, msec + 100);
92595
92596             function continueTo(nextStep) {
92597               context.on('enter.intro', null);
92598               nextStep();
92599             }
92600           }
92601
92602           function startLine() {
92603             if (context.mode().id !== 'add-line') return chapter.restart();
92604             _tulipRoadID = null;
92605             var padding = 70 * Math.pow(2, context.map().zoom() - 18);
92606             var box = pad(tulipRoadStart, padding, context);
92607             box.height = box.height + 100;
92608             var textId = context.lastPointerType() === 'mouse' ? 'start_line' : 'start_line_tap';
92609             var startLineString = helpHtml('intro.lines.missing_road') + '{br}' + helpHtml('intro.lines.line_draw_info') + helpHtml('intro.lines.' + textId);
92610             reveal(box, startLineString);
92611             context.map().on('move.intro drawn.intro', function () {
92612               padding = 70 * Math.pow(2, context.map().zoom() - 18);
92613               box = pad(tulipRoadStart, padding, context);
92614               box.height = box.height + 100;
92615               reveal(box, startLineString, {
92616                 duration: 0
92617               });
92618             });
92619             context.on('enter.intro', function (mode) {
92620               if (mode.id !== 'draw-line') return chapter.restart();
92621               continueTo(drawLine);
92622             });
92623
92624             function continueTo(nextStep) {
92625               context.map().on('move.intro drawn.intro', null);
92626               context.on('enter.intro', null);
92627               nextStep();
92628             }
92629           }
92630
92631           function drawLine() {
92632             if (context.mode().id !== 'draw-line') return chapter.restart();
92633             _tulipRoadID = context.mode().selectedIDs()[0];
92634             context.map().centerEase(tulipRoadMidpoint, 500);
92635             timeout(function () {
92636               var padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
92637               var box = pad(tulipRoadMidpoint, padding, context);
92638               box.height = box.height * 2;
92639               reveal(box, helpHtml('intro.lines.intersect', {
92640                 name: _t('intro.graph.name.flower-street')
92641               }));
92642               context.map().on('move.intro drawn.intro', function () {
92643                 padding = 200 * Math.pow(2, context.map().zoom() - 18.5);
92644                 box = pad(tulipRoadMidpoint, padding, context);
92645                 box.height = box.height * 2;
92646                 reveal(box, helpHtml('intro.lines.intersect', {
92647                   name: _t('intro.graph.name.flower-street')
92648                 }), {
92649                   duration: 0
92650                 });
92651               });
92652             }, 550); // after easing..
92653
92654             context.history().on('change.intro', function () {
92655               if (isLineConnected()) {
92656                 continueTo(continueLine);
92657               }
92658             });
92659             context.on('enter.intro', function (mode) {
92660               if (mode.id === 'draw-line') {
92661                 return;
92662               } else if (mode.id === 'select') {
92663                 continueTo(retryIntersect);
92664                 return;
92665               } else {
92666                 return chapter.restart();
92667               }
92668             });
92669
92670             function continueTo(nextStep) {
92671               context.map().on('move.intro drawn.intro', null);
92672               context.history().on('change.intro', null);
92673               context.on('enter.intro', null);
92674               nextStep();
92675             }
92676           }
92677
92678           function isLineConnected() {
92679             var entity = _tulipRoadID && context.hasEntity(_tulipRoadID);
92680
92681             if (!entity) return false;
92682             var drawNodes = context.graph().childNodes(entity);
92683             return drawNodes.some(function (node) {
92684               return context.graph().parentWays(node).some(function (parent) {
92685                 return parent.id === flowerRoadID;
92686               });
92687             });
92688           }
92689
92690           function retryIntersect() {
92691             select(window).on('pointerdown.intro mousedown.intro', eventCancel, true);
92692             var box = pad(tulipRoadIntersection, 80, context);
92693             reveal(box, helpHtml('intro.lines.retry_intersect', {
92694               name: _t('intro.graph.name.flower-street')
92695             }));
92696             timeout(chapter.restart, 3000);
92697           }
92698
92699           function continueLine() {
92700             if (context.mode().id !== 'draw-line') return chapter.restart();
92701
92702             var entity = _tulipRoadID && context.hasEntity(_tulipRoadID);
92703
92704             if (!entity) return chapter.restart();
92705             context.map().centerEase(tulipRoadIntersection, 500);
92706             var continueLineText = helpHtml('intro.lines.continue_line') + '{br}' + helpHtml('intro.lines.finish_line_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.lines.finish_road');
92707             reveal('.surface', continueLineText);
92708             context.on('enter.intro', function (mode) {
92709               if (mode.id === 'draw-line') {
92710                 return;
92711               } else if (mode.id === 'select') {
92712                 return continueTo(chooseCategoryRoad);
92713               } else {
92714                 return chapter.restart();
92715               }
92716             });
92717
92718             function continueTo(nextStep) {
92719               context.on('enter.intro', null);
92720               nextStep();
92721             }
92722           }
92723
92724           function chooseCategoryRoad() {
92725             if (context.mode().id !== 'select') return chapter.restart();
92726             context.on('exit.intro', function () {
92727               return chapter.restart();
92728             });
92729             var button = context.container().select('.preset-category-road_minor .preset-list-button');
92730             if (button.empty()) return chapter.restart(); // disallow scrolling
92731
92732             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92733             timeout(function () {
92734               // reset pane, in case user somehow happened to change it..
92735               context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
92736               reveal(button.node(), helpHtml('intro.lines.choose_category_road', {
92737                 category: roadCategory.name()
92738               }));
92739               button.on('click.intro', function () {
92740                 continueTo(choosePresetResidential);
92741               });
92742             }, 400); // after editor pane visible
92743
92744             function continueTo(nextStep) {
92745               context.container().select('.inspector-wrap').on('wheel.intro', null);
92746               context.container().select('.preset-list-button').on('click.intro', null);
92747               context.on('exit.intro', null);
92748               nextStep();
92749             }
92750           }
92751
92752           function choosePresetResidential() {
92753             if (context.mode().id !== 'select') return chapter.restart();
92754             context.on('exit.intro', function () {
92755               return chapter.restart();
92756             });
92757             var subgrid = context.container().select('.preset-category-road_minor .subgrid');
92758             if (subgrid.empty()) return chapter.restart();
92759             subgrid.selectAll(':not(.preset-highway-residential) .preset-list-button').on('click.intro', function () {
92760               continueTo(retryPresetResidential);
92761             });
92762             subgrid.selectAll('.preset-highway-residential .preset-list-button').on('click.intro', function () {
92763               continueTo(nameRoad);
92764             });
92765             timeout(function () {
92766               reveal(subgrid.node(), helpHtml('intro.lines.choose_preset_residential', {
92767                 preset: residentialPreset.name()
92768               }), {
92769                 tooltipBox: '.preset-highway-residential .preset-list-button',
92770                 duration: 300
92771               });
92772             }, 300);
92773
92774             function continueTo(nextStep) {
92775               context.container().select('.preset-list-button').on('click.intro', null);
92776               context.on('exit.intro', null);
92777               nextStep();
92778             }
92779           } // selected wrong road type
92780
92781
92782           function retryPresetResidential() {
92783             if (context.mode().id !== 'select') return chapter.restart();
92784             context.on('exit.intro', function () {
92785               return chapter.restart();
92786             }); // disallow scrolling
92787
92788             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
92789             timeout(function () {
92790               var button = context.container().select('.entity-editor-pane .preset-list-button');
92791               reveal(button.node(), helpHtml('intro.lines.retry_preset_residential', {
92792                 preset: residentialPreset.name()
92793               }));
92794               button.on('click.intro', function () {
92795                 continueTo(chooseCategoryRoad);
92796               });
92797             }, 500);
92798
92799             function continueTo(nextStep) {
92800               context.container().select('.inspector-wrap').on('wheel.intro', null);
92801               context.container().select('.preset-list-button').on('click.intro', null);
92802               context.on('exit.intro', null);
92803               nextStep();
92804             }
92805           }
92806
92807           function nameRoad() {
92808             context.on('exit.intro', function () {
92809               continueTo(didNameRoad);
92810             });
92811             timeout(function () {
92812               reveal('.entity-editor-pane', helpHtml('intro.lines.name_road', {
92813                 button: {
92814                   html: icon('#iD-icon-close', 'inline')
92815                 }
92816               }), {
92817                 tooltipClass: 'intro-lines-name_road'
92818               });
92819             }, 500);
92820
92821             function continueTo(nextStep) {
92822               context.on('exit.intro', null);
92823               nextStep();
92824             }
92825           }
92826
92827           function didNameRoad() {
92828             context.history().checkpoint('doneAddLine');
92829             timeout(function () {
92830               reveal('.surface', helpHtml('intro.lines.did_name_road'), {
92831                 buttonText: _t.html('intro.ok'),
92832                 buttonCallback: function buttonCallback() {
92833                   continueTo(updateLine);
92834                 }
92835               });
92836             }, 500);
92837
92838             function continueTo(nextStep) {
92839               nextStep();
92840             }
92841           }
92842
92843           function updateLine() {
92844             context.history().reset('doneAddLine');
92845
92846             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92847               return chapter.restart();
92848             }
92849
92850             var msec = transitionTime(woodRoadDragMidpoint, context.map().center());
92851
92852             if (msec) {
92853               reveal(null, null, {
92854                 duration: 0
92855               });
92856             }
92857
92858             context.map().centerZoomEase(woodRoadDragMidpoint, 19, msec);
92859             timeout(function () {
92860               var padding = 250 * Math.pow(2, context.map().zoom() - 19);
92861               var box = pad(woodRoadDragMidpoint, padding, context);
92862
92863               var advance = function advance() {
92864                 continueTo(addNode);
92865               };
92866
92867               reveal(box, helpHtml('intro.lines.update_line'), {
92868                 buttonText: _t.html('intro.ok'),
92869                 buttonCallback: advance
92870               });
92871               context.map().on('move.intro drawn.intro', function () {
92872                 var padding = 250 * Math.pow(2, context.map().zoom() - 19);
92873                 var box = pad(woodRoadDragMidpoint, padding, context);
92874                 reveal(box, helpHtml('intro.lines.update_line'), {
92875                   duration: 0,
92876                   buttonText: _t.html('intro.ok'),
92877                   buttonCallback: advance
92878                 });
92879               });
92880             }, msec + 100);
92881
92882             function continueTo(nextStep) {
92883               context.map().on('move.intro drawn.intro', null);
92884               nextStep();
92885             }
92886           }
92887
92888           function addNode() {
92889             context.history().reset('doneAddLine');
92890
92891             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92892               return chapter.restart();
92893             }
92894
92895             var padding = 40 * Math.pow(2, context.map().zoom() - 19);
92896             var box = pad(woodRoadAddNode, padding, context);
92897             var addNodeString = helpHtml('intro.lines.add_node' + (context.lastPointerType() === 'mouse' ? '' : '_touch'));
92898             reveal(box, addNodeString);
92899             context.map().on('move.intro drawn.intro', function () {
92900               var padding = 40 * Math.pow(2, context.map().zoom() - 19);
92901               var box = pad(woodRoadAddNode, padding, context);
92902               reveal(box, addNodeString, {
92903                 duration: 0
92904               });
92905             });
92906             context.history().on('change.intro', function (changed) {
92907               if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92908                 return continueTo(updateLine);
92909               }
92910
92911               if (changed.created().length === 1) {
92912                 timeout(function () {
92913                   continueTo(startDragEndpoint);
92914                 }, 500);
92915               }
92916             });
92917             context.on('enter.intro', function (mode) {
92918               if (mode.id !== 'select') {
92919                 continueTo(updateLine);
92920               }
92921             });
92922
92923             function continueTo(nextStep) {
92924               context.map().on('move.intro drawn.intro', null);
92925               context.history().on('change.intro', null);
92926               context.on('enter.intro', null);
92927               nextStep();
92928             }
92929           }
92930
92931           function startDragEndpoint() {
92932             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92933               return continueTo(updateLine);
92934             }
92935
92936             var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92937             var box = pad(woodRoadDragEndpoint, padding, context);
92938             var startDragString = helpHtml('intro.lines.start_drag_endpoint' + (context.lastPointerType() === 'mouse' ? '' : '_touch')) + helpHtml('intro.lines.drag_to_intersection');
92939             reveal(box, startDragString);
92940             context.map().on('move.intro drawn.intro', function () {
92941               if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92942                 return continueTo(updateLine);
92943               }
92944
92945               var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92946               var box = pad(woodRoadDragEndpoint, padding, context);
92947               reveal(box, startDragString, {
92948                 duration: 0
92949               });
92950               var entity = context.entity(woodRoadEndID);
92951
92952               if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) <= 4) {
92953                 continueTo(finishDragEndpoint);
92954               }
92955             });
92956
92957             function continueTo(nextStep) {
92958               context.map().on('move.intro drawn.intro', null);
92959               nextStep();
92960             }
92961           }
92962
92963           function finishDragEndpoint() {
92964             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92965               return continueTo(updateLine);
92966             }
92967
92968             var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92969             var box = pad(woodRoadDragEndpoint, padding, context);
92970             var finishDragString = helpHtml('intro.lines.spot_looks_good') + helpHtml('intro.lines.finish_drag_endpoint' + (context.lastPointerType() === 'mouse' ? '' : '_touch'));
92971             reveal(box, finishDragString);
92972             context.map().on('move.intro drawn.intro', function () {
92973               if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
92974                 return continueTo(updateLine);
92975               }
92976
92977               var padding = 100 * Math.pow(2, context.map().zoom() - 19);
92978               var box = pad(woodRoadDragEndpoint, padding, context);
92979               reveal(box, finishDragString, {
92980                 duration: 0
92981               });
92982               var entity = context.entity(woodRoadEndID);
92983
92984               if (geoSphericalDistance(entity.loc, woodRoadDragEndpoint) > 4) {
92985                 continueTo(startDragEndpoint);
92986               }
92987             });
92988             context.on('enter.intro', function () {
92989               continueTo(startDragMidpoint);
92990             });
92991
92992             function continueTo(nextStep) {
92993               context.map().on('move.intro drawn.intro', null);
92994               context.on('enter.intro', null);
92995               nextStep();
92996             }
92997           }
92998
92999           function startDragMidpoint() {
93000             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
93001               return continueTo(updateLine);
93002             }
93003
93004             if (context.selectedIDs().indexOf(woodRoadID) === -1) {
93005               context.enter(modeSelect(context, [woodRoadID]));
93006             }
93007
93008             var padding = 80 * Math.pow(2, context.map().zoom() - 19);
93009             var box = pad(woodRoadDragMidpoint, padding, context);
93010             reveal(box, helpHtml('intro.lines.start_drag_midpoint'));
93011             context.map().on('move.intro drawn.intro', function () {
93012               if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
93013                 return continueTo(updateLine);
93014               }
93015
93016               var padding = 80 * Math.pow(2, context.map().zoom() - 19);
93017               var box = pad(woodRoadDragMidpoint, padding, context);
93018               reveal(box, helpHtml('intro.lines.start_drag_midpoint'), {
93019                 duration: 0
93020               });
93021             });
93022             context.history().on('change.intro', function (changed) {
93023               if (changed.created().length === 1) {
93024                 continueTo(continueDragMidpoint);
93025               }
93026             });
93027             context.on('enter.intro', function (mode) {
93028               if (mode.id !== 'select') {
93029                 // keep Wood Road selected so midpoint triangles are drawn..
93030                 context.enter(modeSelect(context, [woodRoadID]));
93031               }
93032             });
93033
93034             function continueTo(nextStep) {
93035               context.map().on('move.intro drawn.intro', null);
93036               context.history().on('change.intro', null);
93037               context.on('enter.intro', null);
93038               nextStep();
93039             }
93040           }
93041
93042           function continueDragMidpoint() {
93043             if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
93044               return continueTo(updateLine);
93045             }
93046
93047             var padding = 100 * Math.pow(2, context.map().zoom() - 19);
93048             var box = pad(woodRoadDragEndpoint, padding, context);
93049             box.height += 400;
93050
93051             var advance = function advance() {
93052               context.history().checkpoint('doneUpdateLine');
93053               continueTo(deleteLines);
93054             };
93055
93056             reveal(box, helpHtml('intro.lines.continue_drag_midpoint'), {
93057               buttonText: _t.html('intro.ok'),
93058               buttonCallback: advance
93059             });
93060             context.map().on('move.intro drawn.intro', function () {
93061               if (!context.hasEntity(woodRoadID) || !context.hasEntity(woodRoadEndID)) {
93062                 return continueTo(updateLine);
93063               }
93064
93065               var padding = 100 * Math.pow(2, context.map().zoom() - 19);
93066               var box = pad(woodRoadDragEndpoint, padding, context);
93067               box.height += 400;
93068               reveal(box, helpHtml('intro.lines.continue_drag_midpoint'), {
93069                 duration: 0,
93070                 buttonText: _t.html('intro.ok'),
93071                 buttonCallback: advance
93072               });
93073             });
93074
93075             function continueTo(nextStep) {
93076               context.map().on('move.intro drawn.intro', null);
93077               nextStep();
93078             }
93079           }
93080
93081           function deleteLines() {
93082             context.history().reset('doneUpdateLine');
93083             context.enter(modeBrowse(context));
93084
93085             if (!context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93086               return chapter.restart();
93087             }
93088
93089             var msec = transitionTime(deleteLinesLoc, context.map().center());
93090
93091             if (msec) {
93092               reveal(null, null, {
93093                 duration: 0
93094               });
93095             }
93096
93097             context.map().centerZoomEase(deleteLinesLoc, 18, msec);
93098             timeout(function () {
93099               var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93100               var box = pad(deleteLinesLoc, padding, context);
93101               box.top -= 200;
93102               box.height += 400;
93103
93104               var advance = function advance() {
93105                 continueTo(rightClickIntersection);
93106               };
93107
93108               reveal(box, helpHtml('intro.lines.delete_lines', {
93109                 street: _t('intro.graph.name.12th-avenue')
93110               }), {
93111                 buttonText: _t.html('intro.ok'),
93112                 buttonCallback: advance
93113               });
93114               context.map().on('move.intro drawn.intro', function () {
93115                 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93116                 var box = pad(deleteLinesLoc, padding, context);
93117                 box.top -= 200;
93118                 box.height += 400;
93119                 reveal(box, helpHtml('intro.lines.delete_lines', {
93120                   street: _t('intro.graph.name.12th-avenue')
93121                 }), {
93122                   duration: 0,
93123                   buttonText: _t.html('intro.ok'),
93124                   buttonCallback: advance
93125                 });
93126               });
93127               context.history().on('change.intro', function () {
93128                 timeout(function () {
93129                   continueTo(deleteLines);
93130                 }, 500); // after any transition (e.g. if user deleted intersection)
93131               });
93132             }, msec + 100);
93133
93134             function continueTo(nextStep) {
93135               context.map().on('move.intro drawn.intro', null);
93136               context.history().on('change.intro', null);
93137               nextStep();
93138             }
93139           }
93140
93141           function rightClickIntersection() {
93142             context.history().reset('doneUpdateLine');
93143             context.enter(modeBrowse(context));
93144             context.map().centerZoomEase(eleventhAvenueEnd, 18, 500);
93145             var rightClickString = helpHtml('intro.lines.split_street', {
93146               street1: _t('intro.graph.name.11th-avenue'),
93147               street2: _t('intro.graph.name.washington-street')
93148             }) + helpHtml('intro.lines.' + (context.lastPointerType() === 'mouse' ? 'rightclick_intersection' : 'edit_menu_intersection_touch'));
93149             timeout(function () {
93150               var padding = 60 * Math.pow(2, context.map().zoom() - 18);
93151               var box = pad(eleventhAvenueEnd, padding, context);
93152               reveal(box, rightClickString);
93153               context.map().on('move.intro drawn.intro', function () {
93154                 var padding = 60 * Math.pow(2, context.map().zoom() - 18);
93155                 var box = pad(eleventhAvenueEnd, padding, context);
93156                 reveal(box, rightClickString, {
93157                   duration: 0
93158                 });
93159               });
93160               context.on('enter.intro', function (mode) {
93161                 if (mode.id !== 'select') return;
93162                 var ids = context.selectedIDs();
93163                 if (ids.length !== 1 || ids[0] !== eleventhAvenueEndID) return;
93164                 timeout(function () {
93165                   var node = selectMenuItem(context, 'split').node();
93166                   if (!node) return;
93167                   continueTo(splitIntersection);
93168                 }, 50); // after menu visible
93169               });
93170               context.history().on('change.intro', function () {
93171                 timeout(function () {
93172                   continueTo(deleteLines);
93173                 }, 300); // after any transition (e.g. if user deleted intersection)
93174               });
93175             }, 600);
93176
93177             function continueTo(nextStep) {
93178               context.map().on('move.intro drawn.intro', null);
93179               context.on('enter.intro', null);
93180               context.history().on('change.intro', null);
93181               nextStep();
93182             }
93183           }
93184
93185           function splitIntersection() {
93186             if (!context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93187               return continueTo(deleteLines);
93188             }
93189
93190             var node = selectMenuItem(context, 'split').node();
93191
93192             if (!node) {
93193               return continueTo(rightClickIntersection);
93194             }
93195
93196             var wasChanged = false;
93197             _washingtonSegmentID = null;
93198             reveal('.edit-menu', helpHtml('intro.lines.split_intersection', {
93199               street: _t('intro.graph.name.washington-street')
93200             }), {
93201               padding: 50
93202             });
93203             context.map().on('move.intro drawn.intro', function () {
93204               var node = selectMenuItem(context, 'split').node();
93205
93206               if (!wasChanged && !node) {
93207                 return continueTo(rightClickIntersection);
93208               }
93209
93210               reveal('.edit-menu', helpHtml('intro.lines.split_intersection', {
93211                 street: _t('intro.graph.name.washington-street')
93212               }), {
93213                 duration: 0,
93214                 padding: 50
93215               });
93216             });
93217             context.history().on('change.intro', function (changed) {
93218               wasChanged = true;
93219               timeout(function () {
93220                 if (context.history().undoAnnotation() === _t('operations.split.annotation.line', {
93221                   n: 1
93222                 })) {
93223                   _washingtonSegmentID = changed.created()[0].id;
93224                   continueTo(didSplit);
93225                 } else {
93226                   _washingtonSegmentID = null;
93227                   continueTo(retrySplit);
93228                 }
93229               }, 300); // after any transition (e.g. if user deleted intersection)
93230             });
93231
93232             function continueTo(nextStep) {
93233               context.map().on('move.intro drawn.intro', null);
93234               context.history().on('change.intro', null);
93235               nextStep();
93236             }
93237           }
93238
93239           function retrySplit() {
93240             context.enter(modeBrowse(context));
93241             context.map().centerZoomEase(eleventhAvenueEnd, 18, 500);
93242
93243             var advance = function advance() {
93244               continueTo(rightClickIntersection);
93245             };
93246
93247             var padding = 60 * Math.pow(2, context.map().zoom() - 18);
93248             var box = pad(eleventhAvenueEnd, padding, context);
93249             reveal(box, helpHtml('intro.lines.retry_split'), {
93250               buttonText: _t.html('intro.ok'),
93251               buttonCallback: advance
93252             });
93253             context.map().on('move.intro drawn.intro', function () {
93254               var padding = 60 * Math.pow(2, context.map().zoom() - 18);
93255               var box = pad(eleventhAvenueEnd, padding, context);
93256               reveal(box, helpHtml('intro.lines.retry_split'), {
93257                 duration: 0,
93258                 buttonText: _t.html('intro.ok'),
93259                 buttonCallback: advance
93260               });
93261             });
93262
93263             function continueTo(nextStep) {
93264               context.map().on('move.intro drawn.intro', null);
93265               nextStep();
93266             }
93267           }
93268
93269           function didSplit() {
93270             if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93271               return continueTo(rightClickIntersection);
93272             }
93273
93274             var ids = context.selectedIDs();
93275             var string = 'intro.lines.did_split_' + (ids.length > 1 ? 'multi' : 'single');
93276             var street = _t('intro.graph.name.washington-street');
93277             var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93278             var box = pad(twelfthAvenue, padding, context);
93279             box.width = box.width / 2;
93280             reveal(box, helpHtml(string, {
93281               street1: street,
93282               street2: street
93283             }), {
93284               duration: 500
93285             });
93286             timeout(function () {
93287               context.map().centerZoomEase(twelfthAvenue, 18, 500);
93288               context.map().on('move.intro drawn.intro', function () {
93289                 var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93290                 var box = pad(twelfthAvenue, padding, context);
93291                 box.width = box.width / 2;
93292                 reveal(box, helpHtml(string, {
93293                   street1: street,
93294                   street2: street
93295                 }), {
93296                   duration: 0
93297                 });
93298               });
93299             }, 600); // after initial reveal and curtain cut
93300
93301             context.on('enter.intro', function () {
93302               var ids = context.selectedIDs();
93303
93304               if (ids.length === 1 && ids[0] === _washingtonSegmentID) {
93305                 continueTo(multiSelect);
93306               }
93307             });
93308             context.history().on('change.intro', function () {
93309               if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93310                 return continueTo(rightClickIntersection);
93311               }
93312             });
93313
93314             function continueTo(nextStep) {
93315               context.map().on('move.intro drawn.intro', null);
93316               context.on('enter.intro', null);
93317               context.history().on('change.intro', null);
93318               nextStep();
93319             }
93320           }
93321
93322           function multiSelect() {
93323             if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93324               return continueTo(rightClickIntersection);
93325             }
93326
93327             var ids = context.selectedIDs();
93328             var hasWashington = ids.indexOf(_washingtonSegmentID) !== -1;
93329             var hasTwelfth = ids.indexOf(twelfthAvenueID) !== -1;
93330
93331             if (hasWashington && hasTwelfth) {
93332               return continueTo(multiRightClick);
93333             } else if (!hasWashington && !hasTwelfth) {
93334               return continueTo(didSplit);
93335             }
93336
93337             context.map().centerZoomEase(twelfthAvenue, 18, 500);
93338             timeout(function () {
93339               var selected, other, padding, box;
93340
93341               if (hasWashington) {
93342                 selected = _t('intro.graph.name.washington-street');
93343                 other = _t('intro.graph.name.12th-avenue');
93344                 padding = 60 * Math.pow(2, context.map().zoom() - 18);
93345                 box = pad(twelfthAvenueEnd, padding, context);
93346                 box.width *= 3;
93347               } else {
93348                 selected = _t('intro.graph.name.12th-avenue');
93349                 other = _t('intro.graph.name.washington-street');
93350                 padding = 200 * Math.pow(2, context.map().zoom() - 18);
93351                 box = pad(twelfthAvenue, padding, context);
93352                 box.width /= 2;
93353               }
93354
93355               reveal(box, helpHtml('intro.lines.multi_select', {
93356                 selected: selected,
93357                 other1: other
93358               }) + ' ' + helpHtml('intro.lines.add_to_selection_' + (context.lastPointerType() === 'mouse' ? 'click' : 'touch'), {
93359                 selected: selected,
93360                 other2: other
93361               }));
93362               context.map().on('move.intro drawn.intro', function () {
93363                 if (hasWashington) {
93364                   selected = _t('intro.graph.name.washington-street');
93365                   other = _t('intro.graph.name.12th-avenue');
93366                   padding = 60 * Math.pow(2, context.map().zoom() - 18);
93367                   box = pad(twelfthAvenueEnd, padding, context);
93368                   box.width *= 3;
93369                 } else {
93370                   selected = _t('intro.graph.name.12th-avenue');
93371                   other = _t('intro.graph.name.washington-street');
93372                   padding = 200 * Math.pow(2, context.map().zoom() - 18);
93373                   box = pad(twelfthAvenue, padding, context);
93374                   box.width /= 2;
93375                 }
93376
93377                 reveal(box, helpHtml('intro.lines.multi_select', {
93378                   selected: selected,
93379                   other1: other
93380                 }) + ' ' + helpHtml('intro.lines.add_to_selection_' + (context.lastPointerType() === 'mouse' ? 'click' : 'touch'), {
93381                   selected: selected,
93382                   other2: other
93383                 }), {
93384                   duration: 0
93385                 });
93386               });
93387               context.on('enter.intro', function () {
93388                 continueTo(multiSelect);
93389               });
93390               context.history().on('change.intro', function () {
93391                 if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93392                   return continueTo(rightClickIntersection);
93393                 }
93394               });
93395             }, 600);
93396
93397             function continueTo(nextStep) {
93398               context.map().on('move.intro drawn.intro', null);
93399               context.on('enter.intro', null);
93400               context.history().on('change.intro', null);
93401               nextStep();
93402             }
93403           }
93404
93405           function multiRightClick() {
93406             if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93407               return continueTo(rightClickIntersection);
93408             }
93409
93410             var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93411             var box = pad(twelfthAvenue, padding, context);
93412             var rightClickString = helpHtml('intro.lines.multi_select_success') + helpHtml('intro.lines.multi_' + (context.lastPointerType() === 'mouse' ? 'rightclick' : 'edit_menu_touch'));
93413             reveal(box, rightClickString);
93414             context.map().on('move.intro drawn.intro', function () {
93415               var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93416               var box = pad(twelfthAvenue, padding, context);
93417               reveal(box, rightClickString, {
93418                 duration: 0
93419               });
93420             });
93421             context.ui().editMenu().on('toggled.intro', function (open) {
93422               if (!open) return;
93423               timeout(function () {
93424                 var ids = context.selectedIDs();
93425
93426                 if (ids.length === 2 && ids.indexOf(twelfthAvenueID) !== -1 && ids.indexOf(_washingtonSegmentID) !== -1) {
93427                   var node = selectMenuItem(context, 'delete').node();
93428                   if (!node) return;
93429                   continueTo(multiDelete);
93430                 } else if (ids.length === 1 && ids.indexOf(_washingtonSegmentID) !== -1) {
93431                   return continueTo(multiSelect);
93432                 } else {
93433                   return continueTo(didSplit);
93434                 }
93435               }, 300); // after edit menu visible
93436             });
93437             context.history().on('change.intro', function () {
93438               if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93439                 return continueTo(rightClickIntersection);
93440               }
93441             });
93442
93443             function continueTo(nextStep) {
93444               context.map().on('move.intro drawn.intro', null);
93445               context.ui().editMenu().on('toggled.intro', null);
93446               context.history().on('change.intro', null);
93447               nextStep();
93448             }
93449           }
93450
93451           function multiDelete() {
93452             if (!_washingtonSegmentID || !context.hasEntity(_washingtonSegmentID) || !context.hasEntity(washingtonStreetID) || !context.hasEntity(twelfthAvenueID) || !context.hasEntity(eleventhAvenueEndID)) {
93453               return continueTo(rightClickIntersection);
93454             }
93455
93456             var node = selectMenuItem(context, 'delete').node();
93457             if (!node) return continueTo(multiRightClick);
93458             reveal('.edit-menu', helpHtml('intro.lines.multi_delete'), {
93459               padding: 50
93460             });
93461             context.map().on('move.intro drawn.intro', function () {
93462               reveal('.edit-menu', helpHtml('intro.lines.multi_delete'), {
93463                 duration: 0,
93464                 padding: 50
93465               });
93466             });
93467             context.on('exit.intro', function () {
93468               if (context.hasEntity(_washingtonSegmentID) || context.hasEntity(twelfthAvenueID)) {
93469                 return continueTo(multiSelect); // left select mode but roads still exist
93470               }
93471             });
93472             context.history().on('change.intro', function () {
93473               if (context.hasEntity(_washingtonSegmentID) || context.hasEntity(twelfthAvenueID)) {
93474                 continueTo(retryDelete); // changed something but roads still exist
93475               } else {
93476                 continueTo(play);
93477               }
93478             });
93479
93480             function continueTo(nextStep) {
93481               context.map().on('move.intro drawn.intro', null);
93482               context.on('exit.intro', null);
93483               context.history().on('change.intro', null);
93484               nextStep();
93485             }
93486           }
93487
93488           function retryDelete() {
93489             context.enter(modeBrowse(context));
93490             var padding = 200 * Math.pow(2, context.map().zoom() - 18);
93491             var box = pad(twelfthAvenue, padding, context);
93492             reveal(box, helpHtml('intro.lines.retry_delete'), {
93493               buttonText: _t.html('intro.ok'),
93494               buttonCallback: function buttonCallback() {
93495                 continueTo(multiSelect);
93496               }
93497             });
93498
93499             function continueTo(nextStep) {
93500               nextStep();
93501             }
93502           }
93503
93504           function play() {
93505             dispatch.call('done');
93506             reveal('.ideditor', helpHtml('intro.lines.play', {
93507               next: _t('intro.buildings.title')
93508             }), {
93509               tooltipBox: '.intro-nav-wrap .chapter-building',
93510               buttonText: _t.html('intro.ok'),
93511               buttonCallback: function buttonCallback() {
93512                 reveal('.ideditor');
93513               }
93514             });
93515           }
93516
93517           chapter.enter = function () {
93518             addLine();
93519           };
93520
93521           chapter.exit = function () {
93522             timeouts.forEach(window.clearTimeout);
93523             select(window).on('pointerdown.intro mousedown.intro', null, true);
93524             context.on('enter.intro exit.intro', null);
93525             context.map().on('move.intro drawn.intro', null);
93526             context.history().on('change.intro', null);
93527             context.container().select('.inspector-wrap').on('wheel.intro', null);
93528             context.container().select('.preset-list-button').on('click.intro', null);
93529           };
93530
93531           chapter.restart = function () {
93532             chapter.exit();
93533             chapter.enter();
93534           };
93535
93536           return utilRebind(chapter, dispatch, 'on');
93537         }
93538
93539         function uiIntroBuilding(context, reveal) {
93540           var dispatch = dispatch$8('done');
93541           var house = [-85.62815, 41.95638];
93542           var tank = [-85.62732, 41.95347];
93543           var buildingCatetory = _mainPresetIndex.item('category-building');
93544           var housePreset = _mainPresetIndex.item('building/house');
93545           var tankPreset = _mainPresetIndex.item('man_made/storage_tank');
93546           var timeouts = [];
93547           var _houseID = null;
93548           var _tankID = null;
93549           var chapter = {
93550             title: 'intro.buildings.title'
93551           };
93552
93553           function timeout(f, t) {
93554             timeouts.push(window.setTimeout(f, t));
93555           }
93556
93557           function eventCancel(d3_event) {
93558             d3_event.stopPropagation();
93559             d3_event.preventDefault();
93560           }
93561
93562           function revealHouse(center, text, options) {
93563             var padding = 160 * Math.pow(2, context.map().zoom() - 20);
93564             var box = pad(center, padding, context);
93565             reveal(box, text, options);
93566           }
93567
93568           function revealTank(center, text, options) {
93569             var padding = 190 * Math.pow(2, context.map().zoom() - 19.5);
93570             var box = pad(center, padding, context);
93571             reveal(box, text, options);
93572           }
93573
93574           function addHouse() {
93575             context.enter(modeBrowse(context));
93576             context.history().reset('initial');
93577             _houseID = null;
93578             var msec = transitionTime(house, context.map().center());
93579
93580             if (msec) {
93581               reveal(null, null, {
93582                 duration: 0
93583               });
93584             }
93585
93586             context.map().centerZoomEase(house, 19, msec);
93587             timeout(function () {
93588               var tooltip = reveal('button.add-area', helpHtml('intro.buildings.add_building'));
93589               tooltip.selectAll('.popover-inner').insert('svg', 'span').attr('class', 'tooltip-illustration').append('use').attr('xlink:href', '#iD-graphic-buildings');
93590               context.on('enter.intro', function (mode) {
93591                 if (mode.id !== 'add-area') return;
93592                 continueTo(startHouse);
93593               });
93594             }, msec + 100);
93595
93596             function continueTo(nextStep) {
93597               context.on('enter.intro', null);
93598               nextStep();
93599             }
93600           }
93601
93602           function startHouse() {
93603             if (context.mode().id !== 'add-area') {
93604               return continueTo(addHouse);
93605             }
93606
93607             _houseID = null;
93608             context.map().zoomEase(20, 500);
93609             timeout(function () {
93610               var startString = helpHtml('intro.buildings.start_building') + helpHtml('intro.buildings.building_corner_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap'));
93611               revealHouse(house, startString);
93612               context.map().on('move.intro drawn.intro', function () {
93613                 revealHouse(house, startString, {
93614                   duration: 0
93615                 });
93616               });
93617               context.on('enter.intro', function (mode) {
93618                 if (mode.id !== 'draw-area') return chapter.restart();
93619                 continueTo(continueHouse);
93620               });
93621             }, 550); // after easing
93622
93623             function continueTo(nextStep) {
93624               context.map().on('move.intro drawn.intro', null);
93625               context.on('enter.intro', null);
93626               nextStep();
93627             }
93628           }
93629
93630           function continueHouse() {
93631             if (context.mode().id !== 'draw-area') {
93632               return continueTo(addHouse);
93633             }
93634
93635             _houseID = null;
93636             var continueString = helpHtml('intro.buildings.continue_building') + '{br}' + helpHtml('intro.areas.finish_area_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.buildings.finish_building');
93637             revealHouse(house, continueString);
93638             context.map().on('move.intro drawn.intro', function () {
93639               revealHouse(house, continueString, {
93640                 duration: 0
93641               });
93642             });
93643             context.on('enter.intro', function (mode) {
93644               if (mode.id === 'draw-area') {
93645                 return;
93646               } else if (mode.id === 'select') {
93647                 var graph = context.graph();
93648                 var way = context.entity(context.selectedIDs()[0]);
93649                 var nodes = graph.childNodes(way);
93650                 var points = utilArrayUniq(nodes).map(function (n) {
93651                   return context.projection(n.loc);
93652                 });
93653
93654                 if (isMostlySquare(points)) {
93655                   _houseID = way.id;
93656                   return continueTo(chooseCategoryBuilding);
93657                 } else {
93658                   return continueTo(retryHouse);
93659                 }
93660               } else {
93661                 return chapter.restart();
93662               }
93663             });
93664
93665             function continueTo(nextStep) {
93666               context.map().on('move.intro drawn.intro', null);
93667               context.on('enter.intro', null);
93668               nextStep();
93669             }
93670           }
93671
93672           function retryHouse() {
93673             var onClick = function onClick() {
93674               continueTo(addHouse);
93675             };
93676
93677             revealHouse(house, helpHtml('intro.buildings.retry_building'), {
93678               buttonText: _t.html('intro.ok'),
93679               buttonCallback: onClick
93680             });
93681             context.map().on('move.intro drawn.intro', function () {
93682               revealHouse(house, helpHtml('intro.buildings.retry_building'), {
93683                 duration: 0,
93684                 buttonText: _t.html('intro.ok'),
93685                 buttonCallback: onClick
93686               });
93687             });
93688
93689             function continueTo(nextStep) {
93690               context.map().on('move.intro drawn.intro', null);
93691               nextStep();
93692             }
93693           }
93694
93695           function chooseCategoryBuilding() {
93696             if (!_houseID || !context.hasEntity(_houseID)) {
93697               return addHouse();
93698             }
93699
93700             var ids = context.selectedIDs();
93701
93702             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _houseID) {
93703               context.enter(modeSelect(context, [_houseID]));
93704             } // disallow scrolling
93705
93706
93707             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
93708             timeout(function () {
93709               // reset pane, in case user somehow happened to change it..
93710               context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
93711               var button = context.container().select('.preset-category-building .preset-list-button');
93712               reveal(button.node(), helpHtml('intro.buildings.choose_category_building', {
93713                 category: buildingCatetory.name()
93714               }));
93715               button.on('click.intro', function () {
93716                 button.on('click.intro', null);
93717                 continueTo(choosePresetHouse);
93718               });
93719             }, 400); // after preset list pane visible..
93720
93721             context.on('enter.intro', function (mode) {
93722               if (!_houseID || !context.hasEntity(_houseID)) {
93723                 return continueTo(addHouse);
93724               }
93725
93726               var ids = context.selectedIDs();
93727
93728               if (mode.id !== 'select' || !ids.length || ids[0] !== _houseID) {
93729                 return continueTo(chooseCategoryBuilding);
93730               }
93731             });
93732
93733             function continueTo(nextStep) {
93734               context.container().select('.inspector-wrap').on('wheel.intro', null);
93735               context.container().select('.preset-list-button').on('click.intro', null);
93736               context.on('enter.intro', null);
93737               nextStep();
93738             }
93739           }
93740
93741           function choosePresetHouse() {
93742             if (!_houseID || !context.hasEntity(_houseID)) {
93743               return addHouse();
93744             }
93745
93746             var ids = context.selectedIDs();
93747
93748             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _houseID) {
93749               context.enter(modeSelect(context, [_houseID]));
93750             } // disallow scrolling
93751
93752
93753             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
93754             timeout(function () {
93755               // reset pane, in case user somehow happened to change it..
93756               context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
93757               var button = context.container().select('.preset-building-house .preset-list-button');
93758               reveal(button.node(), helpHtml('intro.buildings.choose_preset_house', {
93759                 preset: housePreset.name()
93760               }), {
93761                 duration: 300
93762               });
93763               button.on('click.intro', function () {
93764                 button.on('click.intro', null);
93765                 continueTo(closeEditorHouse);
93766               });
93767             }, 400); // after preset list pane visible..
93768
93769             context.on('enter.intro', function (mode) {
93770               if (!_houseID || !context.hasEntity(_houseID)) {
93771                 return continueTo(addHouse);
93772               }
93773
93774               var ids = context.selectedIDs();
93775
93776               if (mode.id !== 'select' || !ids.length || ids[0] !== _houseID) {
93777                 return continueTo(chooseCategoryBuilding);
93778               }
93779             });
93780
93781             function continueTo(nextStep) {
93782               context.container().select('.inspector-wrap').on('wheel.intro', null);
93783               context.container().select('.preset-list-button').on('click.intro', null);
93784               context.on('enter.intro', null);
93785               nextStep();
93786             }
93787           }
93788
93789           function closeEditorHouse() {
93790             if (!_houseID || !context.hasEntity(_houseID)) {
93791               return addHouse();
93792             }
93793
93794             var ids = context.selectedIDs();
93795
93796             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _houseID) {
93797               context.enter(modeSelect(context, [_houseID]));
93798             }
93799
93800             context.history().checkpoint('hasHouse');
93801             context.on('exit.intro', function () {
93802               continueTo(rightClickHouse);
93803             });
93804             timeout(function () {
93805               reveal('.entity-editor-pane', helpHtml('intro.buildings.close', {
93806                 button: {
93807                   html: icon('#iD-icon-close', 'inline')
93808                 }
93809               }));
93810             }, 500);
93811
93812             function continueTo(nextStep) {
93813               context.on('exit.intro', null);
93814               nextStep();
93815             }
93816           }
93817
93818           function rightClickHouse() {
93819             if (!_houseID) return chapter.restart();
93820             context.enter(modeBrowse(context));
93821             context.history().reset('hasHouse');
93822             var zoom = context.map().zoom();
93823
93824             if (zoom < 20) {
93825               zoom = 20;
93826             }
93827
93828             context.map().centerZoomEase(house, zoom, 500);
93829             context.on('enter.intro', function (mode) {
93830               if (mode.id !== 'select') return;
93831               var ids = context.selectedIDs();
93832               if (ids.length !== 1 || ids[0] !== _houseID) return;
93833               timeout(function () {
93834                 var node = selectMenuItem(context, 'orthogonalize').node();
93835                 if (!node) return;
93836                 continueTo(clickSquare);
93837               }, 50); // after menu visible
93838             });
93839             context.map().on('move.intro drawn.intro', function () {
93840               var rightclickString = helpHtml('intro.buildings.' + (context.lastPointerType() === 'mouse' ? 'rightclick_building' : 'edit_menu_building_touch'));
93841               revealHouse(house, rightclickString, {
93842                 duration: 0
93843               });
93844             });
93845             context.history().on('change.intro', function () {
93846               continueTo(rightClickHouse);
93847             });
93848
93849             function continueTo(nextStep) {
93850               context.on('enter.intro', null);
93851               context.map().on('move.intro drawn.intro', null);
93852               context.history().on('change.intro', null);
93853               nextStep();
93854             }
93855           }
93856
93857           function clickSquare() {
93858             if (!_houseID) return chapter.restart();
93859             var entity = context.hasEntity(_houseID);
93860             if (!entity) return continueTo(rightClickHouse);
93861             var node = selectMenuItem(context, 'orthogonalize').node();
93862
93863             if (!node) {
93864               return continueTo(rightClickHouse);
93865             }
93866
93867             var wasChanged = false;
93868             reveal('.edit-menu', helpHtml('intro.buildings.square_building'), {
93869               padding: 50
93870             });
93871             context.on('enter.intro', function (mode) {
93872               if (mode.id === 'browse') {
93873                 continueTo(rightClickHouse);
93874               } else if (mode.id === 'move' || mode.id === 'rotate') {
93875                 continueTo(retryClickSquare);
93876               }
93877             });
93878             context.map().on('move.intro', function () {
93879               var node = selectMenuItem(context, 'orthogonalize').node();
93880
93881               if (!wasChanged && !node) {
93882                 return continueTo(rightClickHouse);
93883               }
93884
93885               reveal('.edit-menu', helpHtml('intro.buildings.square_building'), {
93886                 duration: 0,
93887                 padding: 50
93888               });
93889             });
93890             context.history().on('change.intro', function () {
93891               wasChanged = true;
93892               context.history().on('change.intro', null); // Something changed.  Wait for transition to complete and check undo annotation.
93893
93894               timeout(function () {
93895                 if (context.history().undoAnnotation() === _t('operations.orthogonalize.annotation.feature', {
93896                   n: 1
93897                 })) {
93898                   continueTo(doneSquare);
93899                 } else {
93900                   continueTo(retryClickSquare);
93901                 }
93902               }, 500); // after transitioned actions
93903             });
93904
93905             function continueTo(nextStep) {
93906               context.on('enter.intro', null);
93907               context.map().on('move.intro', null);
93908               context.history().on('change.intro', null);
93909               nextStep();
93910             }
93911           }
93912
93913           function retryClickSquare() {
93914             context.enter(modeBrowse(context));
93915             revealHouse(house, helpHtml('intro.buildings.retry_square'), {
93916               buttonText: _t.html('intro.ok'),
93917               buttonCallback: function buttonCallback() {
93918                 continueTo(rightClickHouse);
93919               }
93920             });
93921
93922             function continueTo(nextStep) {
93923               nextStep();
93924             }
93925           }
93926
93927           function doneSquare() {
93928             context.history().checkpoint('doneSquare');
93929             revealHouse(house, helpHtml('intro.buildings.done_square'), {
93930               buttonText: _t.html('intro.ok'),
93931               buttonCallback: function buttonCallback() {
93932                 continueTo(addTank);
93933               }
93934             });
93935
93936             function continueTo(nextStep) {
93937               nextStep();
93938             }
93939           }
93940
93941           function addTank() {
93942             context.enter(modeBrowse(context));
93943             context.history().reset('doneSquare');
93944             _tankID = null;
93945             var msec = transitionTime(tank, context.map().center());
93946
93947             if (msec) {
93948               reveal(null, null, {
93949                 duration: 0
93950               });
93951             }
93952
93953             context.map().centerZoomEase(tank, 19.5, msec);
93954             timeout(function () {
93955               reveal('button.add-area', helpHtml('intro.buildings.add_tank'));
93956               context.on('enter.intro', function (mode) {
93957                 if (mode.id !== 'add-area') return;
93958                 continueTo(startTank);
93959               });
93960             }, msec + 100);
93961
93962             function continueTo(nextStep) {
93963               context.on('enter.intro', null);
93964               nextStep();
93965             }
93966           }
93967
93968           function startTank() {
93969             if (context.mode().id !== 'add-area') {
93970               return continueTo(addTank);
93971             }
93972
93973             _tankID = null;
93974             timeout(function () {
93975               var startString = helpHtml('intro.buildings.start_tank') + helpHtml('intro.buildings.tank_edge_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap'));
93976               revealTank(tank, startString);
93977               context.map().on('move.intro drawn.intro', function () {
93978                 revealTank(tank, startString, {
93979                   duration: 0
93980                 });
93981               });
93982               context.on('enter.intro', function (mode) {
93983                 if (mode.id !== 'draw-area') return chapter.restart();
93984                 continueTo(continueTank);
93985               });
93986             }, 550); // after easing
93987
93988             function continueTo(nextStep) {
93989               context.map().on('move.intro drawn.intro', null);
93990               context.on('enter.intro', null);
93991               nextStep();
93992             }
93993           }
93994
93995           function continueTank() {
93996             if (context.mode().id !== 'draw-area') {
93997               return continueTo(addTank);
93998             }
93999
94000             _tankID = null;
94001             var continueString = helpHtml('intro.buildings.continue_tank') + '{br}' + helpHtml('intro.areas.finish_area_' + (context.lastPointerType() === 'mouse' ? 'click' : 'tap')) + helpHtml('intro.buildings.finish_tank');
94002             revealTank(tank, continueString);
94003             context.map().on('move.intro drawn.intro', function () {
94004               revealTank(tank, continueString, {
94005                 duration: 0
94006               });
94007             });
94008             context.on('enter.intro', function (mode) {
94009               if (mode.id === 'draw-area') {
94010                 return;
94011               } else if (mode.id === 'select') {
94012                 _tankID = context.selectedIDs()[0];
94013                 return continueTo(searchPresetTank);
94014               } else {
94015                 return continueTo(addTank);
94016               }
94017             });
94018
94019             function continueTo(nextStep) {
94020               context.map().on('move.intro drawn.intro', null);
94021               context.on('enter.intro', null);
94022               nextStep();
94023             }
94024           }
94025
94026           function searchPresetTank() {
94027             if (!_tankID || !context.hasEntity(_tankID)) {
94028               return addTank();
94029             }
94030
94031             var ids = context.selectedIDs();
94032
94033             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _tankID) {
94034               context.enter(modeSelect(context, [_tankID]));
94035             } // disallow scrolling
94036
94037
94038             context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
94039             timeout(function () {
94040               // reset pane, in case user somehow happened to change it..
94041               context.container().select('.inspector-wrap .panewrap').style('right', '-100%');
94042               context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
94043               reveal('.preset-search-input', helpHtml('intro.buildings.search_tank', {
94044                 preset: tankPreset.name()
94045               }));
94046             }, 400); // after preset list pane visible..
94047
94048             context.on('enter.intro', function (mode) {
94049               if (!_tankID || !context.hasEntity(_tankID)) {
94050                 return continueTo(addTank);
94051               }
94052
94053               var ids = context.selectedIDs();
94054
94055               if (mode.id !== 'select' || !ids.length || ids[0] !== _tankID) {
94056                 // keep the user's area selected..
94057                 context.enter(modeSelect(context, [_tankID])); // reset pane, in case user somehow happened to change it..
94058
94059                 context.container().select('.inspector-wrap .panewrap').style('right', '-100%'); // disallow scrolling
94060
94061                 context.container().select('.inspector-wrap').on('wheel.intro', eventCancel);
94062                 context.container().select('.preset-search-input').on('keydown.intro', null).on('keyup.intro', checkPresetSearch);
94063                 reveal('.preset-search-input', helpHtml('intro.buildings.search_tank', {
94064                   preset: tankPreset.name()
94065                 }));
94066                 context.history().on('change.intro', null);
94067               }
94068             });
94069
94070             function checkPresetSearch() {
94071               var first = context.container().select('.preset-list-item:first-child');
94072
94073               if (first.classed('preset-man_made-storage_tank')) {
94074                 reveal(first.select('.preset-list-button').node(), helpHtml('intro.buildings.choose_tank', {
94075                   preset: tankPreset.name()
94076                 }), {
94077                   duration: 300
94078                 });
94079                 context.container().select('.preset-search-input').on('keydown.intro', eventCancel, true).on('keyup.intro', null);
94080                 context.history().on('change.intro', function () {
94081                   continueTo(closeEditorTank);
94082                 });
94083               }
94084             }
94085
94086             function continueTo(nextStep) {
94087               context.container().select('.inspector-wrap').on('wheel.intro', null);
94088               context.on('enter.intro', null);
94089               context.history().on('change.intro', null);
94090               context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
94091               nextStep();
94092             }
94093           }
94094
94095           function closeEditorTank() {
94096             if (!_tankID || !context.hasEntity(_tankID)) {
94097               return addTank();
94098             }
94099
94100             var ids = context.selectedIDs();
94101
94102             if (context.mode().id !== 'select' || !ids.length || ids[0] !== _tankID) {
94103               context.enter(modeSelect(context, [_tankID]));
94104             }
94105
94106             context.history().checkpoint('hasTank');
94107             context.on('exit.intro', function () {
94108               continueTo(rightClickTank);
94109             });
94110             timeout(function () {
94111               reveal('.entity-editor-pane', helpHtml('intro.buildings.close', {
94112                 button: {
94113                   html: icon('#iD-icon-close', 'inline')
94114                 }
94115               }));
94116             }, 500);
94117
94118             function continueTo(nextStep) {
94119               context.on('exit.intro', null);
94120               nextStep();
94121             }
94122           }
94123
94124           function rightClickTank() {
94125             if (!_tankID) return continueTo(addTank);
94126             context.enter(modeBrowse(context));
94127             context.history().reset('hasTank');
94128             context.map().centerEase(tank, 500);
94129             timeout(function () {
94130               context.on('enter.intro', function (mode) {
94131                 if (mode.id !== 'select') return;
94132                 var ids = context.selectedIDs();
94133                 if (ids.length !== 1 || ids[0] !== _tankID) return;
94134                 timeout(function () {
94135                   var node = selectMenuItem(context, 'circularize').node();
94136                   if (!node) return;
94137                   continueTo(clickCircle);
94138                 }, 50); // after menu visible
94139               });
94140               var rightclickString = helpHtml('intro.buildings.' + (context.lastPointerType() === 'mouse' ? 'rightclick_tank' : 'edit_menu_tank_touch'));
94141               revealTank(tank, rightclickString);
94142               context.map().on('move.intro drawn.intro', function () {
94143                 revealTank(tank, rightclickString, {
94144                   duration: 0
94145                 });
94146               });
94147               context.history().on('change.intro', function () {
94148                 continueTo(rightClickTank);
94149               });
94150             }, 600);
94151
94152             function continueTo(nextStep) {
94153               context.on('enter.intro', null);
94154               context.map().on('move.intro drawn.intro', null);
94155               context.history().on('change.intro', null);
94156               nextStep();
94157             }
94158           }
94159
94160           function clickCircle() {
94161             if (!_tankID) return chapter.restart();
94162             var entity = context.hasEntity(_tankID);
94163             if (!entity) return continueTo(rightClickTank);
94164             var node = selectMenuItem(context, 'circularize').node();
94165
94166             if (!node) {
94167               return continueTo(rightClickTank);
94168             }
94169
94170             var wasChanged = false;
94171             reveal('.edit-menu', helpHtml('intro.buildings.circle_tank'), {
94172               padding: 50
94173             });
94174             context.on('enter.intro', function (mode) {
94175               if (mode.id === 'browse') {
94176                 continueTo(rightClickTank);
94177               } else if (mode.id === 'move' || mode.id === 'rotate') {
94178                 continueTo(retryClickCircle);
94179               }
94180             });
94181             context.map().on('move.intro', function () {
94182               var node = selectMenuItem(context, 'circularize').node();
94183
94184               if (!wasChanged && !node) {
94185                 return continueTo(rightClickTank);
94186               }
94187
94188               reveal('.edit-menu', helpHtml('intro.buildings.circle_tank'), {
94189                 duration: 0,
94190                 padding: 50
94191               });
94192             });
94193             context.history().on('change.intro', function () {
94194               wasChanged = true;
94195               context.history().on('change.intro', null); // Something changed.  Wait for transition to complete and check undo annotation.
94196
94197               timeout(function () {
94198                 if (context.history().undoAnnotation() === _t('operations.circularize.annotation.feature', {
94199                   n: 1
94200                 })) {
94201                   continueTo(play);
94202                 } else {
94203                   continueTo(retryClickCircle);
94204                 }
94205               }, 500); // after transitioned actions
94206             });
94207
94208             function continueTo(nextStep) {
94209               context.on('enter.intro', null);
94210               context.map().on('move.intro', null);
94211               context.history().on('change.intro', null);
94212               nextStep();
94213             }
94214           }
94215
94216           function retryClickCircle() {
94217             context.enter(modeBrowse(context));
94218             revealTank(tank, helpHtml('intro.buildings.retry_circle'), {
94219               buttonText: _t.html('intro.ok'),
94220               buttonCallback: function buttonCallback() {
94221                 continueTo(rightClickTank);
94222               }
94223             });
94224
94225             function continueTo(nextStep) {
94226               nextStep();
94227             }
94228           }
94229
94230           function play() {
94231             dispatch.call('done');
94232             reveal('.ideditor', helpHtml('intro.buildings.play', {
94233               next: _t('intro.startediting.title')
94234             }), {
94235               tooltipBox: '.intro-nav-wrap .chapter-startEditing',
94236               buttonText: _t.html('intro.ok'),
94237               buttonCallback: function buttonCallback() {
94238                 reveal('.ideditor');
94239               }
94240             });
94241           }
94242
94243           chapter.enter = function () {
94244             addHouse();
94245           };
94246
94247           chapter.exit = function () {
94248             timeouts.forEach(window.clearTimeout);
94249             context.on('enter.intro exit.intro', null);
94250             context.map().on('move.intro drawn.intro', null);
94251             context.history().on('change.intro', null);
94252             context.container().select('.inspector-wrap').on('wheel.intro', null);
94253             context.container().select('.preset-search-input').on('keydown.intro keyup.intro', null);
94254             context.container().select('.more-fields .combobox-input').on('click.intro', null);
94255           };
94256
94257           chapter.restart = function () {
94258             chapter.exit();
94259             chapter.enter();
94260           };
94261
94262           return utilRebind(chapter, dispatch, 'on');
94263         }
94264
94265         function uiIntroStartEditing(context, reveal) {
94266           var dispatch = dispatch$8('done', 'startEditing');
94267           var modalSelection = select(null);
94268           var chapter = {
94269             title: 'intro.startediting.title'
94270           };
94271
94272           function showHelp() {
94273             reveal('.map-control.help-control', helpHtml('intro.startediting.help'), {
94274               buttonText: _t.html('intro.ok'),
94275               buttonCallback: function buttonCallback() {
94276                 shortcuts();
94277               }
94278             });
94279           }
94280
94281           function shortcuts() {
94282             reveal('.map-control.help-control', helpHtml('intro.startediting.shortcuts'), {
94283               buttonText: _t.html('intro.ok'),
94284               buttonCallback: function buttonCallback() {
94285                 showSave();
94286               }
94287             });
94288           }
94289
94290           function showSave() {
94291             context.container().selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
94292
94293             reveal('.top-toolbar button.save', helpHtml('intro.startediting.save'), {
94294               buttonText: _t.html('intro.ok'),
94295               buttonCallback: function buttonCallback() {
94296                 showStart();
94297               }
94298             });
94299           }
94300
94301           function showStart() {
94302             context.container().selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
94303
94304             modalSelection = uiModal(context.container());
94305             modalSelection.select('.modal').attr('class', 'modal-splash modal');
94306             modalSelection.selectAll('.close').remove();
94307             var startbutton = modalSelection.select('.content').attr('class', 'fillL').append('button').attr('class', 'modal-section huge-modal-button').on('click', function () {
94308               modalSelection.remove();
94309             });
94310             startbutton.append('svg').attr('class', 'illustration').append('use').attr('xlink:href', '#iD-logo-walkthrough');
94311             startbutton.append('h2').call(_t.append('intro.startediting.start'));
94312             dispatch.call('startEditing');
94313           }
94314
94315           chapter.enter = function () {
94316             showHelp();
94317           };
94318
94319           chapter.exit = function () {
94320             modalSelection.remove();
94321             context.container().selectAll('.shaded').remove(); // in case user opened keyboard shortcuts
94322           };
94323
94324           return utilRebind(chapter, dispatch, 'on');
94325         }
94326
94327         var chapterUi = {
94328           welcome: uiIntroWelcome,
94329           navigation: uiIntroNavigation,
94330           point: uiIntroPoint,
94331           area: uiIntroArea,
94332           line: uiIntroLine,
94333           building: uiIntroBuilding,
94334           startEditing: uiIntroStartEditing
94335         };
94336         var chapterFlow = ['welcome', 'navigation', 'point', 'area', 'line', 'building', 'startEditing'];
94337         function uiIntro(context) {
94338           var INTRO_IMAGERY = 'EsriWorldImageryClarity';
94339           var _introGraph = {};
94340
94341           var _currChapter;
94342
94343           function intro(selection) {
94344             _mainFileFetcher.get('intro_graph').then(function (dataIntroGraph) {
94345               // create entities for intro graph and localize names
94346               for (var id in dataIntroGraph) {
94347                 if (!_introGraph[id]) {
94348                   _introGraph[id] = osmEntity(localize(dataIntroGraph[id]));
94349                 }
94350               }
94351
94352               selection.call(startIntro);
94353             })["catch"](function () {
94354               /* ignore */
94355             });
94356           }
94357
94358           function startIntro(selection) {
94359             context.enter(modeBrowse(context)); // Save current map state
94360
94361             var osm = context.connection();
94362             var history = context.history().toJSON();
94363             var hash = window.location.hash;
94364             var center = context.map().center();
94365             var zoom = context.map().zoom();
94366             var background = context.background().baseLayerSource();
94367             var overlays = context.background().overlayLayerSources();
94368             var opacity = context.container().selectAll('.main-map .layer-background').style('opacity');
94369             var caches = osm && osm.caches();
94370             var baseEntities = context.history().graph().base().entities; // Show sidebar and disable the sidebar resizing button
94371             // (this needs to be before `context.inIntro(true)`)
94372
94373             context.ui().sidebar.expand();
94374             context.container().selectAll('button.sidebar-toggle').classed('disabled', true); // Block saving
94375
94376             context.inIntro(true); // Load semi-real data used in intro
94377
94378             if (osm) {
94379               osm.toggle(false).reset();
94380             }
94381
94382             context.history().reset();
94383             context.history().merge(Object.values(coreGraph().load(_introGraph).entities));
94384             context.history().checkpoint('initial'); // Setup imagery
94385
94386             var imagery = context.background().findSource(INTRO_IMAGERY);
94387
94388             if (imagery) {
94389               context.background().baseLayerSource(imagery);
94390             } else {
94391               context.background().bing();
94392             }
94393
94394             overlays.forEach(function (d) {
94395               return context.background().toggleOverlayLayer(d);
94396             }); // Setup data layers (only OSM)
94397
94398             var layers = context.layers();
94399             layers.all().forEach(function (item) {
94400               // if the layer has the function `enabled`
94401               if (typeof item.layer.enabled === 'function') {
94402                 item.layer.enabled(item.id === 'osm');
94403               }
94404             });
94405             context.container().selectAll('.main-map .layer-background').style('opacity', 1);
94406             var curtain = uiCurtain(context.container().node());
94407             selection.call(curtain); // Store that the user started the walkthrough..
94408
94409             corePreferences('walkthrough_started', 'yes'); // Restore previous walkthrough progress..
94410
94411             var storedProgress = corePreferences('walkthrough_progress') || '';
94412             var progress = storedProgress.split(';').filter(Boolean);
94413             var chapters = chapterFlow.map(function (chapter, i) {
94414               var s = chapterUi[chapter](context, curtain.reveal).on('done', function () {
94415                 buttons.filter(function (d) {
94416                   return d.title === s.title;
94417                 }).classed('finished', true);
94418
94419                 if (i < chapterFlow.length - 1) {
94420                   var next = chapterFlow[i + 1];
94421                   context.container().select("button.chapter-".concat(next)).classed('next', true);
94422                 } // Store walkthrough progress..
94423
94424
94425                 progress.push(chapter);
94426                 corePreferences('walkthrough_progress', utilArrayUniq(progress).join(';'));
94427               });
94428               return s;
94429             });
94430             chapters[chapters.length - 1].on('startEditing', function () {
94431               // Store walkthrough progress..
94432               progress.push('startEditing');
94433               corePreferences('walkthrough_progress', utilArrayUniq(progress).join(';')); // Store if walkthrough is completed..
94434
94435               var incomplete = utilArrayDifference(chapterFlow, progress);
94436
94437               if (!incomplete.length) {
94438                 corePreferences('walkthrough_completed', 'yes');
94439               }
94440
94441               curtain.remove();
94442               navwrap.remove();
94443               context.container().selectAll('.main-map .layer-background').style('opacity', opacity);
94444               context.container().selectAll('button.sidebar-toggle').classed('disabled', false);
94445
94446               if (osm) {
94447                 osm.toggle(true).reset().caches(caches);
94448               }
94449
94450               context.history().reset().merge(Object.values(baseEntities));
94451               context.background().baseLayerSource(background);
94452               overlays.forEach(function (d) {
94453                 return context.background().toggleOverlayLayer(d);
94454               });
94455
94456               if (history) {
94457                 context.history().fromJSON(history, false);
94458               }
94459
94460               context.map().centerZoom(center, zoom);
94461               window.location.replace(hash);
94462               context.inIntro(false);
94463             });
94464             var navwrap = selection.append('div').attr('class', 'intro-nav-wrap fillD');
94465             navwrap.append('svg').attr('class', 'intro-nav-wrap-logo').append('use').attr('xlink:href', '#iD-logo-walkthrough');
94466             var buttonwrap = navwrap.append('div').attr('class', 'joined').selectAll('button.chapter');
94467             var buttons = buttonwrap.data(chapters).enter().append('button').attr('class', function (d, i) {
94468               return "chapter chapter-".concat(chapterFlow[i]);
94469             }).on('click', enterChapter);
94470             buttons.append('span').html(function (d) {
94471               return _t.html(d.title);
94472             });
94473             buttons.append('span').attr('class', 'status').call(svgIcon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward', 'inline'));
94474             enterChapter(null, chapters[0]);
94475
94476             function enterChapter(d3_event, newChapter) {
94477               if (_currChapter) {
94478                 _currChapter.exit();
94479               }
94480
94481               context.enter(modeBrowse(context));
94482               _currChapter = newChapter;
94483
94484               _currChapter.enter();
94485
94486               buttons.classed('next', false).classed('active', function (d) {
94487                 return d.title === _currChapter.title;
94488               });
94489             }
94490           }
94491
94492           return intro;
94493         }
94494
94495         function uiIssuesInfo(context) {
94496           var warningsItem = {
94497             id: 'warnings',
94498             count: 0,
94499             iconID: 'iD-icon-alert',
94500             descriptionID: 'issues.warnings_and_errors'
94501           };
94502           var resolvedItem = {
94503             id: 'resolved',
94504             count: 0,
94505             iconID: 'iD-icon-apply',
94506             descriptionID: 'issues.user_resolved_issues'
94507           };
94508
94509           function update(selection) {
94510             var shownItems = [];
94511             var liveIssues = context.validator().getIssues({
94512               what: corePreferences('validate-what') || 'edited',
94513               where: corePreferences('validate-where') || 'all'
94514             });
94515
94516             if (liveIssues.length) {
94517               warningsItem.count = liveIssues.length;
94518               shownItems.push(warningsItem);
94519             }
94520
94521             if (corePreferences('validate-what') === 'all') {
94522               var resolvedIssues = context.validator().getResolvedIssues();
94523
94524               if (resolvedIssues.length) {
94525                 resolvedItem.count = resolvedIssues.length;
94526                 shownItems.push(resolvedItem);
94527               }
94528             }
94529
94530             var chips = selection.selectAll('.chip').data(shownItems, function (d) {
94531               return d.id;
94532             });
94533             chips.exit().remove();
94534             var enter = chips.enter().append('a').attr('class', function (d) {
94535               return 'chip ' + d.id + '-count';
94536             }).attr('href', '#').each(function (d) {
94537               var chipSelection = select(this);
94538               var tooltipBehavior = uiTooltip().placement('top').title(_t.html(d.descriptionID));
94539               chipSelection.call(tooltipBehavior).on('click', function (d3_event) {
94540                 d3_event.preventDefault();
94541                 tooltipBehavior.hide(select(this)); // open the Issues pane
94542
94543                 context.ui().togglePanes(context.container().select('.map-panes .issues-pane'));
94544               });
94545               chipSelection.call(svgIcon('#' + d.iconID));
94546             });
94547             enter.append('span').attr('class', 'count');
94548             enter.merge(chips).selectAll('span.count').text(function (d) {
94549               return d.count.toString();
94550             });
94551           }
94552
94553           return function (selection) {
94554             update(selection);
94555             context.validator().on('validated.infobox', function () {
94556               update(selection);
94557             });
94558           };
94559         }
94560
94561         function uiMapInMap(context) {
94562           function mapInMap(selection) {
94563             var backgroundLayer = rendererTileLayer(context);
94564             var overlayLayers = {};
94565             var projection = geoRawMercator();
94566             var dataLayer = svgData(projection, context).showLabels(false);
94567             var debugLayer = svgDebug(projection, context);
94568             var zoom = d3_zoom().scaleExtent([geoZoomToScale(0.5), geoZoomToScale(24)]).on('start', zoomStarted).on('zoom', zoomed).on('end', zoomEnded);
94569             var wrap = select(null);
94570             var tiles = select(null);
94571             var viewport = select(null);
94572             var _isTransformed = false;
94573             var _isHidden = true;
94574             var _skipEvents = false;
94575             var _gesture = null;
94576             var _zDiff = 6; // by default, minimap renders at (main zoom - 6)
94577
94578             var _dMini; // dimensions of minimap
94579
94580
94581             var _cMini; // center pixel of minimap
94582
94583
94584             var _tStart; // transform at start of gesture
94585
94586
94587             var _tCurr; // transform at most recent event
94588
94589
94590             var _timeoutID;
94591
94592             function zoomStarted() {
94593               if (_skipEvents) return;
94594               _tStart = _tCurr = projection.transform();
94595               _gesture = null;
94596             }
94597
94598             function zoomed(d3_event) {
94599               if (_skipEvents) return;
94600               var x = d3_event.transform.x;
94601               var y = d3_event.transform.y;
94602               var k = d3_event.transform.k;
94603               var isZooming = k !== _tStart.k;
94604               var isPanning = x !== _tStart.x || y !== _tStart.y;
94605
94606               if (!isZooming && !isPanning) {
94607                 return; // no change
94608               } // lock in either zooming or panning, don't allow both in minimap.
94609
94610
94611               if (!_gesture) {
94612                 _gesture = isZooming ? 'zoom' : 'pan';
94613               }
94614
94615               var tMini = projection.transform();
94616               var tX, tY, scale;
94617
94618               if (_gesture === 'zoom') {
94619                 scale = k / tMini.k;
94620                 tX = (_cMini[0] / scale - _cMini[0]) * scale;
94621                 tY = (_cMini[1] / scale - _cMini[1]) * scale;
94622               } else {
94623                 k = tMini.k;
94624                 scale = 1;
94625                 tX = x - tMini.x;
94626                 tY = y - tMini.y;
94627               }
94628
94629               utilSetTransform(tiles, tX, tY, scale);
94630               utilSetTransform(viewport, 0, 0, scale);
94631               _isTransformed = true;
94632               _tCurr = identity$2.translate(x, y).scale(k);
94633               var zMain = geoScaleToZoom(context.projection.scale());
94634               var zMini = geoScaleToZoom(k);
94635               _zDiff = zMain - zMini;
94636               queueRedraw();
94637             }
94638
94639             function zoomEnded() {
94640               if (_skipEvents) return;
94641               if (_gesture !== 'pan') return;
94642               updateProjection();
94643               _gesture = null;
94644               context.map().center(projection.invert(_cMini)); // recenter main map..
94645             }
94646
94647             function updateProjection() {
94648               var loc = context.map().center();
94649               var tMain = context.projection.transform();
94650               var zMain = geoScaleToZoom(tMain.k);
94651               var zMini = Math.max(zMain - _zDiff, 0.5);
94652               var kMini = geoZoomToScale(zMini);
94653               projection.translate([tMain.x, tMain.y]).scale(kMini);
94654               var point = projection(loc);
94655               var mouse = _gesture === 'pan' ? geoVecSubtract([_tCurr.x, _tCurr.y], [_tStart.x, _tStart.y]) : [0, 0];
94656               var xMini = _cMini[0] - point[0] + tMain.x + mouse[0];
94657               var yMini = _cMini[1] - point[1] + tMain.y + mouse[1];
94658               projection.translate([xMini, yMini]).clipExtent([[0, 0], _dMini]);
94659               _tCurr = projection.transform();
94660
94661               if (_isTransformed) {
94662                 utilSetTransform(tiles, 0, 0);
94663                 utilSetTransform(viewport, 0, 0);
94664                 _isTransformed = false;
94665               }
94666
94667               zoom.scaleExtent([geoZoomToScale(0.5), geoZoomToScale(zMain - 3)]);
94668               _skipEvents = true;
94669               wrap.call(zoom.transform, _tCurr);
94670               _skipEvents = false;
94671             }
94672
94673             function redraw() {
94674               clearTimeout(_timeoutID);
94675               if (_isHidden) return;
94676               updateProjection();
94677               var zMini = geoScaleToZoom(projection.scale()); // setup tile container
94678
94679               tiles = wrap.selectAll('.map-in-map-tiles').data([0]);
94680               tiles = tiles.enter().append('div').attr('class', 'map-in-map-tiles').merge(tiles); // redraw background
94681
94682               backgroundLayer.source(context.background().baseLayerSource()).projection(projection).dimensions(_dMini);
94683               var background = tiles.selectAll('.map-in-map-background').data([0]);
94684               background.enter().append('div').attr('class', 'map-in-map-background').merge(background).call(backgroundLayer); // redraw overlay
94685
94686               var overlaySources = context.background().overlayLayerSources();
94687               var activeOverlayLayers = [];
94688
94689               for (var i = 0; i < overlaySources.length; i++) {
94690                 if (overlaySources[i].validZoom(zMini)) {
94691                   if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
94692                   activeOverlayLayers.push(overlayLayers[i].source(overlaySources[i]).projection(projection).dimensions(_dMini));
94693                 }
94694               }
94695
94696               var overlay = tiles.selectAll('.map-in-map-overlay').data([0]);
94697               overlay = overlay.enter().append('div').attr('class', 'map-in-map-overlay').merge(overlay);
94698               var overlays = overlay.selectAll('div').data(activeOverlayLayers, function (d) {
94699                 return d.source().name();
94700               });
94701               overlays.exit().remove();
94702               overlays = overlays.enter().append('div').merge(overlays).each(function (layer) {
94703                 select(this).call(layer);
94704               });
94705               var dataLayers = tiles.selectAll('.map-in-map-data').data([0]);
94706               dataLayers.exit().remove();
94707               dataLayers = dataLayers.enter().append('svg').attr('class', 'map-in-map-data').merge(dataLayers).call(dataLayer).call(debugLayer); // redraw viewport bounding box
94708
94709               if (_gesture !== 'pan') {
94710                 var getPath = d3_geoPath(projection);
94711                 var bbox = {
94712                   type: 'Polygon',
94713                   coordinates: [context.map().extent().polygon()]
94714                 };
94715                 viewport = wrap.selectAll('.map-in-map-viewport').data([0]);
94716                 viewport = viewport.enter().append('svg').attr('class', 'map-in-map-viewport').merge(viewport);
94717                 var path = viewport.selectAll('.map-in-map-bbox').data([bbox]);
94718                 path.enter().append('path').attr('class', 'map-in-map-bbox').merge(path).attr('d', getPath).classed('thick', function (d) {
94719                   return getPath.area(d) < 30;
94720                 });
94721               }
94722             }
94723
94724             function queueRedraw() {
94725               clearTimeout(_timeoutID);
94726               _timeoutID = setTimeout(function () {
94727                 redraw();
94728               }, 750);
94729             }
94730
94731             function toggle(d3_event) {
94732               if (d3_event) d3_event.preventDefault();
94733               _isHidden = !_isHidden;
94734               context.container().select('.minimap-toggle-item').classed('active', !_isHidden).select('input').property('checked', !_isHidden);
94735
94736               if (_isHidden) {
94737                 wrap.style('display', 'block').style('opacity', '1').transition().duration(200).style('opacity', '0').on('end', function () {
94738                   selection.selectAll('.map-in-map').style('display', 'none');
94739                 });
94740               } else {
94741                 wrap.style('display', 'block').style('opacity', '0').transition().duration(200).style('opacity', '1').on('end', function () {
94742                   redraw();
94743                 });
94744               }
94745             }
94746
94747             uiMapInMap.toggle = toggle;
94748             wrap = selection.selectAll('.map-in-map').data([0]);
94749             wrap = wrap.enter().append('div').attr('class', 'map-in-map').style('display', _isHidden ? 'none' : 'block').call(zoom).on('dblclick.zoom', null).merge(wrap); // reflow warning: Hardcode dimensions - currently can't resize it anyway..
94750
94751             _dMini = [200, 150]; //utilGetDimensions(wrap);
94752
94753             _cMini = geoVecScale(_dMini, 0.5);
94754             context.map().on('drawn.map-in-map', function (drawn) {
94755               if (drawn.full === true) {
94756                 redraw();
94757               }
94758             });
94759             redraw();
94760             context.keybinding().on(_t('background.minimap.key'), toggle);
94761           }
94762
94763           return mapInMap;
94764         }
94765
94766         function uiNotice(context) {
94767           return function (selection) {
94768             var div = selection.append('div').attr('class', 'notice');
94769             var button = div.append('button').attr('class', 'zoom-to notice fillD').on('click', function () {
94770               context.map().zoomEase(context.minEditableZoom());
94771             }).on('wheel', function (d3_event) {
94772               // let wheel events pass through #4482
94773               var e2 = new WheelEvent(d3_event.type, d3_event);
94774               context.surface().node().dispatchEvent(e2);
94775             });
94776             button.call(svgIcon('#iD-icon-plus', 'pre-text')).append('span').attr('class', 'label').call(_t.append('zoom_in_edit'));
94777
94778             function disableTooHigh() {
94779               var canEdit = context.map().zoom() >= context.minEditableZoom();
94780               div.style('display', canEdit ? 'none' : 'block');
94781             }
94782
94783             context.map().on('move.notice', debounce(disableTooHigh, 500));
94784             disableTooHigh();
94785           };
94786         }
94787
94788         function uiPhotoviewer(context) {
94789           var dispatch = dispatch$8('resize');
94790
94791           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
94792
94793           function photoviewer(selection) {
94794             selection.append('button').attr('class', 'thumb-hide').attr('title', _t('icons.close')).on('click', function () {
94795               if (services.streetside) {
94796                 services.streetside.hideViewer(context);
94797               }
94798
94799               if (services.mapillary) {
94800                 services.mapillary.hideViewer(context);
94801               }
94802
94803               if (services.kartaview) {
94804                 services.kartaview.hideViewer(context);
94805               }
94806             }).append('div').call(svgIcon('#iD-icon-close'));
94807
94808             function preventDefault(d3_event) {
94809               d3_event.preventDefault();
94810             }
94811
94812             selection.append('button').attr('class', 'resize-handle-xy').on('touchstart touchdown touchend', preventDefault).on(_pointerPrefix + 'down', buildResizeListener(selection, 'resize', dispatch, {
94813               resizeOnX: true,
94814               resizeOnY: true
94815             }));
94816             selection.append('button').attr('class', 'resize-handle-x').on('touchstart touchdown touchend', preventDefault).on(_pointerPrefix + 'down', buildResizeListener(selection, 'resize', dispatch, {
94817               resizeOnX: true
94818             }));
94819             selection.append('button').attr('class', 'resize-handle-y').on('touchstart touchdown touchend', preventDefault).on(_pointerPrefix + 'down', buildResizeListener(selection, 'resize', dispatch, {
94820               resizeOnY: true
94821             }));
94822
94823             function buildResizeListener(target, eventName, dispatch, options) {
94824               var resizeOnX = !!options.resizeOnX;
94825               var resizeOnY = !!options.resizeOnY;
94826               var minHeight = options.minHeight || 240;
94827               var minWidth = options.minWidth || 320;
94828               var pointerId;
94829               var startX;
94830               var startY;
94831               var startWidth;
94832               var startHeight;
94833
94834               function startResize(d3_event) {
94835                 if (pointerId !== (d3_event.pointerId || 'mouse')) return;
94836                 d3_event.preventDefault();
94837                 d3_event.stopPropagation();
94838                 var mapSize = context.map().dimensions();
94839
94840                 if (resizeOnX) {
94841                   var maxWidth = mapSize[0];
94842                   var newWidth = clamp(startWidth + d3_event.clientX - startX, minWidth, maxWidth);
94843                   target.style('width', newWidth + 'px');
94844                 }
94845
94846                 if (resizeOnY) {
94847                   var maxHeight = mapSize[1] - 90; // preserve space at top/bottom of map
94848
94849                   var newHeight = clamp(startHeight + startY - d3_event.clientY, minHeight, maxHeight);
94850                   target.style('height', newHeight + 'px');
94851                 }
94852
94853                 dispatch.call(eventName, target, utilGetDimensions(target, true));
94854               }
94855
94856               function clamp(num, min, max) {
94857                 return Math.max(min, Math.min(num, max));
94858               }
94859
94860               function stopResize(d3_event) {
94861                 if (pointerId !== (d3_event.pointerId || 'mouse')) return;
94862                 d3_event.preventDefault();
94863                 d3_event.stopPropagation(); // remove all the listeners we added
94864
94865                 select(window).on('.' + eventName, null);
94866               }
94867
94868               return function initResize(d3_event) {
94869                 d3_event.preventDefault();
94870                 d3_event.stopPropagation();
94871                 pointerId = d3_event.pointerId || 'mouse';
94872                 startX = d3_event.clientX;
94873                 startY = d3_event.clientY;
94874                 var targetRect = target.node().getBoundingClientRect();
94875                 startWidth = targetRect.width;
94876                 startHeight = targetRect.height;
94877                 select(window).on(_pointerPrefix + 'move.' + eventName, startResize, false).on(_pointerPrefix + 'up.' + eventName, stopResize, false);
94878
94879                 if (_pointerPrefix === 'pointer') {
94880                   select(window).on('pointercancel.' + eventName, stopResize, false);
94881                 }
94882               };
94883             }
94884           }
94885
94886           photoviewer.onMapResize = function () {
94887             var photoviewer = context.container().select('.photoviewer');
94888             var content = context.container().select('.main-content');
94889             var mapDimensions = utilGetDimensions(content, true); // shrink photo viewer if it is too big
94890             // (-90 preserves space at top and bottom of map used by menus)
94891
94892             var photoDimensions = utilGetDimensions(photoviewer, true);
94893
94894             if (photoDimensions[0] > mapDimensions[0] || photoDimensions[1] > mapDimensions[1] - 90) {
94895               var setPhotoDimensions = [Math.min(photoDimensions[0], mapDimensions[0]), Math.min(photoDimensions[1], mapDimensions[1] - 90)];
94896               photoviewer.style('width', setPhotoDimensions[0] + 'px').style('height', setPhotoDimensions[1] + 'px');
94897               dispatch.call('resize', photoviewer, setPhotoDimensions);
94898             }
94899           };
94900
94901           return utilRebind(photoviewer, dispatch, 'on');
94902         }
94903
94904         function uiRestore(context) {
94905           return function (selection) {
94906             if (!context.history().hasRestorableChanges()) return;
94907             var modalSelection = uiModal(selection, true);
94908             modalSelection.select('.modal').attr('class', 'modal fillL');
94909             var introModal = modalSelection.select('.content');
94910             introModal.append('div').attr('class', 'modal-section').append('h3').call(_t.append('restore.heading'));
94911             introModal.append('div').attr('class', 'modal-section').append('p').call(_t.append('restore.description'));
94912             var buttonWrap = introModal.append('div').attr('class', 'modal-actions');
94913             var restore = buttonWrap.append('button').attr('class', 'restore').on('click', function () {
94914               context.history().restore();
94915               modalSelection.remove();
94916             });
94917             restore.append('svg').attr('class', 'logo logo-restore').append('use').attr('xlink:href', '#iD-logo-restore');
94918             restore.append('div').call(_t.append('restore.restore'));
94919             var reset = buttonWrap.append('button').attr('class', 'reset').on('click', function () {
94920               context.history().clearSaved();
94921               modalSelection.remove();
94922             });
94923             reset.append('svg').attr('class', 'logo logo-reset').append('use').attr('xlink:href', '#iD-logo-reset');
94924             reset.append('div').call(_t.append('restore.reset'));
94925             restore.node().focus();
94926           };
94927         }
94928
94929         function uiScale(context) {
94930           var projection = context.projection,
94931               isImperial = !_mainLocalizer.usesMetric(),
94932               maxLength = 180,
94933               tickHeight = 8;
94934
94935           function scaleDefs(loc1, loc2) {
94936             var lat = (loc2[1] + loc1[1]) / 2,
94937                 conversion = isImperial ? 3.28084 : 1,
94938                 dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
94939                 scale = {
94940               dist: 0,
94941               px: 0,
94942               text: ''
94943             },
94944                 buckets,
94945                 i,
94946                 val,
94947                 dLon;
94948
94949             if (isImperial) {
94950               buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
94951             } else {
94952               buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
94953             } // determine a user-friendly endpoint for the scale
94954
94955
94956             for (i = 0; i < buckets.length; i++) {
94957               val = buckets[i];
94958
94959               if (dist >= val) {
94960                 scale.dist = Math.floor(dist / val) * val;
94961                 break;
94962               } else {
94963                 scale.dist = +dist.toFixed(2);
94964               }
94965             }
94966
94967             dLon = geoMetersToLon(scale.dist / conversion, lat);
94968             scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
94969             scale.text = displayLength(scale.dist / conversion, isImperial);
94970             return scale;
94971           }
94972
94973           function update(selection) {
94974             // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
94975             var dims = context.map().dimensions(),
94976                 loc1 = projection.invert([0, dims[1]]),
94977                 loc2 = projection.invert([maxLength, dims[1]]),
94978                 scale = scaleDefs(loc1, loc2);
94979             selection.select('.scale-path').attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
94980             selection.select('.scale-text').style(_mainLocalizer.textDirection() === 'ltr' ? 'left' : 'right', scale.px + 16 + 'px').text(scale.text);
94981           }
94982
94983           return function (selection) {
94984             function switchUnits() {
94985               isImperial = !isImperial;
94986               selection.call(update);
94987             }
94988
94989             var scalegroup = selection.append('svg').attr('class', 'scale').on('click', switchUnits).append('g').attr('transform', 'translate(10,11)');
94990             scalegroup.append('path').attr('class', 'scale-path');
94991             selection.append('div').attr('class', 'scale-text');
94992             selection.call(update);
94993             context.map().on('move.scale', function () {
94994               update(selection);
94995             });
94996           };
94997         }
94998
94999         function uiShortcuts(context) {
95000           var detected = utilDetect();
95001           var _activeTab = 0;
95002
95003           var _modalSelection;
95004
95005           var _selection = select(null);
95006
95007           var _dataShortcuts;
95008
95009           function shortcutsModal(_modalSelection) {
95010             _modalSelection.select('.modal').classed('modal-shortcuts', true);
95011
95012             var content = _modalSelection.select('.content');
95013
95014             content.append('div').attr('class', 'modal-section header').append('h2').call(_t.append('shortcuts.title'));
95015             _mainFileFetcher.get('shortcuts').then(function (data) {
95016               _dataShortcuts = data;
95017               content.call(render);
95018             })["catch"](function () {
95019               /* ignore */
95020             });
95021           }
95022
95023           function render(selection) {
95024             if (!_dataShortcuts) return;
95025             var wrapper = selection.selectAll('.wrapper').data([0]);
95026             var wrapperEnter = wrapper.enter().append('div').attr('class', 'wrapper modal-section');
95027             var tabsBar = wrapperEnter.append('div').attr('class', 'tabs-bar');
95028             var shortcutsList = wrapperEnter.append('div').attr('class', 'shortcuts-list');
95029             wrapper = wrapper.merge(wrapperEnter);
95030             var tabs = tabsBar.selectAll('.tab').data(_dataShortcuts);
95031             var tabsEnter = tabs.enter().append('a').attr('class', 'tab').attr('href', '#').on('click', function (d3_event, d) {
95032               d3_event.preventDefault();
95033
95034               var i = _dataShortcuts.indexOf(d);
95035
95036               _activeTab = i;
95037               render(selection);
95038             });
95039             tabsEnter.append('span').html(function (d) {
95040               return _t.html(d.text);
95041             }); // Update
95042
95043             wrapper.selectAll('.tab').classed('active', function (d, i) {
95044               return i === _activeTab;
95045             });
95046             var shortcuts = shortcutsList.selectAll('.shortcut-tab').data(_dataShortcuts);
95047             var shortcutsEnter = shortcuts.enter().append('div').attr('class', function (d) {
95048               return 'shortcut-tab shortcut-tab-' + d.tab;
95049             });
95050             var columnsEnter = shortcutsEnter.selectAll('.shortcut-column').data(function (d) {
95051               return d.columns;
95052             }).enter().append('table').attr('class', 'shortcut-column');
95053             var rowsEnter = columnsEnter.selectAll('.shortcut-row').data(function (d) {
95054               return d.rows;
95055             }).enter().append('tr').attr('class', 'shortcut-row');
95056             var sectionRows = rowsEnter.filter(function (d) {
95057               return !d.shortcuts;
95058             });
95059             sectionRows.append('td');
95060             sectionRows.append('td').attr('class', 'shortcut-section').append('h3').html(function (d) {
95061               return _t.html(d.text);
95062             });
95063             var shortcutRows = rowsEnter.filter(function (d) {
95064               return d.shortcuts;
95065             });
95066             var shortcutKeys = shortcutRows.append('td').attr('class', 'shortcut-keys');
95067             var modifierKeys = shortcutKeys.filter(function (d) {
95068               return d.modifiers;
95069             });
95070             modifierKeys.selectAll('kbd.modifier').data(function (d) {
95071               if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') {
95072                 return ['⌘'];
95073               } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') {
95074                 return [];
95075               } else {
95076                 return d.modifiers;
95077               }
95078             }).enter().each(function () {
95079               var selection = select(this);
95080               selection.append('kbd').attr('class', 'modifier').text(function (d) {
95081                 return uiCmd.display(d);
95082               });
95083               selection.append('span').text('+');
95084             });
95085             shortcutKeys.selectAll('kbd.shortcut').data(function (d) {
95086               var arr = d.shortcuts;
95087
95088               if (detected.os === 'win' && d.text === 'shortcuts.editing.commands.redo') {
95089                 arr = ['Y'];
95090               } else if (detected.os !== 'mac' && d.text === 'shortcuts.browsing.display_options.fullscreen') {
95091                 arr = ['F11'];
95092               } // replace translations
95093
95094
95095               arr = arr.map(function (s) {
95096                 return uiCmd.display(s.indexOf('.') !== -1 ? _t(s) : s);
95097               });
95098               return utilArrayUniq(arr).map(function (s) {
95099                 return {
95100                   shortcut: s,
95101                   separator: d.separator,
95102                   suffix: d.suffix
95103                 };
95104               });
95105             }).enter().each(function (d, i, nodes) {
95106               var selection = select(this);
95107               var click = d.shortcut.toLowerCase().match(/(.*).click/);
95108
95109               if (click && click[1]) {
95110                 // replace "left_click", "right_click" with mouse icon
95111                 selection.call(svgIcon('#iD-walkthrough-mouse-' + click[1], 'operation'));
95112               } else if (d.shortcut.toLowerCase() === 'long-press') {
95113                 selection.call(svgIcon('#iD-walkthrough-longpress', 'longpress operation'));
95114               } else if (d.shortcut.toLowerCase() === 'tap') {
95115                 selection.call(svgIcon('#iD-walkthrough-tap', 'tap operation'));
95116               } else {
95117                 selection.append('kbd').attr('class', 'shortcut').text(function (d) {
95118                   return d.shortcut;
95119                 });
95120               }
95121
95122               if (i < nodes.length - 1) {
95123                 selection.append('span').html(d.separator || "\xA0" + _t.html('shortcuts.or') + "\xA0");
95124               } else if (i === nodes.length - 1 && d.suffix) {
95125                 selection.append('span').text(d.suffix);
95126               }
95127             });
95128             shortcutKeys.filter(function (d) {
95129               return d.gesture;
95130             }).each(function () {
95131               var selection = select(this);
95132               selection.append('span').text('+');
95133               selection.append('span').attr('class', 'gesture').html(function (d) {
95134                 return _t.html(d.gesture);
95135               });
95136             });
95137             shortcutRows.append('td').attr('class', 'shortcut-desc').html(function (d) {
95138               return d.text ? _t.html(d.text) : "\xA0";
95139             }); // Update
95140
95141             wrapper.selectAll('.shortcut-tab').style('display', function (d, i) {
95142               return i === _activeTab ? 'flex' : 'none';
95143             });
95144           }
95145
95146           return function (selection, show) {
95147             _selection = selection;
95148
95149             if (show) {
95150               _modalSelection = uiModal(selection);
95151
95152               _modalSelection.call(shortcutsModal);
95153             } else {
95154               context.keybinding().on([_t('shortcuts.toggle.key'), '?'], function () {
95155                 if (context.container().selectAll('.modal-shortcuts').size()) {
95156                   // already showing
95157                   if (_modalSelection) {
95158                     _modalSelection.close();
95159
95160                     _modalSelection = null;
95161                   }
95162                 } else {
95163                   _modalSelection = uiModal(_selection);
95164
95165                   _modalSelection.call(shortcutsModal);
95166                 }
95167               });
95168             }
95169           };
95170         }
95171
95172         function uiDataHeader() {
95173           var _datum;
95174
95175           function dataHeader(selection) {
95176             var header = selection.selectAll('.data-header').data(_datum ? [_datum] : [], function (d) {
95177               return d.__featurehash__;
95178             });
95179             header.exit().remove();
95180             var headerEnter = header.enter().append('div').attr('class', 'data-header');
95181             var iconEnter = headerEnter.append('div').attr('class', 'data-header-icon');
95182             iconEnter.append('div').attr('class', 'preset-icon-28').call(svgIcon('#iD-icon-data', 'note-fill'));
95183             headerEnter.append('div').attr('class', 'data-header-label').call(_t.append('map_data.layers.custom.title'));
95184           }
95185
95186           dataHeader.datum = function (val) {
95187             if (!arguments.length) return _datum;
95188             _datum = val;
95189             return this;
95190           };
95191
95192           return dataHeader;
95193         }
95194
95195         // It is keyed on the `value` of the entry. Data should be an array of objects like:
95196         //   [{
95197         //       value:   'string value',  // required
95198         //       display: 'label html'     // optional
95199         //       title:   'hover text'     // optional
95200         //       terms:   ['search terms'] // optional
95201         //   }, ...]
95202
95203         var _comboHideTimerID;
95204
95205         function uiCombobox(context, klass) {
95206           var dispatch = dispatch$8('accept', 'cancel');
95207           var container = context.container();
95208           var _suggestions = [];
95209           var _data = [];
95210           var _fetched = {};
95211           var _selected = null;
95212           var _canAutocomplete = true;
95213           var _caseSensitive = false;
95214           var _cancelFetch = false;
95215           var _minItems = 2;
95216           var _tDown = 0;
95217
95218           var _mouseEnterHandler, _mouseLeaveHandler;
95219
95220           var _fetcher = function _fetcher(val, cb) {
95221             cb(_data.filter(function (d) {
95222               var terms = d.terms || [];
95223               terms.push(d.value);
95224               return terms.some(function (term) {
95225                 return term.toString().toLowerCase().indexOf(val.toLowerCase()) !== -1;
95226               });
95227             }));
95228           };
95229
95230           var combobox = function combobox(input, attachTo) {
95231             if (!input || input.empty()) return;
95232             input.classed('combobox-input', true).on('focus.combo-input', focus).on('blur.combo-input', blur).on('keydown.combo-input', keydown).on('keyup.combo-input', keyup).on('input.combo-input', change).on('mousedown.combo-input', mousedown).each(function () {
95233               var parent = this.parentNode;
95234               var sibling = this.nextSibling;
95235               select(parent).selectAll('.combobox-caret').filter(function (d) {
95236                 return d === input.node();
95237               }).data([input.node()]).enter().insert('div', function () {
95238                 return sibling;
95239               }).attr('class', 'combobox-caret').on('mousedown.combo-caret', function (d3_event) {
95240                 d3_event.preventDefault(); // don't steal focus from input
95241
95242                 input.node().focus(); // focus the input as if it was clicked
95243
95244                 mousedown(d3_event);
95245               }).on('mouseup.combo-caret', function (d3_event) {
95246                 d3_event.preventDefault(); // don't steal focus from input
95247
95248                 mouseup(d3_event);
95249               });
95250             });
95251
95252             function mousedown(d3_event) {
95253               if (d3_event.button !== 0) return; // left click only
95254
95255               if (input.classed('disabled')) return;
95256               _tDown = +new Date(); // clear selection
95257
95258               var start = input.property('selectionStart');
95259               var end = input.property('selectionEnd');
95260
95261               if (start !== end) {
95262                 var val = utilGetSetValue(input);
95263                 input.node().setSelectionRange(val.length, val.length);
95264                 return;
95265               }
95266
95267               input.on('mouseup.combo-input', mouseup);
95268             }
95269
95270             function mouseup(d3_event) {
95271               input.on('mouseup.combo-input', null);
95272               if (d3_event.button !== 0) return; // left click only
95273
95274               if (input.classed('disabled')) return;
95275               if (input.node() !== document.activeElement) return; // exit if this input is not focused
95276
95277               var start = input.property('selectionStart');
95278               var end = input.property('selectionEnd');
95279               if (start !== end) return; // exit if user is selecting
95280               // not showing or showing for a different field - try to show it.
95281
95282               var combo = container.selectAll('.combobox');
95283
95284               if (combo.empty() || combo.datum() !== input.node()) {
95285                 var tOrig = _tDown;
95286                 window.setTimeout(function () {
95287                   if (tOrig !== _tDown) return; // exit if user double clicked
95288
95289                   fetchComboData('', function () {
95290                     show();
95291                     render();
95292                   });
95293                 }, 250);
95294               } else {
95295                 hide();
95296               }
95297             }
95298
95299             function focus() {
95300               fetchComboData(''); // prefetch values (may warm taginfo cache)
95301             }
95302
95303             function blur() {
95304               _comboHideTimerID = window.setTimeout(hide, 75);
95305             }
95306
95307             function show() {
95308               hide(); // remove any existing
95309
95310               container.insert('div', ':first-child').datum(input.node()).attr('class', 'combobox' + (klass ? ' combobox-' + klass : '')).style('position', 'absolute').style('display', 'block').style('left', '0px').on('mousedown.combo-container', function (d3_event) {
95311                 // prevent moving focus out of the input field
95312                 d3_event.preventDefault();
95313               });
95314               container.on('scroll.combo-scroll', render, true);
95315             }
95316
95317             function hide() {
95318               if (_comboHideTimerID) {
95319                 window.clearTimeout(_comboHideTimerID);
95320                 _comboHideTimerID = undefined;
95321               }
95322
95323               container.selectAll('.combobox').remove();
95324               container.on('scroll.combo-scroll', null);
95325             }
95326
95327             function keydown(d3_event) {
95328               var shown = !container.selectAll('.combobox').empty();
95329               var tagName = input.node() ? input.node().tagName.toLowerCase() : '';
95330
95331               switch (d3_event.keyCode) {
95332                 case 8: // ⌫ Backspace
95333
95334                 case 46:
95335                   // ⌦ Delete
95336                   d3_event.stopPropagation();
95337                   _selected = null;
95338                   render();
95339                   input.on('input.combo-input', function () {
95340                     var start = input.property('selectionStart');
95341                     input.node().setSelectionRange(start, start);
95342                     input.on('input.combo-input', change);
95343                   });
95344                   break;
95345
95346                 case 9:
95347                   // ⇥ Tab
95348                   accept();
95349                   break;
95350
95351                 case 13:
95352                   // ↩ Return
95353                   d3_event.preventDefault();
95354                   d3_event.stopPropagation();
95355                   break;
95356
95357                 case 38:
95358                   // ↑ Up arrow
95359                   if (tagName === 'textarea' && !shown) return;
95360                   d3_event.preventDefault();
95361
95362                   if (tagName === 'input' && !shown) {
95363                     show();
95364                   }
95365
95366                   nav(-1);
95367                   break;
95368
95369                 case 40:
95370                   // ↓ Down arrow
95371                   if (tagName === 'textarea' && !shown) return;
95372                   d3_event.preventDefault();
95373
95374                   if (tagName === 'input' && !shown) {
95375                     show();
95376                   }
95377
95378                   nav(+1);
95379                   break;
95380               }
95381             }
95382
95383             function keyup(d3_event) {
95384               switch (d3_event.keyCode) {
95385                 case 27:
95386                   // ⎋ Escape
95387                   cancel();
95388                   break;
95389
95390                 case 13:
95391                   // ↩ Return
95392                   accept();
95393                   break;
95394               }
95395             } // Called whenever the input value is changed (e.g. on typing)
95396
95397
95398             function change() {
95399               fetchComboData(value(), function () {
95400                 _selected = null;
95401                 var val = input.property('value');
95402
95403                 if (_suggestions.length) {
95404                   if (input.property('selectionEnd') === val.length) {
95405                     _selected = tryAutocomplete();
95406                   }
95407
95408                   if (!_selected) {
95409                     _selected = val;
95410                   }
95411                 }
95412
95413                 if (val.length) {
95414                   var combo = container.selectAll('.combobox');
95415
95416                   if (combo.empty()) {
95417                     show();
95418                   }
95419                 } else {
95420                   hide();
95421                 }
95422
95423                 render();
95424               });
95425             } // Called when the user presses up/down arrows to navigate the list
95426
95427
95428             function nav(dir) {
95429               if (_suggestions.length) {
95430                 // try to determine previously selected index..
95431                 var index = -1;
95432
95433                 for (var i = 0; i < _suggestions.length; i++) {
95434                   if (_selected && _suggestions[i].value === _selected) {
95435                     index = i;
95436                     break;
95437                   }
95438                 } // pick new _selected
95439
95440
95441                 index = Math.max(Math.min(index + dir, _suggestions.length - 1), 0);
95442                 _selected = _suggestions[index].value;
95443                 input.property('value', _selected);
95444               }
95445
95446               render();
95447               ensureVisible();
95448             }
95449
95450             function ensureVisible() {
95451               var combo = container.selectAll('.combobox');
95452               if (combo.empty()) return;
95453               var containerRect = container.node().getBoundingClientRect();
95454               var comboRect = combo.node().getBoundingClientRect();
95455
95456               if (comboRect.bottom > containerRect.bottom) {
95457                 var node = attachTo ? attachTo.node() : input.node();
95458                 node.scrollIntoView({
95459                   behavior: 'instant',
95460                   block: 'center'
95461                 });
95462                 render();
95463               } // https://stackoverflow.com/questions/11039885/scrollintoview-causing-the-whole-page-to-move
95464
95465
95466               var selected = combo.selectAll('.combobox-option.selected').node();
95467
95468               if (selected) {
95469                 selected.scrollIntoView({
95470                   behavior: 'smooth',
95471                   block: 'nearest'
95472                 });
95473               }
95474             }
95475
95476             function value() {
95477               var value = input.property('value');
95478               var start = input.property('selectionStart');
95479               var end = input.property('selectionEnd');
95480
95481               if (start && end) {
95482                 value = value.substring(0, start);
95483               }
95484
95485               return value;
95486             }
95487
95488             function fetchComboData(v, cb) {
95489               _cancelFetch = false;
95490
95491               _fetcher.call(input, v, function (results) {
95492                 // already chose a value, don't overwrite or autocomplete it
95493                 if (_cancelFetch) return;
95494                 _suggestions = results;
95495                 results.forEach(function (d) {
95496                   _fetched[d.value] = d;
95497                 });
95498
95499                 if (cb) {
95500                   cb();
95501                 }
95502               });
95503             }
95504
95505             function tryAutocomplete() {
95506               if (!_canAutocomplete) return;
95507               var val = _caseSensitive ? value() : value().toLowerCase();
95508               if (!val) return; // Don't autocomplete if user is typing a number - #4935
95509
95510               if (!isNaN(parseFloat(val)) && isFinite(val)) return;
95511               var bestIndex = -1;
95512
95513               for (var i = 0; i < _suggestions.length; i++) {
95514                 var suggestion = _suggestions[i].value;
95515                 var compare = _caseSensitive ? suggestion : suggestion.toLowerCase(); // if search string matches suggestion exactly, pick it..
95516
95517                 if (compare === val) {
95518                   bestIndex = i;
95519                   break; // otherwise lock in the first result that starts with the search string..
95520                 } else if (bestIndex === -1 && compare.indexOf(val) === 0) {
95521                   bestIndex = i;
95522                 }
95523               }
95524
95525               if (bestIndex !== -1) {
95526                 var bestVal = _suggestions[bestIndex].value;
95527                 input.property('value', bestVal);
95528                 input.node().setSelectionRange(val.length, bestVal.length);
95529                 return bestVal;
95530               }
95531             }
95532
95533             function render() {
95534               if (_suggestions.length < _minItems || document.activeElement !== input.node()) {
95535                 hide();
95536                 return;
95537               }
95538
95539               var shown = !container.selectAll('.combobox').empty();
95540               if (!shown) return;
95541               var combo = container.selectAll('.combobox');
95542               var options = combo.selectAll('.combobox-option').data(_suggestions, function (d) {
95543                 return d.value;
95544               });
95545               options.exit().remove(); // enter/update
95546
95547               options.enter().append('a').attr('class', function (d) {
95548                 return 'combobox-option ' + (d.klass || '');
95549               }).attr('title', function (d) {
95550                 return d.title;
95551               }).html(function (d) {
95552                 return d.display || d.value;
95553               }).on('mouseenter', _mouseEnterHandler).on('mouseleave', _mouseLeaveHandler).merge(options).classed('selected', function (d) {
95554                 return d.value === _selected;
95555               }).on('click.combo-option', accept).order();
95556               var node = attachTo ? attachTo.node() : input.node();
95557               var containerRect = container.node().getBoundingClientRect();
95558               var rect = node.getBoundingClientRect();
95559               combo.style('left', rect.left + 5 - containerRect.left + 'px').style('width', rect.width - 10 + 'px').style('top', rect.height + rect.top - containerRect.top + 'px');
95560             } // Dispatches an 'accept' event
95561             // Then hides the combobox.
95562
95563
95564             function accept(d3_event, d) {
95565               _cancelFetch = true;
95566               var thiz = input.node();
95567
95568               if (d) {
95569                 // user clicked on a suggestion
95570                 utilGetSetValue(input, d.value); // replace field contents
95571
95572                 utilTriggerEvent(input, 'change');
95573               } // clear (and keep) selection
95574
95575
95576               var val = utilGetSetValue(input);
95577               thiz.setSelectionRange(val.length, val.length);
95578               d = _fetched[val];
95579               dispatch.call('accept', thiz, d, val);
95580               hide();
95581             } // Dispatches an 'cancel' event
95582             // Then hides the combobox.
95583
95584
95585             function cancel() {
95586               _cancelFetch = true;
95587               var thiz = input.node(); // clear (and remove) selection, and replace field contents
95588
95589               var val = utilGetSetValue(input);
95590               var start = input.property('selectionStart');
95591               var end = input.property('selectionEnd');
95592               val = val.slice(0, start) + val.slice(end);
95593               utilGetSetValue(input, val);
95594               thiz.setSelectionRange(val.length, val.length);
95595               dispatch.call('cancel', thiz);
95596               hide();
95597             }
95598           };
95599
95600           combobox.canAutocomplete = function (val) {
95601             if (!arguments.length) return _canAutocomplete;
95602             _canAutocomplete = val;
95603             return combobox;
95604           };
95605
95606           combobox.caseSensitive = function (val) {
95607             if (!arguments.length) return _caseSensitive;
95608             _caseSensitive = val;
95609             return combobox;
95610           };
95611
95612           combobox.data = function (val) {
95613             if (!arguments.length) return _data;
95614             _data = val;
95615             return combobox;
95616           };
95617
95618           combobox.fetcher = function (val) {
95619             if (!arguments.length) return _fetcher;
95620             _fetcher = val;
95621             return combobox;
95622           };
95623
95624           combobox.minItems = function (val) {
95625             if (!arguments.length) return _minItems;
95626             _minItems = val;
95627             return combobox;
95628           };
95629
95630           combobox.itemsMouseEnter = function (val) {
95631             if (!arguments.length) return _mouseEnterHandler;
95632             _mouseEnterHandler = val;
95633             return combobox;
95634           };
95635
95636           combobox.itemsMouseLeave = function (val) {
95637             if (!arguments.length) return _mouseLeaveHandler;
95638             _mouseLeaveHandler = val;
95639             return combobox;
95640           };
95641
95642           return utilRebind(combobox, dispatch, 'on');
95643         }
95644
95645         uiCombobox.off = function (input, context) {
95646           input.on('focus.combo-input', null).on('blur.combo-input', null).on('keydown.combo-input', null).on('keyup.combo-input', null).on('input.combo-input', null).on('mousedown.combo-input', null).on('mouseup.combo-input', null);
95647           context.container().on('scroll.combo-scroll', null);
95648         };
95649
95650         function uiDisclosure(context, key, expandedDefault) {
95651           var dispatch = dispatch$8('toggled');
95652
95653           var _expanded;
95654
95655           var _label = utilFunctor('');
95656
95657           var _updatePreference = true;
95658
95659           var _content = function _content() {};
95660
95661           var disclosure = function disclosure(selection) {
95662             if (_expanded === undefined || _expanded === null) {
95663               // loading _expanded here allows it to be reset by calling `disclosure.expanded(null)`
95664               var preference = corePreferences('disclosure.' + key + '.expanded');
95665               _expanded = preference === null ? !!expandedDefault : preference === 'true';
95666             }
95667
95668             var hideToggle = selection.selectAll('.hide-toggle-' + key).data([0]); // enter
95669
95670             var hideToggleEnter = hideToggle.enter().append('h3').append('a').attr('role', 'button').attr('href', '#').attr('class', 'hide-toggle hide-toggle-' + key).call(svgIcon('', 'pre-text', 'hide-toggle-icon'));
95671             hideToggleEnter.append('span').attr('class', 'hide-toggle-text'); // update
95672
95673             hideToggle = hideToggleEnter.merge(hideToggle);
95674             hideToggle.on('click', toggle).attr('title', _t("icons.".concat(_expanded ? 'collapse' : 'expand'))).attr('aria-expanded', _expanded).classed('expanded', _expanded);
95675             hideToggle.selectAll('.hide-toggle-text').html(_label());
95676             hideToggle.selectAll('.hide-toggle-icon').attr('xlink:href', _expanded ? '#iD-icon-down' : _mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward');
95677             var wrap = selection.selectAll('.disclosure-wrap').data([0]); // enter/update
95678
95679             wrap = wrap.enter().append('div').attr('class', 'disclosure-wrap disclosure-wrap-' + key).merge(wrap).classed('hide', !_expanded);
95680
95681             if (_expanded) {
95682               wrap.call(_content);
95683             }
95684
95685             function toggle(d3_event) {
95686               d3_event.preventDefault();
95687               _expanded = !_expanded;
95688
95689               if (_updatePreference) {
95690                 corePreferences('disclosure.' + key + '.expanded', _expanded);
95691               }
95692
95693               hideToggle.classed('expanded', _expanded).attr('aria-expanded', _expanded).attr('title', _t("icons.".concat(_expanded ? 'collapse' : 'expand')));
95694               hideToggle.selectAll('.hide-toggle-icon').attr('xlink:href', _expanded ? '#iD-icon-down' : _mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward');
95695               wrap.call(uiToggle(_expanded));
95696
95697               if (_expanded) {
95698                 wrap.call(_content);
95699               }
95700
95701               dispatch.call('toggled', this, _expanded);
95702             }
95703           };
95704
95705           disclosure.label = function (val) {
95706             if (!arguments.length) return _label;
95707             _label = utilFunctor(val);
95708             return disclosure;
95709           };
95710
95711           disclosure.expanded = function (val) {
95712             if (!arguments.length) return _expanded;
95713             _expanded = val;
95714             return disclosure;
95715           };
95716
95717           disclosure.updatePreference = function (val) {
95718             if (!arguments.length) return _updatePreference;
95719             _updatePreference = val;
95720             return disclosure;
95721           };
95722
95723           disclosure.content = function (val) {
95724             if (!arguments.length) return _content;
95725             _content = val;
95726             return disclosure;
95727           };
95728
95729           return utilRebind(disclosure, dispatch, 'on');
95730         }
95731
95732         // Can be labeled and collapsible.
95733
95734         function uiSection(id, context) {
95735           var _classes = utilFunctor('');
95736
95737           var _shouldDisplay;
95738
95739           var _content;
95740
95741           var _disclosure;
95742
95743           var _label;
95744
95745           var _expandedByDefault = utilFunctor(true);
95746
95747           var _disclosureContent;
95748
95749           var _disclosureExpanded;
95750
95751           var _containerSelection = select(null);
95752
95753           var section = {
95754             id: id
95755           };
95756
95757           section.classes = function (val) {
95758             if (!arguments.length) return _classes;
95759             _classes = utilFunctor(val);
95760             return section;
95761           };
95762
95763           section.label = function (val) {
95764             if (!arguments.length) return _label;
95765             _label = utilFunctor(val);
95766             return section;
95767           };
95768
95769           section.expandedByDefault = function (val) {
95770             if (!arguments.length) return _expandedByDefault;
95771             _expandedByDefault = utilFunctor(val);
95772             return section;
95773           };
95774
95775           section.shouldDisplay = function (val) {
95776             if (!arguments.length) return _shouldDisplay;
95777             _shouldDisplay = utilFunctor(val);
95778             return section;
95779           };
95780
95781           section.content = function (val) {
95782             if (!arguments.length) return _content;
95783             _content = val;
95784             return section;
95785           };
95786
95787           section.disclosureContent = function (val) {
95788             if (!arguments.length) return _disclosureContent;
95789             _disclosureContent = val;
95790             return section;
95791           };
95792
95793           section.disclosureExpanded = function (val) {
95794             if (!arguments.length) return _disclosureExpanded;
95795             _disclosureExpanded = val;
95796             return section;
95797           }; // may be called multiple times
95798
95799
95800           section.render = function (selection) {
95801             _containerSelection = selection.selectAll('.section-' + id).data([0]);
95802
95803             var sectionEnter = _containerSelection.enter().append('div').attr('class', 'section section-' + id + ' ' + (_classes && _classes() || ''));
95804
95805             _containerSelection = sectionEnter.merge(_containerSelection);
95806
95807             _containerSelection.call(renderContent);
95808           };
95809
95810           section.reRender = function () {
95811             _containerSelection.call(renderContent);
95812           };
95813
95814           section.selection = function () {
95815             return _containerSelection;
95816           };
95817
95818           section.disclosure = function () {
95819             return _disclosure;
95820           }; // may be called multiple times
95821
95822
95823           function renderContent(selection) {
95824             if (_shouldDisplay) {
95825               var shouldDisplay = _shouldDisplay();
95826
95827               selection.classed('hide', !shouldDisplay);
95828
95829               if (!shouldDisplay) {
95830                 selection.html('');
95831                 return;
95832               }
95833             }
95834
95835             if (_disclosureContent) {
95836               if (!_disclosure) {
95837                 _disclosure = uiDisclosure(context, id.replace(/-/g, '_'), _expandedByDefault()).label(_label || '')
95838                 /*.on('toggled', function(expanded) {
95839                     if (expanded) { selection.node().parentNode.scrollTop += 200; }
95840                 })*/
95841                 .content(_disclosureContent);
95842               }
95843
95844               if (_disclosureExpanded !== undefined) {
95845                 _disclosure.expanded(_disclosureExpanded);
95846
95847                 _disclosureExpanded = undefined;
95848               }
95849
95850               selection.call(_disclosure);
95851               return;
95852             }
95853
95854             if (_content) {
95855               selection.call(_content);
95856             }
95857           }
95858
95859           return section;
95860         }
95861
95862         // {
95863         //   key: 'string',     // required
95864         //   value: 'string'    // optional
95865         // }
95866         //   -or-
95867         // {
95868         //   qid: 'string'      // brand wikidata  (e.g. 'Q37158')
95869         // }
95870         //
95871
95872         function uiTagReference(what) {
95873           var wikibase = what.qid ? services.wikidata : services.osmWikibase;
95874           var tagReference = {};
95875
95876           var _button = select(null);
95877
95878           var _body = select(null);
95879
95880           var _loaded;
95881
95882           var _showing;
95883
95884           function load() {
95885             if (!wikibase) return;
95886
95887             _button.classed('tag-reference-loading', true);
95888
95889             wikibase.getDocs(what, gotDocs);
95890           }
95891
95892           function gotDocs(err, docs) {
95893             _body.html('');
95894
95895             if (!docs || !docs.title) {
95896               _body.append('p').attr('class', 'tag-reference-description').call(_t.append('inspector.no_documentation_key'));
95897
95898               done();
95899               return;
95900             }
95901
95902             if (docs.imageURL) {
95903               _body.append('img').attr('class', 'tag-reference-wiki-image').attr('alt', docs.description).attr('src', docs.imageURL).on('load', function () {
95904                 done();
95905               }).on('error', function () {
95906                 select(this).remove();
95907                 done();
95908               });
95909             } else {
95910               done();
95911             }
95912
95913             var tagReferenceDescription = _body.append('p').attr('class', 'tag-reference-description').append('span');
95914
95915             if (docs.description) {
95916               tagReferenceDescription = tagReferenceDescription.attr('class', 'localized-text').attr('lang', docs.descriptionLocaleCode || 'und').text(docs.description);
95917             } else {
95918               tagReferenceDescription = tagReferenceDescription.call(_t.append('inspector.no_documentation_key'));
95919             }
95920
95921             tagReferenceDescription.append('a').attr('class', 'tag-reference-edit').attr('target', '_blank').attr('title', _t('inspector.edit_reference')).attr('href', docs.editURL).call(svgIcon('#iD-icon-edit', 'inline'));
95922
95923             if (docs.wiki) {
95924               _body.append('a').attr('class', 'tag-reference-link').attr('target', '_blank').attr('href', docs.wiki.url).call(svgIcon('#iD-icon-out-link', 'inline')).append('span').call(_t.append(docs.wiki.text));
95925             } // Add link to info about "good changeset comments" - #2923
95926
95927
95928             if (what.key === 'comment') {
95929               _body.append('a').attr('class', 'tag-reference-comment-link').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).attr('href', _t('commit.about_changeset_comments_link')).append('span').call(_t.append('commit.about_changeset_comments'));
95930             }
95931           }
95932
95933           function done() {
95934             _loaded = true;
95935
95936             _button.classed('tag-reference-loading', false);
95937
95938             _body.classed('expanded', true).transition().duration(200).style('max-height', '200px').style('opacity', '1');
95939
95940             _showing = true;
95941
95942             _button.selectAll('svg.icon use').each(function () {
95943               var iconUse = select(this);
95944
95945               if (iconUse.attr('href') === '#iD-icon-info') {
95946                 iconUse.attr('href', '#iD-icon-info-filled');
95947               }
95948             });
95949           }
95950
95951           function hide() {
95952             _body.transition().duration(200).style('max-height', '0px').style('opacity', '0').on('end', function () {
95953               _body.classed('expanded', false);
95954             });
95955
95956             _showing = false;
95957
95958             _button.selectAll('svg.icon use').each(function () {
95959               var iconUse = select(this);
95960
95961               if (iconUse.attr('href') === '#iD-icon-info-filled') {
95962                 iconUse.attr('href', '#iD-icon-info');
95963               }
95964             });
95965           }
95966
95967           tagReference.button = function (selection, klass, iconName) {
95968             _button = selection.selectAll('.tag-reference-button').data([0]);
95969             _button = _button.enter().append('button').attr('class', 'tag-reference-button ' + (klass || '')).attr('title', _t('icons.information')).call(svgIcon('#iD-icon-' + (iconName || 'inspect'))).merge(_button);
95970
95971             _button.on('click', function (d3_event) {
95972               d3_event.stopPropagation();
95973               d3_event.preventDefault();
95974               this.blur(); // avoid keeping focus on the button - #4641
95975
95976               if (_showing) {
95977                 hide();
95978               } else if (_loaded) {
95979                 done();
95980               } else {
95981                 load();
95982               }
95983             });
95984           };
95985
95986           tagReference.body = function (selection) {
95987             var itemID = what.qid || what.key + '-' + (what.value || '');
95988             _body = selection.selectAll('.tag-reference-body').data([itemID], function (d) {
95989               return d;
95990             });
95991
95992             _body.exit().remove();
95993
95994             _body = _body.enter().append('div').attr('class', 'tag-reference-body').style('max-height', '0').style('opacity', '0').merge(_body);
95995
95996             if (_showing === false) {
95997               hide();
95998             }
95999           };
96000
96001           tagReference.showing = function (val) {
96002             if (!arguments.length) return _showing;
96003             _showing = val;
96004             return tagReference;
96005           };
96006
96007           return tagReference;
96008         }
96009
96010         // It borrows some code from uiHelp
96011
96012         function uiFieldHelp(context, fieldName) {
96013           var fieldHelp = {};
96014
96015           var _inspector = select(null);
96016
96017           var _wrap = select(null);
96018
96019           var _body = select(null);
96020
96021           var fieldHelpKeys = {
96022             restrictions: [['about', ['about', 'from_via_to', 'maxdist', 'maxvia']], ['inspecting', ['about', 'from_shadow', 'allow_shadow', 'restrict_shadow', 'only_shadow', 'restricted', 'only']], ['modifying', ['about', 'indicators', 'allow_turn', 'restrict_turn', 'only_turn']], ['tips', ['simple', 'simple_example', 'indirect', 'indirect_example', 'indirect_noedit']]]
96023           };
96024           var fieldHelpHeadings = {};
96025           var replacements = {
96026             distField: {
96027               html: _t.html('restriction.controls.distance')
96028             },
96029             viaField: {
96030               html: _t.html('restriction.controls.via')
96031             },
96032             fromShadow: {
96033               html: icon('#iD-turn-shadow', 'inline shadow from')
96034             },
96035             allowShadow: {
96036               html: icon('#iD-turn-shadow', 'inline shadow allow')
96037             },
96038             restrictShadow: {
96039               html: icon('#iD-turn-shadow', 'inline shadow restrict')
96040             },
96041             onlyShadow: {
96042               html: icon('#iD-turn-shadow', 'inline shadow only')
96043             },
96044             allowTurn: {
96045               html: icon('#iD-turn-yes', 'inline turn')
96046             },
96047             restrictTurn: {
96048               html: icon('#iD-turn-no', 'inline turn')
96049             },
96050             onlyTurn: {
96051               html: icon('#iD-turn-only', 'inline turn')
96052             }
96053           }; // For each section, squash all the texts into a single markdown document
96054
96055           var docs = fieldHelpKeys[fieldName].map(function (key) {
96056             var helpkey = 'help.field.' + fieldName + '.' + key[0];
96057             var text = key[1].reduce(function (all, part) {
96058               var subkey = helpkey + '.' + part;
96059               var depth = fieldHelpHeadings[subkey]; // is this subkey a heading?
96060
96061               var hhh = depth ? Array(depth + 1).join('#') + ' ' : ''; // if so, prepend with some ##'s
96062
96063               return all + hhh + _t.html(subkey, replacements) + '\n\n';
96064             }, '');
96065             return {
96066               key: helpkey,
96067               title: _t.html(helpkey + '.title'),
96068               html: marked_1(text.trim())
96069             };
96070           });
96071
96072           function show() {
96073             updatePosition();
96074
96075             _body.classed('hide', false).style('opacity', '0').transition().duration(200).style('opacity', '1');
96076           }
96077
96078           function hide() {
96079             _body.classed('hide', true).transition().duration(200).style('opacity', '0').on('end', function () {
96080               _body.classed('hide', true);
96081             });
96082           }
96083
96084           function clickHelp(index) {
96085             var d = docs[index];
96086             var tkeys = fieldHelpKeys[fieldName][index][1];
96087
96088             _body.selectAll('.field-help-nav-item').classed('active', function (d, i) {
96089               return i === index;
96090             });
96091
96092             var content = _body.selectAll('.field-help-content').html(d.html); // class the paragraphs so we can find and style them
96093
96094
96095             content.selectAll('p').attr('class', function (d, i) {
96096               return tkeys[i];
96097             }); // insert special content for certain help sections
96098
96099             if (d.key === 'help.field.restrictions.inspecting') {
96100               content.insert('img', 'p.from_shadow').attr('class', 'field-help-image cf').attr('src', context.imagePath('tr_inspect.gif'));
96101             } else if (d.key === 'help.field.restrictions.modifying') {
96102               content.insert('img', 'p.allow_turn').attr('class', 'field-help-image cf').attr('src', context.imagePath('tr_modify.gif'));
96103             }
96104           }
96105
96106           fieldHelp.button = function (selection) {
96107             if (_body.empty()) return;
96108             var button = selection.selectAll('.field-help-button').data([0]); // enter/update
96109
96110             button.enter().append('button').attr('class', 'field-help-button').call(svgIcon('#iD-icon-help')).merge(button).on('click', function (d3_event) {
96111               d3_event.stopPropagation();
96112               d3_event.preventDefault();
96113
96114               if (_body.classed('hide')) {
96115                 show();
96116               } else {
96117                 hide();
96118               }
96119             });
96120           };
96121
96122           function updatePosition() {
96123             var wrap = _wrap.node();
96124
96125             var inspector = _inspector.node();
96126
96127             var wRect = wrap.getBoundingClientRect();
96128             var iRect = inspector.getBoundingClientRect();
96129
96130             _body.style('top', wRect.top + inspector.scrollTop - iRect.top + 'px');
96131           }
96132
96133           fieldHelp.body = function (selection) {
96134             // This control expects the field to have a form-field-input-wrap div
96135             _wrap = selection.selectAll('.form-field-input-wrap');
96136             if (_wrap.empty()) return; // absolute position relative to the inspector, so it "floats" above the fields
96137
96138             _inspector = context.container().select('.sidebar .entity-editor-pane .inspector-body');
96139             if (_inspector.empty()) return;
96140             _body = _inspector.selectAll('.field-help-body').data([0]);
96141
96142             var enter = _body.enter().append('div').attr('class', 'field-help-body hide'); // initially hidden
96143
96144
96145             var titleEnter = enter.append('div').attr('class', 'field-help-title cf');
96146             titleEnter.append('h2').attr('class', _mainLocalizer.textDirection() === 'rtl' ? 'fr' : 'fl').call(_t.append('help.field.' + fieldName + '.title'));
96147             titleEnter.append('button').attr('class', 'fr close').attr('title', _t('icons.close')).on('click', function (d3_event) {
96148               d3_event.stopPropagation();
96149               d3_event.preventDefault();
96150               hide();
96151             }).call(svgIcon('#iD-icon-close'));
96152             var navEnter = enter.append('div').attr('class', 'field-help-nav cf');
96153             var titles = docs.map(function (d) {
96154               return d.title;
96155             });
96156             navEnter.selectAll('.field-help-nav-item').data(titles).enter().append('div').attr('class', 'field-help-nav-item').html(function (d) {
96157               return d;
96158             }).on('click', function (d3_event, d) {
96159               d3_event.stopPropagation();
96160               d3_event.preventDefault();
96161               clickHelp(titles.indexOf(d));
96162             });
96163             enter.append('div').attr('class', 'field-help-content');
96164             _body = _body.merge(enter);
96165             clickHelp(0);
96166           };
96167
96168           return fieldHelp;
96169         }
96170
96171         function uiFieldCheck(field, context) {
96172           var dispatch = dispatch$8('change');
96173           var options = field.options;
96174           var values = [];
96175           var texts = [];
96176
96177           var _tags;
96178
96179           var input = select(null);
96180           var text = select(null);
96181           var label = select(null);
96182           var reverser = select(null);
96183
96184           var _impliedYes;
96185
96186           var _entityIDs = [];
96187
96188           var _value;
96189
96190           if (options) {
96191             for (var i in options) {
96192               var v = options[i];
96193               values.push(v === 'undefined' ? undefined : v);
96194               texts.push(field.t.html('options.' + v, {
96195                 'default': v
96196               }));
96197             }
96198           } else {
96199             values = [undefined, 'yes'];
96200             texts = [_t.html('inspector.unknown'), _t.html('inspector.check.yes')];
96201
96202             if (field.type !== 'defaultCheck') {
96203               values.push('no');
96204               texts.push(_t.html('inspector.check.no'));
96205             }
96206           } // Checks tags to see whether an undefined value is "Assumed to be Yes"
96207
96208
96209           function checkImpliedYes() {
96210             _impliedYes = field.id === 'oneway_yes'; // hack: pretend `oneway` field is a `oneway_yes` field
96211             // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
96212
96213             if (field.id === 'oneway') {
96214               var entity = context.entity(_entityIDs[0]);
96215
96216               for (var key in entity.tags) {
96217                 if (key in osmOneWayTags && entity.tags[key] in osmOneWayTags[key]) {
96218                   _impliedYes = true;
96219                   texts[0] = _t.html('_tagging.presets.fields.oneway_yes.options.undefined');
96220                   break;
96221                 }
96222               }
96223             }
96224           }
96225
96226           function reverserHidden() {
96227             if (!context.container().select('div.inspector-hover').empty()) return true;
96228             return !(_value === 'yes' || _impliedYes && !_value);
96229           }
96230
96231           function reverserSetText(selection) {
96232             var entity = _entityIDs.length && context.hasEntity(_entityIDs[0]);
96233             if (reverserHidden() || !entity) return selection;
96234             var first = entity.first();
96235             var last = entity.isClosed() ? entity.nodes[entity.nodes.length - 2] : entity.last();
96236             var pseudoDirection = first < last;
96237             var icon = pseudoDirection ? '#iD-icon-forward' : '#iD-icon-backward';
96238             selection.selectAll('.reverser-span').html('').call(_t.append('inspector.check.reverser')).call(svgIcon(icon, 'inline'));
96239             return selection;
96240           }
96241
96242           var check = function check(selection) {
96243             checkImpliedYes();
96244             label = selection.selectAll('.form-field-input-wrap').data([0]);
96245             var enter = label.enter().append('label').attr('class', 'form-field-input-wrap form-field-input-check');
96246             enter.append('input').property('indeterminate', field.type !== 'defaultCheck').attr('type', 'checkbox').attr('id', field.domId);
96247             enter.append('span').html(texts[0]).attr('class', 'value');
96248
96249             if (field.type === 'onewayCheck') {
96250               enter.append('button').attr('class', 'reverser' + (reverserHidden() ? ' hide' : '')).append('span').attr('class', 'reverser-span');
96251             }
96252
96253             label = label.merge(enter);
96254             input = label.selectAll('input');
96255             text = label.selectAll('span.value');
96256             input.on('click', function (d3_event) {
96257               d3_event.stopPropagation();
96258               var t = {};
96259
96260               if (Array.isArray(_tags[field.key])) {
96261                 if (values.indexOf('yes') !== -1) {
96262                   t[field.key] = 'yes';
96263                 } else {
96264                   t[field.key] = values[0];
96265                 }
96266               } else {
96267                 t[field.key] = values[(values.indexOf(_value) + 1) % values.length];
96268               } // Don't cycle through `alternating` or `reversible` states - #4970
96269               // (They are supported as translated strings, but should not toggle with clicks)
96270
96271
96272               if (t[field.key] === 'reversible' || t[field.key] === 'alternating') {
96273                 t[field.key] = values[0];
96274               }
96275
96276               dispatch.call('change', this, t);
96277             });
96278
96279             if (field.type === 'onewayCheck') {
96280               reverser = label.selectAll('.reverser');
96281               reverser.call(reverserSetText).on('click', function (d3_event) {
96282                 d3_event.preventDefault();
96283                 d3_event.stopPropagation();
96284                 context.perform(function (graph) {
96285                   for (var i in _entityIDs) {
96286                     graph = actionReverse(_entityIDs[i])(graph);
96287                   }
96288
96289                   return graph;
96290                 }, _t('operations.reverse.annotation.line', {
96291                   n: 1
96292                 })); // must manually revalidate since no 'change' event was called
96293
96294                 context.validator().validate();
96295                 select(this).call(reverserSetText);
96296               });
96297             }
96298           };
96299
96300           check.entityIDs = function (val) {
96301             if (!arguments.length) return _entityIDs;
96302             _entityIDs = val;
96303             return check;
96304           };
96305
96306           check.tags = function (tags) {
96307             _tags = tags;
96308
96309             function isChecked(val) {
96310               return val !== 'no' && val !== '' && val !== undefined && val !== null;
96311             }
96312
96313             function textFor(val) {
96314               if (val === '') val = undefined;
96315               var index = values.indexOf(val);
96316               return index !== -1 ? texts[index] : '"' + val + '"';
96317             }
96318
96319             checkImpliedYes();
96320             var isMixed = Array.isArray(tags[field.key]);
96321             _value = !isMixed && tags[field.key] && tags[field.key].toLowerCase();
96322
96323             if (field.type === 'onewayCheck' && (_value === '1' || _value === '-1')) {
96324               _value = 'yes';
96325             }
96326
96327             input.property('indeterminate', isMixed || field.type !== 'defaultCheck' && !_value).property('checked', isChecked(_value));
96328             text.html(isMixed ? _t.html('inspector.multiple_values') : textFor(_value)).classed('mixed', isMixed);
96329             label.classed('set', !!_value);
96330
96331             if (field.type === 'onewayCheck') {
96332               reverser.classed('hide', reverserHidden()).call(reverserSetText);
96333             }
96334           };
96335
96336           check.focus = function () {
96337             input.node().focus();
96338           };
96339
96340           return utilRebind(check, dispatch, 'on');
96341         }
96342
96343         function uiFieldCombo(field, context) {
96344           var dispatch = dispatch$8('change');
96345
96346           var _isMulti = field.type === 'multiCombo' || field.type === 'manyCombo';
96347
96348           var _isNetwork = field.type === 'networkCombo';
96349
96350           var _isSemi = field.type === 'semiCombo';
96351
96352           var _optarray = field.options;
96353
96354           var _showTagInfoSuggestions = field.type !== 'manyCombo' && field.autoSuggestions !== false;
96355
96356           var _allowCustomValues = field.type !== 'manyCombo' && field.customValues !== false;
96357
96358           var _snake_case = field.snake_case || field.snake_case === undefined;
96359
96360           var _combobox = uiCombobox(context, 'combo-' + field.safeid).caseSensitive(field.caseSensitive).minItems(_isMulti || _isSemi ? 1 : 2);
96361
96362           var _container = select(null);
96363
96364           var _inputWrap = select(null);
96365
96366           var _input = select(null);
96367
96368           var _comboData = [];
96369           var _multiData = [];
96370           var _entityIDs = [];
96371
96372           var _tags;
96373
96374           var _countryCode;
96375
96376           var _staticPlaceholder; // initialize deprecated tags array
96377
96378
96379           var _dataDeprecated = [];
96380           _mainFileFetcher.get('deprecated').then(function (d) {
96381             _dataDeprecated = d;
96382           })["catch"](function () {
96383             /* ignore */
96384           }); // ensure multiCombo field.key ends with a ':'
96385
96386           if (_isMulti && field.key && /[^:]$/.test(field.key)) {
96387             field.key += ':';
96388           }
96389
96390           function snake(s) {
96391             return s.replace(/\s+/g, '_').toLowerCase();
96392           }
96393
96394           function clean(s) {
96395             return s.split(';').map(function (s) {
96396               return s.trim();
96397             }).join(';');
96398           } // returns the tag value for a display value
96399           // (for multiCombo, dval should be the key suffix, not the entire key)
96400
96401
96402           function tagValue(dval) {
96403             dval = clean(dval || '');
96404
96405             var found = _comboData.find(function (o) {
96406               return o.key && clean(o.value) === dval;
96407             });
96408
96409             if (found) return found.key;
96410
96411             if (field.type === 'typeCombo' && !dval) {
96412               return 'yes';
96413             }
96414
96415             return (_snake_case ? snake(dval) : dval) || undefined;
96416           } // returns the display value for a tag value
96417           // (for multiCombo, tval should be the key suffix, not the entire key)
96418
96419
96420           function displayValue(tval) {
96421             tval = tval || '';
96422
96423             if (field.hasTextForStringId('options.' + tval)) {
96424               return field.t('options.' + tval, {
96425                 "default": tval
96426               });
96427             }
96428
96429             if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
96430               return '';
96431             }
96432
96433             return tval;
96434           } // Compute the difference between arrays of objects by `value` property
96435           //
96436           // objectDifference([{value:1}, {value:2}, {value:3}], [{value:2}])
96437           // > [{value:1}, {value:3}]
96438           //
96439
96440
96441           function objectDifference(a, b) {
96442             return a.filter(function (d1) {
96443               return !b.some(function (d2) {
96444                 return !d2.isMixed && d1.value === d2.value;
96445               });
96446             });
96447           }
96448
96449           function initCombo(selection, attachTo) {
96450             if (!_allowCustomValues) {
96451               selection.attr('readonly', 'readonly');
96452             }
96453
96454             if (_showTagInfoSuggestions && services.taginfo) {
96455               selection.call(_combobox.fetcher(setTaginfoValues), attachTo);
96456               setTaginfoValues('', setPlaceholder);
96457             } else {
96458               selection.call(_combobox, attachTo);
96459               setStaticValues(setPlaceholder);
96460             }
96461           }
96462
96463           function setStaticValues(callback) {
96464             if (!_optarray) return;
96465             _comboData = _optarray.map(function (v) {
96466               return {
96467                 key: v,
96468                 value: field.t('options.' + v, {
96469                   "default": v
96470                 }),
96471                 title: v,
96472                 display: field.t.html('options.' + v, {
96473                   "default": v
96474                 }),
96475                 klass: field.hasTextForStringId('options.' + v) ? '' : 'raw-option'
96476               };
96477             });
96478
96479             _combobox.data(objectDifference(_comboData, _multiData));
96480
96481             if (callback) callback(_comboData);
96482           }
96483
96484           function setTaginfoValues(q, callback) {
96485             var fn = _isMulti ? 'multikeys' : 'values';
96486             var query = (_isMulti ? field.key : '') + q;
96487             var hasCountryPrefix = _isNetwork && _countryCode && _countryCode.indexOf(q.toLowerCase()) === 0;
96488
96489             if (hasCountryPrefix) {
96490               query = _countryCode + ':';
96491             }
96492
96493             var params = {
96494               debounce: q !== '',
96495               key: field.key,
96496               query: query
96497             };
96498
96499             if (_entityIDs.length) {
96500               params.geometry = context.graph().geometry(_entityIDs[0]);
96501             }
96502
96503             services.taginfo[fn](params, function (err, data) {
96504               if (err) return;
96505               data = data.filter(function (d) {
96506                 if (field.type === 'typeCombo' && d.value === 'yes') {
96507                   // don't show the fallback value
96508                   return false;
96509                 } // don't show values with very low usage
96510
96511
96512                 return !d.count || d.count > 10;
96513               });
96514               var deprecatedValues = osmEntity.deprecatedTagValuesByKey(_dataDeprecated)[field.key];
96515
96516               if (deprecatedValues) {
96517                 // don't suggest deprecated tag values
96518                 data = data.filter(function (d) {
96519                   return deprecatedValues.indexOf(d.value) === -1;
96520                 });
96521               }
96522
96523               if (hasCountryPrefix) {
96524                 data = data.filter(function (d) {
96525                   return d.value.toLowerCase().indexOf(_countryCode + ':') === 0;
96526                 });
96527               } // hide the caret if there are no suggestions
96528
96529
96530               _container.classed('empty-combobox', data.length === 0);
96531
96532               _comboData = data.map(function (d) {
96533                 var k = d.value;
96534                 if (_isMulti) k = k.replace(field.key, '');
96535                 var label = field.t('options.' + k, {
96536                   "default": k
96537                 });
96538                 return {
96539                   key: k,
96540                   value: label,
96541                   display: field.t.html('options.' + k, {
96542                     "default": k
96543                   }),
96544                   title: d.title || label,
96545                   klass: field.hasTextForStringId('options.' + k) ? '' : 'raw-option'
96546                 };
96547               });
96548               _comboData = objectDifference(_comboData, _multiData);
96549               if (callback) callback(_comboData);
96550             });
96551           }
96552
96553           function setPlaceholder(values) {
96554             if (_isMulti || _isSemi) {
96555               _staticPlaceholder = field.placeholder() || _t('inspector.add');
96556             } else {
96557               var vals = values.map(function (d) {
96558                 return d.value;
96559               }).filter(function (s) {
96560                 return s.length < 20;
96561               });
96562               var placeholders = vals.length > 1 ? vals : values.map(function (d) {
96563                 return d.key;
96564               });
96565               _staticPlaceholder = field.placeholder() || placeholders.slice(0, 3).join(', ');
96566             }
96567
96568             if (!/(…|\.\.\.)$/.test(_staticPlaceholder)) {
96569               _staticPlaceholder += '…';
96570             }
96571
96572             var ph;
96573
96574             if (!_isMulti && !_isSemi && _tags && Array.isArray(_tags[field.key])) {
96575               ph = _t('inspector.multiple_values');
96576             } else {
96577               ph = _staticPlaceholder;
96578             }
96579
96580             _container.selectAll('input').attr('placeholder', ph);
96581           }
96582
96583           function change() {
96584             var t = {};
96585             var val;
96586
96587             if (_isMulti || _isSemi) {
96588               val = tagValue(utilGetSetValue(_input).replace(/,/g, ';')) || '';
96589
96590               _container.classed('active', false);
96591
96592               utilGetSetValue(_input, '');
96593               var vals = val.split(';').filter(Boolean);
96594               if (!vals.length) return;
96595
96596               if (_isMulti) {
96597                 utilArrayUniq(vals).forEach(function (v) {
96598                   var key = (field.key || '') + v;
96599
96600                   if (_tags) {
96601                     // don't set a multicombo value to 'yes' if it already has a non-'no' value
96602                     // e.g. `language:de=main`
96603                     var old = _tags[key];
96604                     if (typeof old === 'string' && old.toLowerCase() !== 'no') return;
96605                   }
96606
96607                   key = context.cleanTagKey(key);
96608                   field.keys.push(key);
96609                   t[key] = 'yes';
96610                 });
96611               } else if (_isSemi) {
96612                 var arr = _multiData.map(function (d) {
96613                   return d.key;
96614                 });
96615
96616                 arr = arr.concat(vals);
96617                 t[field.key] = context.cleanTagValue(utilArrayUniq(arr).filter(Boolean).join(';'));
96618               }
96619
96620               window.setTimeout(function () {
96621                 _input.node().focus();
96622               }, 10);
96623             } else {
96624               var rawValue = utilGetSetValue(_input); // don't override multiple values with blank string
96625
96626               if (!rawValue && Array.isArray(_tags[field.key])) return;
96627               val = context.cleanTagValue(tagValue(rawValue));
96628               t[field.key] = val || undefined;
96629             }
96630
96631             dispatch.call('change', this, t);
96632           }
96633
96634           function removeMultikey(d3_event, d) {
96635             d3_event.preventDefault();
96636             d3_event.stopPropagation();
96637             var t = {};
96638
96639             if (_isMulti) {
96640               t[d.key] = undefined;
96641             } else if (_isSemi) {
96642               var arr = _multiData.map(function (md) {
96643                 return md.key === d.key ? null : md.key;
96644               }).filter(Boolean);
96645
96646               arr = utilArrayUniq(arr);
96647               t[field.key] = arr.length ? arr.join(';') : undefined;
96648             }
96649
96650             dispatch.call('change', this, t);
96651           }
96652
96653           function combo(selection) {
96654             _container = selection.selectAll('.form-field-input-wrap').data([0]);
96655             var type = _isMulti || _isSemi ? 'multicombo' : 'combo';
96656             _container = _container.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + type).merge(_container);
96657
96658             if (_isMulti || _isSemi) {
96659               _container = _container.selectAll('.chiplist').data([0]);
96660               var listClass = 'chiplist'; // Use a separate line for each value in the Destinations and Via fields
96661               // to mimic highway exit signs
96662
96663               if (field.key === 'destination' || field.key === 'via') {
96664                 listClass += ' full-line-chips';
96665               }
96666
96667               _container = _container.enter().append('ul').attr('class', listClass).on('click', function () {
96668                 window.setTimeout(function () {
96669                   _input.node().focus();
96670                 }, 10);
96671               }).merge(_container);
96672               _inputWrap = _container.selectAll('.input-wrap').data([0]);
96673               _inputWrap = _inputWrap.enter().append('li').attr('class', 'input-wrap').merge(_inputWrap);
96674               _input = _inputWrap.selectAll('input').data([0]);
96675             } else {
96676               _input = _container.selectAll('input').data([0]);
96677             }
96678
96679             _input = _input.enter().append('input').attr('type', 'text').attr('id', field.domId).call(utilNoAuto).call(initCombo, selection).merge(_input);
96680
96681             if (_isNetwork) {
96682               var extent = combinedEntityExtent();
96683               var countryCode = extent && iso1A2Code(extent.center());
96684               _countryCode = countryCode && countryCode.toLowerCase();
96685             }
96686
96687             _input.on('change', change).on('blur', change);
96688
96689             _input.on('keydown.field', function (d3_event) {
96690               switch (d3_event.keyCode) {
96691                 case 13:
96692                   // ↩ Return
96693                   _input.node().blur(); // blurring also enters the value
96694
96695
96696                   d3_event.stopPropagation();
96697                   break;
96698               }
96699             });
96700
96701             if (_isMulti || _isSemi) {
96702               _combobox.on('accept', function () {
96703                 _input.node().blur();
96704
96705                 _input.node().focus();
96706               });
96707
96708               _input.on('focus', function () {
96709                 _container.classed('active', true);
96710               });
96711             }
96712           }
96713
96714           combo.tags = function (tags) {
96715             _tags = tags;
96716
96717             if (_isMulti || _isSemi) {
96718               _multiData = [];
96719               var maxLength;
96720
96721               if (_isMulti) {
96722                 // Build _multiData array containing keys already set..
96723                 for (var k in tags) {
96724                   if (field.key && k.indexOf(field.key) !== 0) continue;
96725                   if (!field.key && field.keys.indexOf(k) === -1) continue;
96726                   var v = tags[k];
96727                   if (!v || typeof v === 'string' && v.toLowerCase() === 'no') continue;
96728                   var suffix = field.key ? k.substr(field.key.length) : k;
96729
96730                   _multiData.push({
96731                     key: k,
96732                     value: displayValue(suffix),
96733                     isMixed: Array.isArray(v)
96734                   });
96735                 }
96736
96737                 if (field.key) {
96738                   // Set keys for form-field modified (needed for undo and reset buttons)..
96739                   field.keys = _multiData.map(function (d) {
96740                     return d.key;
96741                   }); // limit the input length so it fits after prepending the key prefix
96742
96743                   maxLength = context.maxCharsForTagKey() - utilUnicodeCharsCount(field.key);
96744                 } else {
96745                   maxLength = context.maxCharsForTagKey();
96746                 }
96747               } else if (_isSemi) {
96748                 var allValues = [];
96749                 var commonValues;
96750
96751                 if (Array.isArray(tags[field.key])) {
96752                   tags[field.key].forEach(function (tagVal) {
96753                     var thisVals = utilArrayUniq((tagVal || '').split(';')).filter(Boolean);
96754                     allValues = allValues.concat(thisVals);
96755
96756                     if (!commonValues) {
96757                       commonValues = thisVals;
96758                     } else {
96759                       commonValues = commonValues.filter(function (value) {
96760                         return thisVals.includes(value);
96761                       });
96762                     }
96763                   });
96764                   allValues = utilArrayUniq(allValues).filter(Boolean);
96765                 } else {
96766                   allValues = utilArrayUniq((tags[field.key] || '').split(';')).filter(Boolean);
96767                   commonValues = allValues;
96768                 }
96769
96770                 _multiData = allValues.map(function (v) {
96771                   return {
96772                     key: v,
96773                     value: displayValue(v),
96774                     isMixed: !commonValues.includes(v)
96775                   };
96776                 });
96777                 var currLength = utilUnicodeCharsCount(commonValues.join(';')); // limit the input length to the remaining available characters
96778
96779                 maxLength = context.maxCharsForTagValue() - currLength;
96780
96781                 if (currLength > 0) {
96782                   // account for the separator if a new value will be appended to existing
96783                   maxLength -= 1;
96784                 }
96785               } // a negative maxlength doesn't make sense
96786
96787
96788               maxLength = Math.max(0, maxLength);
96789               var allowDragAndDrop = _isSemi // only semiCombo values are ordered
96790               && !Array.isArray(tags[field.key]); // Exclude existing multikeys from combo options..
96791
96792               var available = objectDifference(_comboData, _multiData);
96793
96794               _combobox.data(available); // Hide 'Add' button if this field uses fixed set of
96795               // options and they're all currently used,
96796               // or if the field is already at its character limit
96797
96798
96799               var hideAdd = !_allowCustomValues && !available.length || maxLength <= 0;
96800
96801               _container.selectAll('.chiplist .input-wrap').style('display', hideAdd ? 'none' : null); // Render chips
96802
96803
96804               var chips = _container.selectAll('.chip').data(_multiData);
96805
96806               chips.exit().remove();
96807               var enter = chips.enter().insert('li', '.input-wrap').attr('class', 'chip');
96808               enter.append('span');
96809               enter.append('a');
96810               chips = chips.merge(enter).order().classed('raw-value', function (d) {
96811                 var k = d.key;
96812                 if (_isMulti) k = k.replace(field.key, '');
96813                 return !field.hasTextForStringId('options.' + k);
96814               }).classed('draggable', allowDragAndDrop).classed('mixed', function (d) {
96815                 return d.isMixed;
96816               }).attr('title', function (d) {
96817                 return d.isMixed ? _t('inspector.unshared_value_tooltip') : null;
96818               });
96819
96820               if (allowDragAndDrop) {
96821                 registerDragAndDrop(chips);
96822               }
96823
96824               chips.select('span').text(function (d) {
96825                 return d.value;
96826               });
96827               chips.select('a').attr('href', '#').on('click', removeMultikey).attr('class', 'remove').text('×');
96828             } else {
96829               var isMixed = Array.isArray(tags[field.key]);
96830               var mixedValues = isMixed && tags[field.key].map(function (val) {
96831                 return displayValue(val);
96832               }).filter(Boolean);
96833               var showsValue = !isMixed && tags[field.key] && !(field.type === 'typeCombo' && tags[field.key] === 'yes');
96834               var isRawValue = showsValue && !field.hasTextForStringId('options.' + tags[field.key]);
96835               var isKnownValue = showsValue && !isRawValue;
96836               var isReadOnly = !_allowCustomValues || isKnownValue;
96837               utilGetSetValue(_input, !isMixed ? displayValue(tags[field.key]) : '').classed('raw-value', isRawValue).classed('known-value', isKnownValue).attr('readonly', isReadOnly ? 'readonly' : undefined).attr('title', isMixed ? mixedValues.join('\n') : undefined).attr('placeholder', isMixed ? _t('inspector.multiple_values') : _staticPlaceholder || '').classed('mixed', isMixed).on('keydown.deleteCapture', function (d3_event) {
96838                 if (isReadOnly && isKnownValue && (d3_event.keyCode === utilKeybinding.keyCodes['⌫'] || d3_event.keyCode === utilKeybinding.keyCodes['⌦'])) {
96839                   d3_event.preventDefault();
96840                   d3_event.stopPropagation();
96841                   var t = {};
96842                   t[field.key] = undefined;
96843                   dispatch.call('change', this, t);
96844                 }
96845               });
96846             }
96847           };
96848
96849           function registerDragAndDrop(selection) {
96850             // allow drag and drop re-ordering of chips
96851             var dragOrigin, targetIndex;
96852             selection.call(d3_drag().on('start', function (d3_event) {
96853               dragOrigin = {
96854                 x: d3_event.x,
96855                 y: d3_event.y
96856               };
96857               targetIndex = null;
96858             }).on('drag', function (d3_event) {
96859               var x = d3_event.x - dragOrigin.x,
96860                   y = d3_event.y - dragOrigin.y;
96861               if (!select(this).classed('dragging') && // don't display drag until dragging beyond a distance threshold
96862               Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5) return;
96863               var index = selection.nodes().indexOf(this);
96864               select(this).classed('dragging', true);
96865               targetIndex = null;
96866               var targetIndexOffsetTop = null;
96867               var draggedTagWidth = select(this).node().offsetWidth;
96868
96869               if (field.key === 'destination' || field.key === 'via') {
96870                 // meaning tags are full width
96871                 _container.selectAll('.chip').style('transform', function (d2, index2) {
96872                   var node = select(this).node();
96873
96874                   if (index === index2) {
96875                     return 'translate(' + x + 'px, ' + y + 'px)'; // move the dragged tag up the order
96876                   } else if (index2 > index && d3_event.y > node.offsetTop) {
96877                     if (targetIndex === null || index2 > targetIndex) {
96878                       targetIndex = index2;
96879                     }
96880
96881                     return 'translateY(-100%)'; // move the dragged tag down the order
96882                   } else if (index2 < index && d3_event.y < node.offsetTop + node.offsetHeight) {
96883                     if (targetIndex === null || index2 < targetIndex) {
96884                       targetIndex = index2;
96885                     }
96886
96887                     return 'translateY(100%)';
96888                   }
96889
96890                   return null;
96891                 });
96892               } else {
96893                 _container.selectAll('.chip').each(function (d2, index2) {
96894                   var node = select(this).node(); // check the cursor is in the bounding box
96895
96896                   if (index !== index2 && d3_event.x < node.offsetLeft + node.offsetWidth + 5 && d3_event.x > node.offsetLeft && d3_event.y < node.offsetTop + node.offsetHeight && d3_event.y > node.offsetTop) {
96897                     targetIndex = index2;
96898                     targetIndexOffsetTop = node.offsetTop;
96899                   }
96900                 }).style('transform', function (d2, index2) {
96901                   var node = select(this).node();
96902
96903                   if (index === index2) {
96904                     return 'translate(' + x + 'px, ' + y + 'px)';
96905                   } // only translate tags in the same row
96906
96907
96908                   if (node.offsetTop === targetIndexOffsetTop) {
96909                     if (index2 < index && index2 >= targetIndex) {
96910                       return 'translateX(' + draggedTagWidth + 'px)';
96911                     } else if (index2 > index && index2 <= targetIndex) {
96912                       return 'translateX(-' + draggedTagWidth + 'px)';
96913                     }
96914                   }
96915
96916                   return null;
96917                 });
96918               }
96919             }).on('end', function () {
96920               if (!select(this).classed('dragging')) {
96921                 return;
96922               }
96923
96924               var index = selection.nodes().indexOf(this);
96925               select(this).classed('dragging', false);
96926
96927               _container.selectAll('.chip').style('transform', null);
96928
96929               if (typeof targetIndex === 'number') {
96930                 var element = _multiData[index];
96931
96932                 _multiData.splice(index, 1);
96933
96934                 _multiData.splice(targetIndex, 0, element);
96935
96936                 var t = {};
96937
96938                 if (_multiData.length) {
96939                   t[field.key] = _multiData.map(function (element) {
96940                     return element.key;
96941                   }).join(';');
96942                 } else {
96943                   t[field.key] = undefined;
96944                 }
96945
96946                 dispatch.call('change', this, t);
96947               }
96948
96949               dragOrigin = undefined;
96950               targetIndex = undefined;
96951             }));
96952           }
96953
96954           combo.focus = function () {
96955             _input.node().focus();
96956           };
96957
96958           combo.entityIDs = function (val) {
96959             if (!arguments.length) return _entityIDs;
96960             _entityIDs = val;
96961             return combo;
96962           };
96963
96964           function combinedEntityExtent() {
96965             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
96966           }
96967
96968           return utilRebind(combo, dispatch, 'on');
96969         }
96970
96971         // based on https://github.com/bestiejs/punycode.js/blob/master/punycode.js
96972         var global$2 = global$1o;
96973         var uncurryThis$1 = functionUncurryThis;
96974
96975         var maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1
96976         var base = 36;
96977         var tMin = 1;
96978         var tMax = 26;
96979         var skew = 38;
96980         var damp = 700;
96981         var initialBias = 72;
96982         var initialN = 128; // 0x80
96983         var delimiter = '-'; // '\x2D'
96984         var regexNonASCII = /[^\0-\u007E]/; // non-ASCII chars
96985         var regexSeparators = /[.\u3002\uFF0E\uFF61]/g; // RFC 3490 separators
96986         var OVERFLOW_ERROR = 'Overflow: input needs wider integers to process';
96987         var baseMinusTMin = base - tMin;
96988
96989         var RangeError$1 = global$2.RangeError;
96990         var exec$1 = uncurryThis$1(regexSeparators.exec);
96991         var floor$1 = Math.floor;
96992         var fromCharCode = String.fromCharCode;
96993         var charCodeAt = uncurryThis$1(''.charCodeAt);
96994         var join$1 = uncurryThis$1([].join);
96995         var push$1 = uncurryThis$1([].push);
96996         var replace$1 = uncurryThis$1(''.replace);
96997         var split$1 = uncurryThis$1(''.split);
96998         var toLowerCase$1 = uncurryThis$1(''.toLowerCase);
96999
97000         /**
97001          * Creates an array containing the numeric code points of each Unicode
97002          * character in the string. While JavaScript uses UCS-2 internally,
97003          * this function will convert a pair of surrogate halves (each of which
97004          * UCS-2 exposes as separate characters) into a single code point,
97005          * matching UTF-16.
97006          */
97007         var ucs2decode = function (string) {
97008           var output = [];
97009           var counter = 0;
97010           var length = string.length;
97011           while (counter < length) {
97012             var value = charCodeAt(string, counter++);
97013             if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
97014               // It's a high surrogate, and there is a next character.
97015               var extra = charCodeAt(string, counter++);
97016               if ((extra & 0xFC00) == 0xDC00) { // Low surrogate.
97017                 push$1(output, ((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
97018               } else {
97019                 // It's an unmatched surrogate; only append this code unit, in case the
97020                 // next code unit is the high surrogate of a surrogate pair.
97021                 push$1(output, value);
97022                 counter--;
97023               }
97024             } else {
97025               push$1(output, value);
97026             }
97027           }
97028           return output;
97029         };
97030
97031         /**
97032          * Converts a digit/integer into a basic code point.
97033          */
97034         var digitToBasic = function (digit) {
97035           //  0..25 map to ASCII a..z or A..Z
97036           // 26..35 map to ASCII 0..9
97037           return digit + 22 + 75 * (digit < 26);
97038         };
97039
97040         /**
97041          * Bias adaptation function as per section 3.4 of RFC 3492.
97042          * https://tools.ietf.org/html/rfc3492#section-3.4
97043          */
97044         var adapt = function (delta, numPoints, firstTime) {
97045           var k = 0;
97046           delta = firstTime ? floor$1(delta / damp) : delta >> 1;
97047           delta += floor$1(delta / numPoints);
97048           while (delta > baseMinusTMin * tMax >> 1) {
97049             delta = floor$1(delta / baseMinusTMin);
97050             k += base;
97051           }
97052           return floor$1(k + (baseMinusTMin + 1) * delta / (delta + skew));
97053         };
97054
97055         /**
97056          * Converts a string of Unicode symbols (e.g. a domain name label) to a
97057          * Punycode string of ASCII-only symbols.
97058          */
97059         var encode = function (input) {
97060           var output = [];
97061
97062           // Convert the input in UCS-2 to an array of Unicode code points.
97063           input = ucs2decode(input);
97064
97065           // Cache the length.
97066           var inputLength = input.length;
97067
97068           // Initialize the state.
97069           var n = initialN;
97070           var delta = 0;
97071           var bias = initialBias;
97072           var i, currentValue;
97073
97074           // Handle the basic code points.
97075           for (i = 0; i < input.length; i++) {
97076             currentValue = input[i];
97077             if (currentValue < 0x80) {
97078               push$1(output, fromCharCode(currentValue));
97079             }
97080           }
97081
97082           var basicLength = output.length; // number of basic code points.
97083           var handledCPCount = basicLength; // number of code points that have been handled;
97084
97085           // Finish the basic string with a delimiter unless it's empty.
97086           if (basicLength) {
97087             push$1(output, delimiter);
97088           }
97089
97090           // Main encoding loop:
97091           while (handledCPCount < inputLength) {
97092             // All non-basic code points < n have been handled already. Find the next larger one:
97093             var m = maxInt;
97094             for (i = 0; i < input.length; i++) {
97095               currentValue = input[i];
97096               if (currentValue >= n && currentValue < m) {
97097                 m = currentValue;
97098               }
97099             }
97100
97101             // Increase `delta` enough to advance the decoder's <n,i> state to <m,0>, but guard against overflow.
97102             var handledCPCountPlusOne = handledCPCount + 1;
97103             if (m - n > floor$1((maxInt - delta) / handledCPCountPlusOne)) {
97104               throw RangeError$1(OVERFLOW_ERROR);
97105             }
97106
97107             delta += (m - n) * handledCPCountPlusOne;
97108             n = m;
97109
97110             for (i = 0; i < input.length; i++) {
97111               currentValue = input[i];
97112               if (currentValue < n && ++delta > maxInt) {
97113                 throw RangeError$1(OVERFLOW_ERROR);
97114               }
97115               if (currentValue == n) {
97116                 // Represent delta as a generalized variable-length integer.
97117                 var q = delta;
97118                 var k = base;
97119                 while (true) {
97120                   var t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
97121                   if (q < t) break;
97122                   var qMinusT = q - t;
97123                   var baseMinusT = base - t;
97124                   push$1(output, fromCharCode(digitToBasic(t + qMinusT % baseMinusT)));
97125                   q = floor$1(qMinusT / baseMinusT);
97126                   k += base;
97127                 }
97128
97129                 push$1(output, fromCharCode(digitToBasic(q)));
97130                 bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
97131                 delta = 0;
97132                 handledCPCount++;
97133               }
97134             }
97135
97136             delta++;
97137             n++;
97138           }
97139           return join$1(output, '');
97140         };
97141
97142         var stringPunycodeToAscii = function (input) {
97143           var encoded = [];
97144           var labels = split$1(replace$1(toLowerCase$1(input), regexSeparators, '\u002E'), '.');
97145           var i, label;
97146           for (i = 0; i < labels.length; i++) {
97147             label = labels[i];
97148             push$1(encoded, exec$1(regexNonASCII, label) ? 'xn--' + encode(label) : label);
97149           }
97150           return join$1(encoded, '.');
97151         };
97152
97153         // TODO: in core-js@4, move /modules/ dependencies to public entries for better optimization by tools like `preset-env`
97154
97155         var $ = _export;
97156         var DESCRIPTORS = descriptors;
97157         var USE_NATIVE_URL = nativeUrl;
97158         var global$1 = global$1o;
97159         var bind$2 = functionBindContext;
97160         var uncurryThis = functionUncurryThis;
97161         var defineProperties = objectDefineProperties.f;
97162         var redefine = redefine$h.exports;
97163         var anInstance = anInstance$7;
97164         var hasOwn = hasOwnProperty_1;
97165         var assign$1 = objectAssign;
97166         var arrayFrom = arrayFrom$1;
97167         var arraySlice = arraySliceSimple;
97168         var codeAt = stringMultibyte.codeAt;
97169         var toASCII = stringPunycodeToAscii;
97170         var $toString = toString$k;
97171         var setToStringTag = setToStringTag$a;
97172         var validateArgumentsLength = validateArgumentsLength$4;
97173         var URLSearchParamsModule = web_urlSearchParams;
97174         var InternalStateModule = internalState;
97175
97176         var setInternalState = InternalStateModule.set;
97177         var getInternalURLState = InternalStateModule.getterFor('URL');
97178         var URLSearchParams$1 = URLSearchParamsModule.URLSearchParams;
97179         var getInternalSearchParamsState = URLSearchParamsModule.getState;
97180
97181         var NativeURL = global$1.URL;
97182         var TypeError$1 = global$1.TypeError;
97183         var parseInt$1 = global$1.parseInt;
97184         var floor = Math.floor;
97185         var pow = Math.pow;
97186         var charAt = uncurryThis(''.charAt);
97187         var exec = uncurryThis(/./.exec);
97188         var join = uncurryThis([].join);
97189         var numberToString = uncurryThis(1.0.toString);
97190         var pop = uncurryThis([].pop);
97191         var push = uncurryThis([].push);
97192         var replace = uncurryThis(''.replace);
97193         var shift = uncurryThis([].shift);
97194         var split = uncurryThis(''.split);
97195         var stringSlice = uncurryThis(''.slice);
97196         var toLowerCase = uncurryThis(''.toLowerCase);
97197         var unshift = uncurryThis([].unshift);
97198
97199         var INVALID_AUTHORITY = 'Invalid authority';
97200         var INVALID_SCHEME = 'Invalid scheme';
97201         var INVALID_HOST = 'Invalid host';
97202         var INVALID_PORT = 'Invalid port';
97203
97204         var ALPHA = /[a-z]/i;
97205         // eslint-disable-next-line regexp/no-obscure-range -- safe
97206         var ALPHANUMERIC = /[\d+-.a-z]/i;
97207         var DIGIT = /\d/;
97208         var HEX_START = /^0x/i;
97209         var OCT = /^[0-7]+$/;
97210         var DEC = /^\d+$/;
97211         var HEX = /^[\da-f]+$/i;
97212         /* eslint-disable regexp/no-control-character -- safe */
97213         var FORBIDDEN_HOST_CODE_POINT = /[\0\t\n\r #%/:<>?@[\\\]^|]/;
97214         var FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT = /[\0\t\n\r #/:<>?@[\\\]^|]/;
97215         var LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE = /^[\u0000-\u0020]+|[\u0000-\u0020]+$/g;
97216         var TAB_AND_NEW_LINE = /[\t\n\r]/g;
97217         /* eslint-enable regexp/no-control-character -- safe */
97218         var EOF;
97219
97220         // https://url.spec.whatwg.org/#ipv4-number-parser
97221         var parseIPv4 = function (input) {
97222           var parts = split(input, '.');
97223           var partsLength, numbers, index, part, radix, number, ipv4;
97224           if (parts.length && parts[parts.length - 1] == '') {
97225             parts.length--;
97226           }
97227           partsLength = parts.length;
97228           if (partsLength > 4) return input;
97229           numbers = [];
97230           for (index = 0; index < partsLength; index++) {
97231             part = parts[index];
97232             if (part == '') return input;
97233             radix = 10;
97234             if (part.length > 1 && charAt(part, 0) == '0') {
97235               radix = exec(HEX_START, part) ? 16 : 8;
97236               part = stringSlice(part, radix == 8 ? 1 : 2);
97237             }
97238             if (part === '') {
97239               number = 0;
97240             } else {
97241               if (!exec(radix == 10 ? DEC : radix == 8 ? OCT : HEX, part)) return input;
97242               number = parseInt$1(part, radix);
97243             }
97244             push(numbers, number);
97245           }
97246           for (index = 0; index < partsLength; index++) {
97247             number = numbers[index];
97248             if (index == partsLength - 1) {
97249               if (number >= pow(256, 5 - partsLength)) return null;
97250             } else if (number > 255) return null;
97251           }
97252           ipv4 = pop(numbers);
97253           for (index = 0; index < numbers.length; index++) {
97254             ipv4 += numbers[index] * pow(256, 3 - index);
97255           }
97256           return ipv4;
97257         };
97258
97259         // https://url.spec.whatwg.org/#concept-ipv6-parser
97260         // eslint-disable-next-line max-statements -- TODO
97261         var parseIPv6 = function (input) {
97262           var address = [0, 0, 0, 0, 0, 0, 0, 0];
97263           var pieceIndex = 0;
97264           var compress = null;
97265           var pointer = 0;
97266           var value, length, numbersSeen, ipv4Piece, number, swaps, swap;
97267
97268           var chr = function () {
97269             return charAt(input, pointer);
97270           };
97271
97272           if (chr() == ':') {
97273             if (charAt(input, 1) != ':') return;
97274             pointer += 2;
97275             pieceIndex++;
97276             compress = pieceIndex;
97277           }
97278           while (chr()) {
97279             if (pieceIndex == 8) return;
97280             if (chr() == ':') {
97281               if (compress !== null) return;
97282               pointer++;
97283               pieceIndex++;
97284               compress = pieceIndex;
97285               continue;
97286             }
97287             value = length = 0;
97288             while (length < 4 && exec(HEX, chr())) {
97289               value = value * 16 + parseInt$1(chr(), 16);
97290               pointer++;
97291               length++;
97292             }
97293             if (chr() == '.') {
97294               if (length == 0) return;
97295               pointer -= length;
97296               if (pieceIndex > 6) return;
97297               numbersSeen = 0;
97298               while (chr()) {
97299                 ipv4Piece = null;
97300                 if (numbersSeen > 0) {
97301                   if (chr() == '.' && numbersSeen < 4) pointer++;
97302                   else return;
97303                 }
97304                 if (!exec(DIGIT, chr())) return;
97305                 while (exec(DIGIT, chr())) {
97306                   number = parseInt$1(chr(), 10);
97307                   if (ipv4Piece === null) ipv4Piece = number;
97308                   else if (ipv4Piece == 0) return;
97309                   else ipv4Piece = ipv4Piece * 10 + number;
97310                   if (ipv4Piece > 255) return;
97311                   pointer++;
97312                 }
97313                 address[pieceIndex] = address[pieceIndex] * 256 + ipv4Piece;
97314                 numbersSeen++;
97315                 if (numbersSeen == 2 || numbersSeen == 4) pieceIndex++;
97316               }
97317               if (numbersSeen != 4) return;
97318               break;
97319             } else if (chr() == ':') {
97320               pointer++;
97321               if (!chr()) return;
97322             } else if (chr()) return;
97323             address[pieceIndex++] = value;
97324           }
97325           if (compress !== null) {
97326             swaps = pieceIndex - compress;
97327             pieceIndex = 7;
97328             while (pieceIndex != 0 && swaps > 0) {
97329               swap = address[pieceIndex];
97330               address[pieceIndex--] = address[compress + swaps - 1];
97331               address[compress + --swaps] = swap;
97332             }
97333           } else if (pieceIndex != 8) return;
97334           return address;
97335         };
97336
97337         var findLongestZeroSequence = function (ipv6) {
97338           var maxIndex = null;
97339           var maxLength = 1;
97340           var currStart = null;
97341           var currLength = 0;
97342           var index = 0;
97343           for (; index < 8; index++) {
97344             if (ipv6[index] !== 0) {
97345               if (currLength > maxLength) {
97346                 maxIndex = currStart;
97347                 maxLength = currLength;
97348               }
97349               currStart = null;
97350               currLength = 0;
97351             } else {
97352               if (currStart === null) currStart = index;
97353               ++currLength;
97354             }
97355           }
97356           if (currLength > maxLength) {
97357             maxIndex = currStart;
97358             maxLength = currLength;
97359           }
97360           return maxIndex;
97361         };
97362
97363         // https://url.spec.whatwg.org/#host-serializing
97364         var serializeHost = function (host) {
97365           var result, index, compress, ignore0;
97366           // ipv4
97367           if (typeof host == 'number') {
97368             result = [];
97369             for (index = 0; index < 4; index++) {
97370               unshift(result, host % 256);
97371               host = floor(host / 256);
97372             } return join(result, '.');
97373           // ipv6
97374           } else if (typeof host == 'object') {
97375             result = '';
97376             compress = findLongestZeroSequence(host);
97377             for (index = 0; index < 8; index++) {
97378               if (ignore0 && host[index] === 0) continue;
97379               if (ignore0) ignore0 = false;
97380               if (compress === index) {
97381                 result += index ? ':' : '::';
97382                 ignore0 = true;
97383               } else {
97384                 result += numberToString(host[index], 16);
97385                 if (index < 7) result += ':';
97386               }
97387             }
97388             return '[' + result + ']';
97389           } return host;
97390         };
97391
97392         var C0ControlPercentEncodeSet = {};
97393         var fragmentPercentEncodeSet = assign$1({}, C0ControlPercentEncodeSet, {
97394           ' ': 1, '"': 1, '<': 1, '>': 1, '`': 1
97395         });
97396         var pathPercentEncodeSet = assign$1({}, fragmentPercentEncodeSet, {
97397           '#': 1, '?': 1, '{': 1, '}': 1
97398         });
97399         var userinfoPercentEncodeSet = assign$1({}, pathPercentEncodeSet, {
97400           '/': 1, ':': 1, ';': 1, '=': 1, '@': 1, '[': 1, '\\': 1, ']': 1, '^': 1, '|': 1
97401         });
97402
97403         var percentEncode = function (chr, set) {
97404           var code = codeAt(chr, 0);
97405           return code > 0x20 && code < 0x7F && !hasOwn(set, chr) ? chr : encodeURIComponent(chr);
97406         };
97407
97408         // https://url.spec.whatwg.org/#special-scheme
97409         var specialSchemes = {
97410           ftp: 21,
97411           file: null,
97412           http: 80,
97413           https: 443,
97414           ws: 80,
97415           wss: 443
97416         };
97417
97418         // https://url.spec.whatwg.org/#windows-drive-letter
97419         var isWindowsDriveLetter = function (string, normalized) {
97420           var second;
97421           return string.length == 2 && exec(ALPHA, charAt(string, 0))
97422             && ((second = charAt(string, 1)) == ':' || (!normalized && second == '|'));
97423         };
97424
97425         // https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
97426         var startsWithWindowsDriveLetter = function (string) {
97427           var third;
97428           return string.length > 1 && isWindowsDriveLetter(stringSlice(string, 0, 2)) && (
97429             string.length == 2 ||
97430             ((third = charAt(string, 2)) === '/' || third === '\\' || third === '?' || third === '#')
97431           );
97432         };
97433
97434         // https://url.spec.whatwg.org/#single-dot-path-segment
97435         var isSingleDot = function (segment) {
97436           return segment === '.' || toLowerCase(segment) === '%2e';
97437         };
97438
97439         // https://url.spec.whatwg.org/#double-dot-path-segment
97440         var isDoubleDot = function (segment) {
97441           segment = toLowerCase(segment);
97442           return segment === '..' || segment === '%2e.' || segment === '.%2e' || segment === '%2e%2e';
97443         };
97444
97445         // States:
97446         var SCHEME_START = {};
97447         var SCHEME = {};
97448         var NO_SCHEME = {};
97449         var SPECIAL_RELATIVE_OR_AUTHORITY = {};
97450         var PATH_OR_AUTHORITY = {};
97451         var RELATIVE = {};
97452         var RELATIVE_SLASH = {};
97453         var SPECIAL_AUTHORITY_SLASHES = {};
97454         var SPECIAL_AUTHORITY_IGNORE_SLASHES = {};
97455         var AUTHORITY = {};
97456         var HOST = {};
97457         var HOSTNAME = {};
97458         var PORT = {};
97459         var FILE = {};
97460         var FILE_SLASH = {};
97461         var FILE_HOST = {};
97462         var PATH_START = {};
97463         var PATH = {};
97464         var CANNOT_BE_A_BASE_URL_PATH = {};
97465         var QUERY = {};
97466         var FRAGMENT = {};
97467
97468         var URLState = function (url, isBase, base) {
97469           var urlString = $toString(url);
97470           var baseState, failure, searchParams;
97471           if (isBase) {
97472             failure = this.parse(urlString);
97473             if (failure) throw TypeError$1(failure);
97474             this.searchParams = null;
97475           } else {
97476             if (base !== undefined) baseState = new URLState(base, true);
97477             failure = this.parse(urlString, null, baseState);
97478             if (failure) throw TypeError$1(failure);
97479             searchParams = getInternalSearchParamsState(new URLSearchParams$1());
97480             searchParams.bindURL(this);
97481             this.searchParams = searchParams;
97482           }
97483         };
97484
97485         URLState.prototype = {
97486           type: 'URL',
97487           // https://url.spec.whatwg.org/#url-parsing
97488           // eslint-disable-next-line max-statements -- TODO
97489           parse: function (input, stateOverride, base) {
97490             var url = this;
97491             var state = stateOverride || SCHEME_START;
97492             var pointer = 0;
97493             var buffer = '';
97494             var seenAt = false;
97495             var seenBracket = false;
97496             var seenPasswordToken = false;
97497             var codePoints, chr, bufferCodePoints, failure;
97498
97499             input = $toString(input);
97500
97501             if (!stateOverride) {
97502               url.scheme = '';
97503               url.username = '';
97504               url.password = '';
97505               url.host = null;
97506               url.port = null;
97507               url.path = [];
97508               url.query = null;
97509               url.fragment = null;
97510               url.cannotBeABaseURL = false;
97511               input = replace(input, LEADING_AND_TRAILING_C0_CONTROL_OR_SPACE, '');
97512             }
97513
97514             input = replace(input, TAB_AND_NEW_LINE, '');
97515
97516             codePoints = arrayFrom(input);
97517
97518             while (pointer <= codePoints.length) {
97519               chr = codePoints[pointer];
97520               switch (state) {
97521                 case SCHEME_START:
97522                   if (chr && exec(ALPHA, chr)) {
97523                     buffer += toLowerCase(chr);
97524                     state = SCHEME;
97525                   } else if (!stateOverride) {
97526                     state = NO_SCHEME;
97527                     continue;
97528                   } else return INVALID_SCHEME;
97529                   break;
97530
97531                 case SCHEME:
97532                   if (chr && (exec(ALPHANUMERIC, chr) || chr == '+' || chr == '-' || chr == '.')) {
97533                     buffer += toLowerCase(chr);
97534                   } else if (chr == ':') {
97535                     if (stateOverride && (
97536                       (url.isSpecial() != hasOwn(specialSchemes, buffer)) ||
97537                       (buffer == 'file' && (url.includesCredentials() || url.port !== null)) ||
97538                       (url.scheme == 'file' && !url.host)
97539                     )) return;
97540                     url.scheme = buffer;
97541                     if (stateOverride) {
97542                       if (url.isSpecial() && specialSchemes[url.scheme] == url.port) url.port = null;
97543                       return;
97544                     }
97545                     buffer = '';
97546                     if (url.scheme == 'file') {
97547                       state = FILE;
97548                     } else if (url.isSpecial() && base && base.scheme == url.scheme) {
97549                       state = SPECIAL_RELATIVE_OR_AUTHORITY;
97550                     } else if (url.isSpecial()) {
97551                       state = SPECIAL_AUTHORITY_SLASHES;
97552                     } else if (codePoints[pointer + 1] == '/') {
97553                       state = PATH_OR_AUTHORITY;
97554                       pointer++;
97555                     } else {
97556                       url.cannotBeABaseURL = true;
97557                       push(url.path, '');
97558                       state = CANNOT_BE_A_BASE_URL_PATH;
97559                     }
97560                   } else if (!stateOverride) {
97561                     buffer = '';
97562                     state = NO_SCHEME;
97563                     pointer = 0;
97564                     continue;
97565                   } else return INVALID_SCHEME;
97566                   break;
97567
97568                 case NO_SCHEME:
97569                   if (!base || (base.cannotBeABaseURL && chr != '#')) return INVALID_SCHEME;
97570                   if (base.cannotBeABaseURL && chr == '#') {
97571                     url.scheme = base.scheme;
97572                     url.path = arraySlice(base.path);
97573                     url.query = base.query;
97574                     url.fragment = '';
97575                     url.cannotBeABaseURL = true;
97576                     state = FRAGMENT;
97577                     break;
97578                   }
97579                   state = base.scheme == 'file' ? FILE : RELATIVE;
97580                   continue;
97581
97582                 case SPECIAL_RELATIVE_OR_AUTHORITY:
97583                   if (chr == '/' && codePoints[pointer + 1] == '/') {
97584                     state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
97585                     pointer++;
97586                   } else {
97587                     state = RELATIVE;
97588                     continue;
97589                   } break;
97590
97591                 case PATH_OR_AUTHORITY:
97592                   if (chr == '/') {
97593                     state = AUTHORITY;
97594                     break;
97595                   } else {
97596                     state = PATH;
97597                     continue;
97598                   }
97599
97600                 case RELATIVE:
97601                   url.scheme = base.scheme;
97602                   if (chr == EOF) {
97603                     url.username = base.username;
97604                     url.password = base.password;
97605                     url.host = base.host;
97606                     url.port = base.port;
97607                     url.path = arraySlice(base.path);
97608                     url.query = base.query;
97609                   } else if (chr == '/' || (chr == '\\' && url.isSpecial())) {
97610                     state = RELATIVE_SLASH;
97611                   } else if (chr == '?') {
97612                     url.username = base.username;
97613                     url.password = base.password;
97614                     url.host = base.host;
97615                     url.port = base.port;
97616                     url.path = arraySlice(base.path);
97617                     url.query = '';
97618                     state = QUERY;
97619                   } else if (chr == '#') {
97620                     url.username = base.username;
97621                     url.password = base.password;
97622                     url.host = base.host;
97623                     url.port = base.port;
97624                     url.path = arraySlice(base.path);
97625                     url.query = base.query;
97626                     url.fragment = '';
97627                     state = FRAGMENT;
97628                   } else {
97629                     url.username = base.username;
97630                     url.password = base.password;
97631                     url.host = base.host;
97632                     url.port = base.port;
97633                     url.path = arraySlice(base.path);
97634                     url.path.length--;
97635                     state = PATH;
97636                     continue;
97637                   } break;
97638
97639                 case RELATIVE_SLASH:
97640                   if (url.isSpecial() && (chr == '/' || chr == '\\')) {
97641                     state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
97642                   } else if (chr == '/') {
97643                     state = AUTHORITY;
97644                   } else {
97645                     url.username = base.username;
97646                     url.password = base.password;
97647                     url.host = base.host;
97648                     url.port = base.port;
97649                     state = PATH;
97650                     continue;
97651                   } break;
97652
97653                 case SPECIAL_AUTHORITY_SLASHES:
97654                   state = SPECIAL_AUTHORITY_IGNORE_SLASHES;
97655                   if (chr != '/' || charAt(buffer, pointer + 1) != '/') continue;
97656                   pointer++;
97657                   break;
97658
97659                 case SPECIAL_AUTHORITY_IGNORE_SLASHES:
97660                   if (chr != '/' && chr != '\\') {
97661                     state = AUTHORITY;
97662                     continue;
97663                   } break;
97664
97665                 case AUTHORITY:
97666                   if (chr == '@') {
97667                     if (seenAt) buffer = '%40' + buffer;
97668                     seenAt = true;
97669                     bufferCodePoints = arrayFrom(buffer);
97670                     for (var i = 0; i < bufferCodePoints.length; i++) {
97671                       var codePoint = bufferCodePoints[i];
97672                       if (codePoint == ':' && !seenPasswordToken) {
97673                         seenPasswordToken = true;
97674                         continue;
97675                       }
97676                       var encodedCodePoints = percentEncode(codePoint, userinfoPercentEncodeSet);
97677                       if (seenPasswordToken) url.password += encodedCodePoints;
97678                       else url.username += encodedCodePoints;
97679                     }
97680                     buffer = '';
97681                   } else if (
97682                     chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
97683                     (chr == '\\' && url.isSpecial())
97684                   ) {
97685                     if (seenAt && buffer == '') return INVALID_AUTHORITY;
97686                     pointer -= arrayFrom(buffer).length + 1;
97687                     buffer = '';
97688                     state = HOST;
97689                   } else buffer += chr;
97690                   break;
97691
97692                 case HOST:
97693                 case HOSTNAME:
97694                   if (stateOverride && url.scheme == 'file') {
97695                     state = FILE_HOST;
97696                     continue;
97697                   } else if (chr == ':' && !seenBracket) {
97698                     if (buffer == '') return INVALID_HOST;
97699                     failure = url.parseHost(buffer);
97700                     if (failure) return failure;
97701                     buffer = '';
97702                     state = PORT;
97703                     if (stateOverride == HOSTNAME) return;
97704                   } else if (
97705                     chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
97706                     (chr == '\\' && url.isSpecial())
97707                   ) {
97708                     if (url.isSpecial() && buffer == '') return INVALID_HOST;
97709                     if (stateOverride && buffer == '' && (url.includesCredentials() || url.port !== null)) return;
97710                     failure = url.parseHost(buffer);
97711                     if (failure) return failure;
97712                     buffer = '';
97713                     state = PATH_START;
97714                     if (stateOverride) return;
97715                     continue;
97716                   } else {
97717                     if (chr == '[') seenBracket = true;
97718                     else if (chr == ']') seenBracket = false;
97719                     buffer += chr;
97720                   } break;
97721
97722                 case PORT:
97723                   if (exec(DIGIT, chr)) {
97724                     buffer += chr;
97725                   } else if (
97726                     chr == EOF || chr == '/' || chr == '?' || chr == '#' ||
97727                     (chr == '\\' && url.isSpecial()) ||
97728                     stateOverride
97729                   ) {
97730                     if (buffer != '') {
97731                       var port = parseInt$1(buffer, 10);
97732                       if (port > 0xFFFF) return INVALID_PORT;
97733                       url.port = (url.isSpecial() && port === specialSchemes[url.scheme]) ? null : port;
97734                       buffer = '';
97735                     }
97736                     if (stateOverride) return;
97737                     state = PATH_START;
97738                     continue;
97739                   } else return INVALID_PORT;
97740                   break;
97741
97742                 case FILE:
97743                   url.scheme = 'file';
97744                   if (chr == '/' || chr == '\\') state = FILE_SLASH;
97745                   else if (base && base.scheme == 'file') {
97746                     if (chr == EOF) {
97747                       url.host = base.host;
97748                       url.path = arraySlice(base.path);
97749                       url.query = base.query;
97750                     } else if (chr == '?') {
97751                       url.host = base.host;
97752                       url.path = arraySlice(base.path);
97753                       url.query = '';
97754                       state = QUERY;
97755                     } else if (chr == '#') {
97756                       url.host = base.host;
97757                       url.path = arraySlice(base.path);
97758                       url.query = base.query;
97759                       url.fragment = '';
97760                       state = FRAGMENT;
97761                     } else {
97762                       if (!startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) {
97763                         url.host = base.host;
97764                         url.path = arraySlice(base.path);
97765                         url.shortenPath();
97766                       }
97767                       state = PATH;
97768                       continue;
97769                     }
97770                   } else {
97771                     state = PATH;
97772                     continue;
97773                   } break;
97774
97775                 case FILE_SLASH:
97776                   if (chr == '/' || chr == '\\') {
97777                     state = FILE_HOST;
97778                     break;
97779                   }
97780                   if (base && base.scheme == 'file' && !startsWithWindowsDriveLetter(join(arraySlice(codePoints, pointer), ''))) {
97781                     if (isWindowsDriveLetter(base.path[0], true)) push(url.path, base.path[0]);
97782                     else url.host = base.host;
97783                   }
97784                   state = PATH;
97785                   continue;
97786
97787                 case FILE_HOST:
97788                   if (chr == EOF || chr == '/' || chr == '\\' || chr == '?' || chr == '#') {
97789                     if (!stateOverride && isWindowsDriveLetter(buffer)) {
97790                       state = PATH;
97791                     } else if (buffer == '') {
97792                       url.host = '';
97793                       if (stateOverride) return;
97794                       state = PATH_START;
97795                     } else {
97796                       failure = url.parseHost(buffer);
97797                       if (failure) return failure;
97798                       if (url.host == 'localhost') url.host = '';
97799                       if (stateOverride) return;
97800                       buffer = '';
97801                       state = PATH_START;
97802                     } continue;
97803                   } else buffer += chr;
97804                   break;
97805
97806                 case PATH_START:
97807                   if (url.isSpecial()) {
97808                     state = PATH;
97809                     if (chr != '/' && chr != '\\') continue;
97810                   } else if (!stateOverride && chr == '?') {
97811                     url.query = '';
97812                     state = QUERY;
97813                   } else if (!stateOverride && chr == '#') {
97814                     url.fragment = '';
97815                     state = FRAGMENT;
97816                   } else if (chr != EOF) {
97817                     state = PATH;
97818                     if (chr != '/') continue;
97819                   } break;
97820
97821                 case PATH:
97822                   if (
97823                     chr == EOF || chr == '/' ||
97824                     (chr == '\\' && url.isSpecial()) ||
97825                     (!stateOverride && (chr == '?' || chr == '#'))
97826                   ) {
97827                     if (isDoubleDot(buffer)) {
97828                       url.shortenPath();
97829                       if (chr != '/' && !(chr == '\\' && url.isSpecial())) {
97830                         push(url.path, '');
97831                       }
97832                     } else if (isSingleDot(buffer)) {
97833                       if (chr != '/' && !(chr == '\\' && url.isSpecial())) {
97834                         push(url.path, '');
97835                       }
97836                     } else {
97837                       if (url.scheme == 'file' && !url.path.length && isWindowsDriveLetter(buffer)) {
97838                         if (url.host) url.host = '';
97839                         buffer = charAt(buffer, 0) + ':'; // normalize windows drive letter
97840                       }
97841                       push(url.path, buffer);
97842                     }
97843                     buffer = '';
97844                     if (url.scheme == 'file' && (chr == EOF || chr == '?' || chr == '#')) {
97845                       while (url.path.length > 1 && url.path[0] === '') {
97846                         shift(url.path);
97847                       }
97848                     }
97849                     if (chr == '?') {
97850                       url.query = '';
97851                       state = QUERY;
97852                     } else if (chr == '#') {
97853                       url.fragment = '';
97854                       state = FRAGMENT;
97855                     }
97856                   } else {
97857                     buffer += percentEncode(chr, pathPercentEncodeSet);
97858                   } break;
97859
97860                 case CANNOT_BE_A_BASE_URL_PATH:
97861                   if (chr == '?') {
97862                     url.query = '';
97863                     state = QUERY;
97864                   } else if (chr == '#') {
97865                     url.fragment = '';
97866                     state = FRAGMENT;
97867                   } else if (chr != EOF) {
97868                     url.path[0] += percentEncode(chr, C0ControlPercentEncodeSet);
97869                   } break;
97870
97871                 case QUERY:
97872                   if (!stateOverride && chr == '#') {
97873                     url.fragment = '';
97874                     state = FRAGMENT;
97875                   } else if (chr != EOF) {
97876                     if (chr == "'" && url.isSpecial()) url.query += '%27';
97877                     else if (chr == '#') url.query += '%23';
97878                     else url.query += percentEncode(chr, C0ControlPercentEncodeSet);
97879                   } break;
97880
97881                 case FRAGMENT:
97882                   if (chr != EOF) url.fragment += percentEncode(chr, fragmentPercentEncodeSet);
97883                   break;
97884               }
97885
97886               pointer++;
97887             }
97888           },
97889           // https://url.spec.whatwg.org/#host-parsing
97890           parseHost: function (input) {
97891             var result, codePoints, index;
97892             if (charAt(input, 0) == '[') {
97893               if (charAt(input, input.length - 1) != ']') return INVALID_HOST;
97894               result = parseIPv6(stringSlice(input, 1, -1));
97895               if (!result) return INVALID_HOST;
97896               this.host = result;
97897             // opaque host
97898             } else if (!this.isSpecial()) {
97899               if (exec(FORBIDDEN_HOST_CODE_POINT_EXCLUDING_PERCENT, input)) return INVALID_HOST;
97900               result = '';
97901               codePoints = arrayFrom(input);
97902               for (index = 0; index < codePoints.length; index++) {
97903                 result += percentEncode(codePoints[index], C0ControlPercentEncodeSet);
97904               }
97905               this.host = result;
97906             } else {
97907               input = toASCII(input);
97908               if (exec(FORBIDDEN_HOST_CODE_POINT, input)) return INVALID_HOST;
97909               result = parseIPv4(input);
97910               if (result === null) return INVALID_HOST;
97911               this.host = result;
97912             }
97913           },
97914           // https://url.spec.whatwg.org/#cannot-have-a-username-password-port
97915           cannotHaveUsernamePasswordPort: function () {
97916             return !this.host || this.cannotBeABaseURL || this.scheme == 'file';
97917           },
97918           // https://url.spec.whatwg.org/#include-credentials
97919           includesCredentials: function () {
97920             return this.username != '' || this.password != '';
97921           },
97922           // https://url.spec.whatwg.org/#is-special
97923           isSpecial: function () {
97924             return hasOwn(specialSchemes, this.scheme);
97925           },
97926           // https://url.spec.whatwg.org/#shorten-a-urls-path
97927           shortenPath: function () {
97928             var path = this.path;
97929             var pathSize = path.length;
97930             if (pathSize && (this.scheme != 'file' || pathSize != 1 || !isWindowsDriveLetter(path[0], true))) {
97931               path.length--;
97932             }
97933           },
97934           // https://url.spec.whatwg.org/#concept-url-serializer
97935           serialize: function () {
97936             var url = this;
97937             var scheme = url.scheme;
97938             var username = url.username;
97939             var password = url.password;
97940             var host = url.host;
97941             var port = url.port;
97942             var path = url.path;
97943             var query = url.query;
97944             var fragment = url.fragment;
97945             var output = scheme + ':';
97946             if (host !== null) {
97947               output += '//';
97948               if (url.includesCredentials()) {
97949                 output += username + (password ? ':' + password : '') + '@';
97950               }
97951               output += serializeHost(host);
97952               if (port !== null) output += ':' + port;
97953             } else if (scheme == 'file') output += '//';
97954             output += url.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : '';
97955             if (query !== null) output += '?' + query;
97956             if (fragment !== null) output += '#' + fragment;
97957             return output;
97958           },
97959           // https://url.spec.whatwg.org/#dom-url-href
97960           setHref: function (href) {
97961             var failure = this.parse(href);
97962             if (failure) throw TypeError$1(failure);
97963             this.searchParams.update();
97964           },
97965           // https://url.spec.whatwg.org/#dom-url-origin
97966           getOrigin: function () {
97967             var scheme = this.scheme;
97968             var port = this.port;
97969             if (scheme == 'blob') try {
97970               return new URLConstructor(scheme.path[0]).origin;
97971             } catch (error) {
97972               return 'null';
97973             }
97974             if (scheme == 'file' || !this.isSpecial()) return 'null';
97975             return scheme + '://' + serializeHost(this.host) + (port !== null ? ':' + port : '');
97976           },
97977           // https://url.spec.whatwg.org/#dom-url-protocol
97978           getProtocol: function () {
97979             return this.scheme + ':';
97980           },
97981           setProtocol: function (protocol) {
97982             this.parse($toString(protocol) + ':', SCHEME_START);
97983           },
97984           // https://url.spec.whatwg.org/#dom-url-username
97985           getUsername: function () {
97986             return this.username;
97987           },
97988           setUsername: function (username) {
97989             var codePoints = arrayFrom($toString(username));
97990             if (this.cannotHaveUsernamePasswordPort()) return;
97991             this.username = '';
97992             for (var i = 0; i < codePoints.length; i++) {
97993               this.username += percentEncode(codePoints[i], userinfoPercentEncodeSet);
97994             }
97995           },
97996           // https://url.spec.whatwg.org/#dom-url-password
97997           getPassword: function () {
97998             return this.password;
97999           },
98000           setPassword: function (password) {
98001             var codePoints = arrayFrom($toString(password));
98002             if (this.cannotHaveUsernamePasswordPort()) return;
98003             this.password = '';
98004             for (var i = 0; i < codePoints.length; i++) {
98005               this.password += percentEncode(codePoints[i], userinfoPercentEncodeSet);
98006             }
98007           },
98008           // https://url.spec.whatwg.org/#dom-url-host
98009           getHost: function () {
98010             var host = this.host;
98011             var port = this.port;
98012             return host === null ? ''
98013               : port === null ? serializeHost(host)
98014               : serializeHost(host) + ':' + port;
98015           },
98016           setHost: function (host) {
98017             if (this.cannotBeABaseURL) return;
98018             this.parse(host, HOST);
98019           },
98020           // https://url.spec.whatwg.org/#dom-url-hostname
98021           getHostname: function () {
98022             var host = this.host;
98023             return host === null ? '' : serializeHost(host);
98024           },
98025           setHostname: function (hostname) {
98026             if (this.cannotBeABaseURL) return;
98027             this.parse(hostname, HOSTNAME);
98028           },
98029           // https://url.spec.whatwg.org/#dom-url-port
98030           getPort: function () {
98031             var port = this.port;
98032             return port === null ? '' : $toString(port);
98033           },
98034           setPort: function (port) {
98035             if (this.cannotHaveUsernamePasswordPort()) return;
98036             port = $toString(port);
98037             if (port == '') this.port = null;
98038             else this.parse(port, PORT);
98039           },
98040           // https://url.spec.whatwg.org/#dom-url-pathname
98041           getPathname: function () {
98042             var path = this.path;
98043             return this.cannotBeABaseURL ? path[0] : path.length ? '/' + join(path, '/') : '';
98044           },
98045           setPathname: function (pathname) {
98046             if (this.cannotBeABaseURL) return;
98047             this.path = [];
98048             this.parse(pathname, PATH_START);
98049           },
98050           // https://url.spec.whatwg.org/#dom-url-search
98051           getSearch: function () {
98052             var query = this.query;
98053             return query ? '?' + query : '';
98054           },
98055           setSearch: function (search) {
98056             search = $toString(search);
98057             if (search == '') {
98058               this.query = null;
98059             } else {
98060               if ('?' == charAt(search, 0)) search = stringSlice(search, 1);
98061               this.query = '';
98062               this.parse(search, QUERY);
98063             }
98064             this.searchParams.update();
98065           },
98066           // https://url.spec.whatwg.org/#dom-url-searchparams
98067           getSearchParams: function () {
98068             return this.searchParams.facade;
98069           },
98070           // https://url.spec.whatwg.org/#dom-url-hash
98071           getHash: function () {
98072             var fragment = this.fragment;
98073             return fragment ? '#' + fragment : '';
98074           },
98075           setHash: function (hash) {
98076             hash = $toString(hash);
98077             if (hash == '') {
98078               this.fragment = null;
98079               return;
98080             }
98081             if ('#' == charAt(hash, 0)) hash = stringSlice(hash, 1);
98082             this.fragment = '';
98083             this.parse(hash, FRAGMENT);
98084           },
98085           update: function () {
98086             this.query = this.searchParams.serialize() || null;
98087           }
98088         };
98089
98090         // `URL` constructor
98091         // https://url.spec.whatwg.org/#url-class
98092         var URLConstructor = function URL(url /* , base */) {
98093           var that = anInstance(this, URLPrototype);
98094           var base = validateArgumentsLength(arguments.length, 1) > 1 ? arguments[1] : undefined;
98095           var state = setInternalState(that, new URLState(url, false, base));
98096           if (!DESCRIPTORS) {
98097             that.href = state.serialize();
98098             that.origin = state.getOrigin();
98099             that.protocol = state.getProtocol();
98100             that.username = state.getUsername();
98101             that.password = state.getPassword();
98102             that.host = state.getHost();
98103             that.hostname = state.getHostname();
98104             that.port = state.getPort();
98105             that.pathname = state.getPathname();
98106             that.search = state.getSearch();
98107             that.searchParams = state.getSearchParams();
98108             that.hash = state.getHash();
98109           }
98110         };
98111
98112         var URLPrototype = URLConstructor.prototype;
98113
98114         var accessorDescriptor = function (getter, setter) {
98115           return {
98116             get: function () {
98117               return getInternalURLState(this)[getter]();
98118             },
98119             set: setter && function (value) {
98120               return getInternalURLState(this)[setter](value);
98121             },
98122             configurable: true,
98123             enumerable: true
98124           };
98125         };
98126
98127         if (DESCRIPTORS) {
98128           defineProperties(URLPrototype, {
98129             // `URL.prototype.href` accessors pair
98130             // https://url.spec.whatwg.org/#dom-url-href
98131             href: accessorDescriptor('serialize', 'setHref'),
98132             // `URL.prototype.origin` getter
98133             // https://url.spec.whatwg.org/#dom-url-origin
98134             origin: accessorDescriptor('getOrigin'),
98135             // `URL.prototype.protocol` accessors pair
98136             // https://url.spec.whatwg.org/#dom-url-protocol
98137             protocol: accessorDescriptor('getProtocol', 'setProtocol'),
98138             // `URL.prototype.username` accessors pair
98139             // https://url.spec.whatwg.org/#dom-url-username
98140             username: accessorDescriptor('getUsername', 'setUsername'),
98141             // `URL.prototype.password` accessors pair
98142             // https://url.spec.whatwg.org/#dom-url-password
98143             password: accessorDescriptor('getPassword', 'setPassword'),
98144             // `URL.prototype.host` accessors pair
98145             // https://url.spec.whatwg.org/#dom-url-host
98146             host: accessorDescriptor('getHost', 'setHost'),
98147             // `URL.prototype.hostname` accessors pair
98148             // https://url.spec.whatwg.org/#dom-url-hostname
98149             hostname: accessorDescriptor('getHostname', 'setHostname'),
98150             // `URL.prototype.port` accessors pair
98151             // https://url.spec.whatwg.org/#dom-url-port
98152             port: accessorDescriptor('getPort', 'setPort'),
98153             // `URL.prototype.pathname` accessors pair
98154             // https://url.spec.whatwg.org/#dom-url-pathname
98155             pathname: accessorDescriptor('getPathname', 'setPathname'),
98156             // `URL.prototype.search` accessors pair
98157             // https://url.spec.whatwg.org/#dom-url-search
98158             search: accessorDescriptor('getSearch', 'setSearch'),
98159             // `URL.prototype.searchParams` getter
98160             // https://url.spec.whatwg.org/#dom-url-searchparams
98161             searchParams: accessorDescriptor('getSearchParams'),
98162             // `URL.prototype.hash` accessors pair
98163             // https://url.spec.whatwg.org/#dom-url-hash
98164             hash: accessorDescriptor('getHash', 'setHash')
98165           });
98166         }
98167
98168         // `URL.prototype.toJSON` method
98169         // https://url.spec.whatwg.org/#dom-url-tojson
98170         redefine(URLPrototype, 'toJSON', function toJSON() {
98171           return getInternalURLState(this).serialize();
98172         }, { enumerable: true });
98173
98174         // `URL.prototype.toString` method
98175         // https://url.spec.whatwg.org/#URL-stringification-behavior
98176         redefine(URLPrototype, 'toString', function toString() {
98177           return getInternalURLState(this).serialize();
98178         }, { enumerable: true });
98179
98180         if (NativeURL) {
98181           var nativeCreateObjectURL = NativeURL.createObjectURL;
98182           var nativeRevokeObjectURL = NativeURL.revokeObjectURL;
98183           // `URL.createObjectURL` method
98184           // https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL
98185           if (nativeCreateObjectURL) redefine(URLConstructor, 'createObjectURL', bind$2(nativeCreateObjectURL, NativeURL));
98186           // `URL.revokeObjectURL` method
98187           // https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL
98188           if (nativeRevokeObjectURL) redefine(URLConstructor, 'revokeObjectURL', bind$2(nativeRevokeObjectURL, NativeURL));
98189         }
98190
98191         setToStringTag(URLConstructor, 'URL');
98192
98193         $({ global: true, forced: !USE_NATIVE_URL, sham: !DESCRIPTORS }, {
98194           URL: URLConstructor
98195         });
98196
98197         function uiFieldText(field, context) {
98198           var dispatch = dispatch$8('change');
98199           var input = select(null);
98200           var outlinkButton = select(null);
98201           var wrap = select(null);
98202           var _entityIDs = [];
98203
98204           var _tags;
98205
98206           var _phoneFormats = {};
98207
98208           if (field.type === 'tel') {
98209             _mainFileFetcher.get('phone_formats').then(function (d) {
98210               _phoneFormats = d;
98211               updatePhonePlaceholder();
98212             })["catch"](function () {
98213               /* ignore */
98214             });
98215           }
98216
98217           function calcLocked() {
98218             // Protect certain fields that have a companion `*:wikidata` value
98219             var isLocked = (field.id === 'brand' || field.id === 'network' || field.id === 'operator' || field.id === 'flag') && _entityIDs.length && _entityIDs.some(function (entityID) {
98220               var entity = context.graph().hasEntity(entityID);
98221               if (!entity) return false; // Features linked to Wikidata are likely important and should be protected
98222
98223               if (entity.tags.wikidata) return true;
98224               var preset = _mainPresetIndex.match(entity, context.graph());
98225               var isSuggestion = preset && preset.suggestion; // Lock the field if there is a value and a companion `*:wikidata` value
98226
98227               var which = field.id; // 'brand', 'network', 'operator', 'flag'
98228
98229               return isSuggestion && !!entity.tags[which] && !!entity.tags[which + ':wikidata'];
98230             });
98231
98232             field.locked(isLocked);
98233           }
98234
98235           function i(selection) {
98236             calcLocked();
98237             var isLocked = field.locked();
98238             wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98239             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
98240             input = wrap.selectAll('input').data([0]);
98241             input = input.enter().append('input').attr('type', field.type === 'identifier' ? 'text' : field.type).attr('id', field.domId).classed(field.type, true).call(utilNoAuto).merge(input);
98242             input.classed('disabled', !!isLocked).attr('readonly', isLocked || null).on('input', change(true)).on('blur', change()).on('change', change());
98243
98244             if (field.type === 'tel') {
98245               updatePhonePlaceholder();
98246             } else if (field.type === 'number') {
98247               var rtl = _mainLocalizer.textDirection() === 'rtl';
98248               input.attr('type', 'text');
98249               var inc = field.increment;
98250               var buttons = wrap.selectAll('.increment, .decrement').data(rtl ? [inc, -inc] : [-inc, inc]);
98251               buttons.enter().append('button').attr('class', function (d) {
98252                 var which = d > 0 ? 'increment' : 'decrement';
98253                 return 'form-field-button ' + which;
98254               }).attr('title', function (d) {
98255                 var which = d > 0 ? 'increment' : 'decrement';
98256                 return _t("inspector.".concat(which));
98257               }).merge(buttons).on('click', function (d3_event, d) {
98258                 d3_event.preventDefault();
98259                 var raw_vals = input.node().value || '0';
98260                 var vals = raw_vals.split(';');
98261                 vals = vals.map(function (v) {
98262                   var num = parseFloat(v.trim(), 10);
98263                   return isFinite(num) ? clamped(num + d) : v.trim();
98264                 });
98265                 input.node().value = vals.join(';');
98266                 change()();
98267               });
98268             } else if (field.type === 'identifier' && field.urlFormat && field.pattern) {
98269               input.attr('type', 'text');
98270               outlinkButton = wrap.selectAll('.foreign-id-permalink').data([0]);
98271               outlinkButton.enter().append('button').call(svgIcon('#iD-icon-out-link')).attr('class', 'form-field-button foreign-id-permalink').attr('title', function () {
98272                 var domainResults = /^https?:\/\/(.{1,}?)\//.exec(field.urlFormat);
98273
98274                 if (domainResults.length >= 2 && domainResults[1]) {
98275                   var domain = domainResults[1];
98276                   return _t('icons.view_on', {
98277                     domain: domain
98278                   });
98279                 }
98280
98281                 return '';
98282               }).on('click', function (d3_event) {
98283                 d3_event.preventDefault();
98284                 var value = validIdentifierValueForLink();
98285
98286                 if (value) {
98287                   var url = field.urlFormat.replace(/{value}/, encodeURIComponent(value));
98288                   window.open(url, '_blank');
98289                 }
98290               }).merge(outlinkButton);
98291             } else if (field.type === 'url') {
98292               input.attr('type', 'text');
98293               outlinkButton = wrap.selectAll('.foreign-id-permalink').data([0]);
98294               outlinkButton.enter().append('button').call(svgIcon('#iD-icon-out-link')).attr('class', 'form-field-button foreign-id-permalink').attr('title', function () {
98295                 return _t('icons.visit_website');
98296               }).on('click', function (d3_event) {
98297                 d3_event.preventDefault();
98298                 var value = validIdentifierValueForLink();
98299                 if (value) window.open(value, '_blank');
98300               }).merge(outlinkButton);
98301             } else if (field.key.split(':').includes('colour')) {
98302               input.attr('type', 'text');
98303               updateColourPreview();
98304             }
98305           }
98306
98307           function isColourValid(colour) {
98308             if (!colour.match(/^(#([0-9a-fA-F]{3}){1,2}|\w+)$/)) {
98309               // OSM only supports hex or named colors
98310               return false;
98311             } else if (!CSS.supports('color', colour) || ['unset', 'inherit', 'initial', 'revert'].includes(colour)) {
98312               // see https://stackoverflow.com/a/68217760/1627467
98313               return false;
98314             }
98315
98316             return true;
98317           }
98318
98319           function updateColourPreview() {
98320             wrap.selectAll('.colour-preview').remove();
98321             var colour = utilGetSetValue(input);
98322             if (!isColourValid(colour) && colour !== '') return;
98323             var colourSelector = wrap.selectAll('.colour-selector').data([0]);
98324             outlinkButton = wrap.selectAll('.colour-preview').data([colour]);
98325             colourSelector.enter().append('input').attr('type', 'color').attr('class', 'form-field-button colour-selector').attr('value', colour).on('input', debounce(function (d3_event) {
98326               d3_event.preventDefault();
98327               var colour = this.value;
98328               if (!isColourValid(colour)) return;
98329               utilGetSetValue(input, this.value);
98330               change()();
98331               updateColourPreview();
98332             }, 100));
98333             outlinkButton = outlinkButton.enter().append('div').attr('class', 'form-field-button colour-preview').append('div').style('background-color', function (d) {
98334               return d;
98335             }).attr('class', 'colour-box');
98336
98337             if (colour === '') {
98338               outlinkButton = outlinkButton.call(svgIcon('#iD-icon-edit'));
98339             }
98340
98341             outlinkButton.on('click', function () {
98342               return wrap.select('.colour-selector').node().click();
98343             }).merge(outlinkButton);
98344           }
98345
98346           function updatePhonePlaceholder() {
98347             if (input.empty() || !Object.keys(_phoneFormats).length) return;
98348             var extent = combinedEntityExtent();
98349             var countryCode = extent && iso1A2Code(extent.center());
98350
98351             var format = countryCode && _phoneFormats[countryCode.toLowerCase()];
98352
98353             if (format) input.attr('placeholder', format);
98354           }
98355
98356           function validIdentifierValueForLink() {
98357             var value = utilGetSetValue(input).trim();
98358
98359             if (field.type === 'url' && value) {
98360               try {
98361                 return new URL(value).href;
98362               } catch (e) {
98363                 return null;
98364               }
98365             }
98366
98367             if (field.type === 'identifier' && field.pattern) {
98368               return value && value.match(new RegExp(field.pattern))[0];
98369             }
98370
98371             return null;
98372           } // clamp number to min/max
98373
98374
98375           function clamped(num) {
98376             if (field.minValue !== undefined) {
98377               num = Math.max(num, field.minValue);
98378             }
98379
98380             if (field.maxValue !== undefined) {
98381               num = Math.min(num, field.maxValue);
98382             }
98383
98384             return num;
98385           }
98386
98387           function change(onInput) {
98388             return function () {
98389               var t = {};
98390               var val = utilGetSetValue(input);
98391               if (!onInput) val = context.cleanTagValue(val); // don't override multiple values with blank string
98392
98393               if (!val && Array.isArray(_tags[field.key])) return;
98394
98395               if (!onInput) {
98396                 if (field.type === 'number' && val) {
98397                   var vals = val.split(';');
98398                   vals = vals.map(function (v) {
98399                     var num = parseFloat(v.trim(), 10);
98400                     return isFinite(num) ? clamped(num) : v.trim();
98401                   });
98402                   val = vals.join(';');
98403                 }
98404
98405                 utilGetSetValue(input, val);
98406               }
98407
98408               t[field.key] = val || undefined;
98409               dispatch.call('change', this, t, onInput);
98410             };
98411           }
98412
98413           i.entityIDs = function (val) {
98414             if (!arguments.length) return _entityIDs;
98415             _entityIDs = val;
98416             return i;
98417           };
98418
98419           i.tags = function (tags) {
98420             _tags = tags;
98421             var isMixed = Array.isArray(tags[field.key]);
98422             utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : '').attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : undefined).attr('placeholder', isMixed ? _t('inspector.multiple_values') : field.placeholder() || _t('inspector.unknown')).classed('mixed', isMixed);
98423             if (field.key.split(':').includes('colour')) updateColourPreview();
98424
98425             if (outlinkButton && !outlinkButton.empty()) {
98426               var disabled = !validIdentifierValueForLink();
98427               outlinkButton.classed('disabled', disabled);
98428             }
98429           };
98430
98431           i.focus = function () {
98432             var node = input.node();
98433             if (node) node.focus();
98434           };
98435
98436           function combinedEntityExtent() {
98437             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
98438           }
98439
98440           return utilRebind(i, dispatch, 'on');
98441         }
98442
98443         function uiFieldAccess(field, context) {
98444           var dispatch = dispatch$8('change');
98445           var items = select(null);
98446
98447           var _tags;
98448
98449           function access(selection) {
98450             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98451             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
98452             var list = wrap.selectAll('ul').data([0]);
98453             list = list.enter().append('ul').attr('class', 'rows').merge(list);
98454             items = list.selectAll('li').data(field.keys); // Enter
98455
98456             var enter = items.enter().append('li').attr('class', function (d) {
98457               return 'labeled-input preset-access-' + d;
98458             });
98459             enter.append('span').attr('class', 'label preset-label-access').attr('for', function (d) {
98460               return 'preset-input-access-' + d;
98461             }).html(function (d) {
98462               return field.t.html('types.' + d);
98463             });
98464             enter.append('div').attr('class', 'preset-input-access-wrap').append('input').attr('type', 'text').attr('class', function (d) {
98465               return 'preset-input-access preset-input-access-' + d;
98466             }).call(utilNoAuto).each(function (d) {
98467               select(this).call(uiCombobox(context, 'access-' + d).data(access.options(d)));
98468             }); // Update
98469
98470             items = items.merge(enter);
98471             wrap.selectAll('.preset-input-access').on('change', change).on('blur', change);
98472           }
98473
98474           function change(d3_event, d) {
98475             var tag = {};
98476             var value = context.cleanTagValue(utilGetSetValue(select(this))); // don't override multiple values with blank string
98477
98478             if (!value && typeof _tags[d] !== 'string') return;
98479             tag[d] = value || undefined;
98480             dispatch.call('change', this, tag);
98481           }
98482
98483           access.options = function (type) {
98484             var options = ['no', 'permissive', 'private', 'permit', 'destination', 'customers', 'unknown'];
98485
98486             if (type !== 'access') {
98487               options.unshift('yes');
98488               options.push('designated');
98489
98490               if (type === 'bicycle') {
98491                 options.push('dismount');
98492               }
98493             }
98494
98495             return options.map(function (option) {
98496               return {
98497                 title: field.t('options.' + option + '.description'),
98498                 value: option
98499               };
98500             });
98501           };
98502
98503           var placeholdersByHighway = {
98504             footway: {
98505               foot: 'designated',
98506               motor_vehicle: 'no'
98507             },
98508             steps: {
98509               foot: 'yes',
98510               motor_vehicle: 'no',
98511               bicycle: 'no',
98512               horse: 'no'
98513             },
98514             pedestrian: {
98515               foot: 'yes',
98516               motor_vehicle: 'no'
98517             },
98518             cycleway: {
98519               motor_vehicle: 'no',
98520               bicycle: 'designated'
98521             },
98522             bridleway: {
98523               motor_vehicle: 'no',
98524               horse: 'designated'
98525             },
98526             path: {
98527               foot: 'yes',
98528               motor_vehicle: 'no',
98529               bicycle: 'yes',
98530               horse: 'yes'
98531             },
98532             motorway: {
98533               foot: 'no',
98534               motor_vehicle: 'yes',
98535               bicycle: 'no',
98536               horse: 'no'
98537             },
98538             trunk: {
98539               motor_vehicle: 'yes'
98540             },
98541             primary: {
98542               foot: 'yes',
98543               motor_vehicle: 'yes',
98544               bicycle: 'yes',
98545               horse: 'yes'
98546             },
98547             secondary: {
98548               foot: 'yes',
98549               motor_vehicle: 'yes',
98550               bicycle: 'yes',
98551               horse: 'yes'
98552             },
98553             tertiary: {
98554               foot: 'yes',
98555               motor_vehicle: 'yes',
98556               bicycle: 'yes',
98557               horse: 'yes'
98558             },
98559             residential: {
98560               foot: 'yes',
98561               motor_vehicle: 'yes',
98562               bicycle: 'yes',
98563               horse: 'yes'
98564             },
98565             unclassified: {
98566               foot: 'yes',
98567               motor_vehicle: 'yes',
98568               bicycle: 'yes',
98569               horse: 'yes'
98570             },
98571             service: {
98572               foot: 'yes',
98573               motor_vehicle: 'yes',
98574               bicycle: 'yes',
98575               horse: 'yes'
98576             },
98577             motorway_link: {
98578               foot: 'no',
98579               motor_vehicle: 'yes',
98580               bicycle: 'no',
98581               horse: 'no'
98582             },
98583             trunk_link: {
98584               motor_vehicle: 'yes'
98585             },
98586             primary_link: {
98587               foot: 'yes',
98588               motor_vehicle: 'yes',
98589               bicycle: 'yes',
98590               horse: 'yes'
98591             },
98592             secondary_link: {
98593               foot: 'yes',
98594               motor_vehicle: 'yes',
98595               bicycle: 'yes',
98596               horse: 'yes'
98597             },
98598             tertiary_link: {
98599               foot: 'yes',
98600               motor_vehicle: 'yes',
98601               bicycle: 'yes',
98602               horse: 'yes'
98603             }
98604           };
98605
98606           access.tags = function (tags) {
98607             _tags = tags;
98608             utilGetSetValue(items.selectAll('.preset-input-access'), function (d) {
98609               return typeof tags[d] === 'string' ? tags[d] : '';
98610             }).classed('mixed', function (d) {
98611               return tags[d] && Array.isArray(tags[d]);
98612             }).attr('title', function (d) {
98613               return tags[d] && Array.isArray(tags[d]) && tags[d].filter(Boolean).join('\n');
98614             }).attr('placeholder', function (d) {
98615               if (tags[d] && Array.isArray(tags[d])) {
98616                 return _t('inspector.multiple_values');
98617               }
98618
98619               if (d === 'access') {
98620                 return 'yes';
98621               }
98622
98623               if (tags.access && typeof tags.access === 'string') {
98624                 return tags.access;
98625               }
98626
98627               if (tags.highway) {
98628                 if (typeof tags.highway === 'string') {
98629                   if (placeholdersByHighway[tags.highway] && placeholdersByHighway[tags.highway][d]) {
98630                     return placeholdersByHighway[tags.highway][d];
98631                   }
98632                 } else {
98633                   var impliedAccesses = tags.highway.filter(Boolean).map(function (highwayVal) {
98634                     return placeholdersByHighway[highwayVal] && placeholdersByHighway[highwayVal][d];
98635                   }).filter(Boolean);
98636
98637                   if (impliedAccesses.length === tags.highway.length && new Set(impliedAccesses).size === 1) {
98638                     // if all the highway values have the same implied access for this type then use that
98639                     return impliedAccesses[0];
98640                   }
98641                 }
98642               }
98643
98644               return field.placeholder();
98645             });
98646           };
98647
98648           access.focus = function () {
98649             items.selectAll('.preset-input-access').node().focus();
98650           };
98651
98652           return utilRebind(access, dispatch, 'on');
98653         }
98654
98655         function uiFieldAddress(field, context) {
98656           var dispatch = dispatch$8('change');
98657
98658           var _selection = select(null);
98659
98660           var _wrap = select(null);
98661
98662           var addrField = _mainPresetIndex.field('address'); // needed for placeholder strings
98663
98664           var _entityIDs = [];
98665
98666           var _tags;
98667
98668           var _countryCode;
98669
98670           var _addressFormats = [{
98671             format: [['housenumber', 'street'], ['city', 'postcode']]
98672           }];
98673           _mainFileFetcher.get('address_formats').then(function (d) {
98674             _addressFormats = d;
98675
98676             if (!_selection.empty()) {
98677               _selection.call(address);
98678             }
98679           })["catch"](function () {
98680             /* ignore */
98681           });
98682
98683           function getNearStreets() {
98684             var extent = combinedEntityExtent();
98685             var l = extent.center();
98686             var box = geoExtent(l).padByMeters(200);
98687             var streets = context.history().intersects(box).filter(isAddressable).map(function (d) {
98688               var loc = context.projection([(extent[0][0] + extent[1][0]) / 2, (extent[0][1] + extent[1][1]) / 2]);
98689               var choice = geoChooseEdge(context.graph().childNodes(d), loc, context.projection);
98690               return {
98691                 title: d.tags.name,
98692                 value: d.tags.name,
98693                 dist: choice.distance
98694               };
98695             }).sort(function (a, b) {
98696               return a.dist - b.dist;
98697             });
98698             return utilArrayUniqBy(streets, 'value');
98699
98700             function isAddressable(d) {
98701               return d.tags.highway && d.tags.name && d.type === 'way';
98702             }
98703           }
98704
98705           function getNearCities() {
98706             var extent = combinedEntityExtent();
98707             var l = extent.center();
98708             var box = geoExtent(l).padByMeters(200);
98709             var cities = context.history().intersects(box).filter(isAddressable).map(function (d) {
98710               return {
98711                 title: d.tags['addr:city'] || d.tags.name,
98712                 value: d.tags['addr:city'] || d.tags.name,
98713                 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
98714               };
98715             }).sort(function (a, b) {
98716               return a.dist - b.dist;
98717             });
98718             return utilArrayUniqBy(cities, 'value');
98719
98720             function isAddressable(d) {
98721               if (d.tags.name) {
98722                 if (d.tags.admin_level === '8' && d.tags.boundary === 'administrative') return true;
98723                 if (d.tags.border_type === 'city') return true;
98724                 if (d.tags.place === 'city' || d.tags.place === 'town' || d.tags.place === 'village') return true;
98725               }
98726
98727               if (d.tags['addr:city']) return true;
98728               return false;
98729             }
98730           }
98731
98732           function getNearValues(key) {
98733             var extent = combinedEntityExtent();
98734             var l = extent.center();
98735             var box = geoExtent(l).padByMeters(200);
98736             var results = context.history().intersects(box).filter(function hasTag(d) {
98737               return _entityIDs.indexOf(d.id) === -1 && d.tags[key];
98738             }).map(function (d) {
98739               return {
98740                 title: d.tags[key],
98741                 value: d.tags[key],
98742                 dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
98743               };
98744             }).sort(function (a, b) {
98745               return a.dist - b.dist;
98746             });
98747             return utilArrayUniqBy(results, 'value');
98748           }
98749
98750           function updateForCountryCode() {
98751             if (!_countryCode) return;
98752             var addressFormat;
98753
98754             for (var i = 0; i < _addressFormats.length; i++) {
98755               var format = _addressFormats[i];
98756
98757               if (!format.countryCodes) {
98758                 addressFormat = format; // choose the default format, keep going
98759               } else if (format.countryCodes.indexOf(_countryCode) !== -1) {
98760                 addressFormat = format; // choose the country format, stop here
98761
98762                 break;
98763               }
98764             }
98765
98766             var dropdowns = addressFormat.dropdowns || ['city', 'county', 'country', 'district', 'hamlet', 'neighbourhood', 'place', 'postcode', 'province', 'quarter', 'state', 'street', 'subdistrict', 'suburb'];
98767             var widths = addressFormat.widths || {
98768               housenumber: 1 / 3,
98769               street: 2 / 3,
98770               city: 2 / 3,
98771               state: 1 / 4,
98772               postcode: 1 / 3
98773             };
98774
98775             function row(r) {
98776               // Normalize widths.
98777               var total = r.reduce(function (sum, key) {
98778                 return sum + (widths[key] || 0.5);
98779               }, 0);
98780               return r.map(function (key) {
98781                 return {
98782                   id: key,
98783                   width: (widths[key] || 0.5) / total
98784                 };
98785               });
98786             }
98787
98788             var rows = _wrap.selectAll('.addr-row').data(addressFormat.format, function (d) {
98789               return d.toString();
98790             });
98791
98792             rows.exit().remove();
98793             rows.enter().append('div').attr('class', 'addr-row').selectAll('input').data(row).enter().append('input').property('type', 'text').call(updatePlaceholder).attr('class', function (d) {
98794               return 'addr-' + d.id;
98795             }).call(utilNoAuto).each(addDropdown).style('width', function (d) {
98796               return d.width * 100 + '%';
98797             });
98798
98799             function addDropdown(d) {
98800               if (dropdowns.indexOf(d.id) === -1) return; // not a dropdown
98801
98802               var nearValues = d.id === 'street' ? getNearStreets : d.id === 'city' ? getNearCities : getNearValues;
98803               select(this).call(uiCombobox(context, 'address-' + d.id).minItems(1).caseSensitive(true).fetcher(function (value, callback) {
98804                 callback(nearValues('addr:' + d.id));
98805               }));
98806             }
98807
98808             _wrap.selectAll('input').on('blur', change()).on('change', change());
98809
98810             _wrap.selectAll('input:not(.combobox-input)').on('input', change(true));
98811
98812             if (_tags) updateTags(_tags);
98813           }
98814
98815           function address(selection) {
98816             _selection = selection;
98817             _wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98818             _wrap = _wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(_wrap);
98819             var extent = combinedEntityExtent();
98820
98821             if (extent) {
98822               var countryCode;
98823
98824               if (context.inIntro()) {
98825                 // localize the address format for the walkthrough
98826                 countryCode = _t('intro.graph.countrycode');
98827               } else {
98828                 var center = extent.center();
98829                 countryCode = iso1A2Code(center);
98830               }
98831
98832               if (countryCode) {
98833                 _countryCode = countryCode.toLowerCase();
98834                 updateForCountryCode();
98835               }
98836             }
98837           }
98838
98839           function change(onInput) {
98840             return function () {
98841               var tags = {};
98842
98843               _wrap.selectAll('input').each(function (subfield) {
98844                 var key = field.key + ':' + subfield.id;
98845                 var value = this.value;
98846                 if (!onInput) value = context.cleanTagValue(value); // don't override multiple values with blank string
98847
98848                 if (Array.isArray(_tags[key]) && !value) return;
98849                 tags[key] = value || undefined;
98850               });
98851
98852               dispatch.call('change', this, tags, onInput);
98853             };
98854           }
98855
98856           function updatePlaceholder(inputSelection) {
98857             return inputSelection.attr('placeholder', function (subfield) {
98858               if (_tags && Array.isArray(_tags[field.key + ':' + subfield.id])) {
98859                 return _t('inspector.multiple_values');
98860               }
98861
98862               if (_countryCode) {
98863                 var localkey = subfield.id + '!' + _countryCode;
98864                 var tkey = addrField.hasTextForStringId('placeholders.' + localkey) ? localkey : subfield.id;
98865                 return addrField.t('placeholders.' + tkey);
98866               }
98867             });
98868           }
98869
98870           function updateTags(tags) {
98871             utilGetSetValue(_wrap.selectAll('input'), function (subfield) {
98872               var val = tags[field.key + ':' + subfield.id];
98873               return typeof val === 'string' ? val : '';
98874             }).attr('title', function (subfield) {
98875               var val = tags[field.key + ':' + subfield.id];
98876               return val && Array.isArray(val) ? val.filter(Boolean).join('\n') : undefined;
98877             }).classed('mixed', function (subfield) {
98878               return Array.isArray(tags[field.key + ':' + subfield.id]);
98879             }).call(updatePlaceholder);
98880           }
98881
98882           function combinedEntityExtent() {
98883             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
98884           }
98885
98886           address.entityIDs = function (val) {
98887             if (!arguments.length) return _entityIDs;
98888             _entityIDs = val;
98889             return address;
98890           };
98891
98892           address.tags = function (tags) {
98893             _tags = tags;
98894             updateTags(tags);
98895           };
98896
98897           address.focus = function () {
98898             var node = _wrap.selectAll('input').node();
98899
98900             if (node) node.focus();
98901           };
98902
98903           return utilRebind(address, dispatch, 'on');
98904         }
98905
98906         function uiFieldCycleway(field, context) {
98907           var dispatch = dispatch$8('change');
98908           var items = select(null);
98909           var wrap = select(null);
98910
98911           var _tags;
98912
98913           function cycleway(selection) {
98914             function stripcolon(s) {
98915               return s.replace(':', '');
98916             }
98917
98918             wrap = selection.selectAll('.form-field-input-wrap').data([0]);
98919             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
98920             var div = wrap.selectAll('ul').data([0]);
98921             div = div.enter().append('ul').attr('class', 'rows').merge(div);
98922             var keys = ['cycleway:left', 'cycleway:right'];
98923             items = div.selectAll('li').data(keys);
98924             var enter = items.enter().append('li').attr('class', function (d) {
98925               return 'labeled-input preset-cycleway-' + stripcolon(d);
98926             });
98927             enter.append('span').attr('class', 'label preset-label-cycleway').attr('for', function (d) {
98928               return 'preset-input-cycleway-' + stripcolon(d);
98929             }).html(function (d) {
98930               return field.t.html('types.' + d);
98931             });
98932             enter.append('div').attr('class', 'preset-input-cycleway-wrap').append('input').attr('type', 'text').attr('class', function (d) {
98933               return 'preset-input-cycleway preset-input-' + stripcolon(d);
98934             }).call(utilNoAuto).each(function (d) {
98935               select(this).call(uiCombobox(context, 'cycleway-' + stripcolon(d)).data(cycleway.options(d)));
98936             });
98937             items = items.merge(enter); // Update
98938
98939             wrap.selectAll('.preset-input-cycleway').on('change', change).on('blur', change);
98940           }
98941
98942           function change(d3_event, key) {
98943             var newValue = context.cleanTagValue(utilGetSetValue(select(this))); // don't override multiple values with blank string
98944
98945             if (!newValue && (Array.isArray(_tags.cycleway) || Array.isArray(_tags[key]))) return;
98946
98947             if (newValue === 'none' || newValue === '') {
98948               newValue = undefined;
98949             }
98950
98951             var otherKey = key === 'cycleway:left' ? 'cycleway:right' : 'cycleway:left';
98952             var otherValue = typeof _tags.cycleway === 'string' ? _tags.cycleway : _tags[otherKey];
98953
98954             if (otherValue && Array.isArray(otherValue)) {
98955               // we must always have an explicit value for comparison
98956               otherValue = otherValue[0];
98957             }
98958
98959             if (otherValue === 'none' || otherValue === '') {
98960               otherValue = undefined;
98961             }
98962
98963             var tag = {}; // If the left and right tags match, use the cycleway tag to tag both
98964             // sides the same way
98965
98966             if (newValue === otherValue) {
98967               tag = {
98968                 cycleway: newValue,
98969                 'cycleway:left': undefined,
98970                 'cycleway:right': undefined
98971               };
98972             } else {
98973               // Always set both left and right as changing one can affect the other
98974               tag = {
98975                 cycleway: undefined
98976               };
98977               tag[key] = newValue;
98978               tag[otherKey] = otherValue;
98979             }
98980
98981             dispatch.call('change', this, tag);
98982           }
98983
98984           cycleway.options = function () {
98985             return field.options.map(function (option) {
98986               return {
98987                 title: field.t('options.' + option + '.description'),
98988                 value: option
98989               };
98990             });
98991           };
98992
98993           cycleway.tags = function (tags) {
98994             _tags = tags; // If cycleway is set, use that instead of individual values
98995
98996             var commonValue = typeof tags.cycleway === 'string' && tags.cycleway;
98997             utilGetSetValue(items.selectAll('.preset-input-cycleway'), function (d) {
98998               if (commonValue) return commonValue;
98999               return !tags.cycleway && typeof tags[d] === 'string' ? tags[d] : '';
99000             }).attr('title', function (d) {
99001               if (Array.isArray(tags.cycleway) || Array.isArray(tags[d])) {
99002                 var vals = [];
99003
99004                 if (Array.isArray(tags.cycleway)) {
99005                   vals = vals.concat(tags.cycleway);
99006                 }
99007
99008                 if (Array.isArray(tags[d])) {
99009                   vals = vals.concat(tags[d]);
99010                 }
99011
99012                 return vals.filter(Boolean).join('\n');
99013               }
99014
99015               return null;
99016             }).attr('placeholder', function (d) {
99017               if (Array.isArray(tags.cycleway) || Array.isArray(tags[d])) {
99018                 return _t('inspector.multiple_values');
99019               }
99020
99021               return field.placeholder();
99022             }).classed('mixed', function (d) {
99023               return Array.isArray(tags.cycleway) || Array.isArray(tags[d]);
99024             });
99025           };
99026
99027           cycleway.focus = function () {
99028             var node = wrap.selectAll('input').node();
99029             if (node) node.focus();
99030           };
99031
99032           return utilRebind(cycleway, dispatch, 'on');
99033         }
99034
99035         function uiFieldLanes(field, context) {
99036           var dispatch = dispatch$8('change');
99037           var LANE_WIDTH = 40;
99038           var LANE_HEIGHT = 200;
99039           var _entityIDs = [];
99040
99041           function lanes(selection) {
99042             var lanesData = context.entity(_entityIDs[0]).lanes();
99043
99044             if (!context.container().select('.inspector-wrap.inspector-hidden').empty() || !selection.node().parentNode) {
99045               selection.call(lanes.off);
99046               return;
99047             }
99048
99049             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99050             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
99051             var surface = wrap.selectAll('.surface').data([0]);
99052             var d = utilGetDimensions(wrap);
99053             var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
99054             surface = surface.enter().append('svg').attr('width', d[0]).attr('height', 300).attr('class', 'surface').merge(surface);
99055             var lanesSelection = surface.selectAll('.lanes').data([0]);
99056             lanesSelection = lanesSelection.enter().append('g').attr('class', 'lanes').merge(lanesSelection);
99057             lanesSelection.attr('transform', function () {
99058               return 'translate(' + freeSpace / 2 + ', 0)';
99059             });
99060             var lane = lanesSelection.selectAll('.lane').data(lanesData.lanes);
99061             lane.exit().remove();
99062             var enter = lane.enter().append('g').attr('class', 'lane');
99063             enter.append('g').append('rect').attr('y', 50).attr('width', LANE_WIDTH).attr('height', LANE_HEIGHT);
99064             enter.append('g').attr('class', 'forward').append('text').attr('y', 40).attr('x', 14).text('▲');
99065             enter.append('g').attr('class', 'bothways').append('text').attr('y', 40).attr('x', 14).text('▲▼');
99066             enter.append('g').attr('class', 'backward').append('text').attr('y', 40).attr('x', 14).text('▼');
99067             lane = lane.merge(enter);
99068             lane.attr('transform', function (d) {
99069               return 'translate(' + LANE_WIDTH * d.index * 1.5 + ', 0)';
99070             });
99071             lane.select('.forward').style('visibility', function (d) {
99072               return d.direction === 'forward' ? 'visible' : 'hidden';
99073             });
99074             lane.select('.bothways').style('visibility', function (d) {
99075               return d.direction === 'bothways' ? 'visible' : 'hidden';
99076             });
99077             lane.select('.backward').style('visibility', function (d) {
99078               return d.direction === 'backward' ? 'visible' : 'hidden';
99079             });
99080           }
99081
99082           lanes.entityIDs = function (val) {
99083             _entityIDs = val;
99084           };
99085
99086           lanes.tags = function () {};
99087
99088           lanes.focus = function () {};
99089
99090           lanes.off = function () {};
99091
99092           return utilRebind(lanes, dispatch, 'on');
99093         }
99094         uiFieldLanes.supportsMultiselection = false;
99095
99096         var _languagesArray = [];
99097         function uiFieldLocalized(field, context) {
99098           var dispatch = dispatch$8('change', 'input');
99099           var wikipedia = services.wikipedia;
99100           var input = select(null);
99101           var localizedInputs = select(null);
99102
99103           var _countryCode;
99104
99105           var _tags; // A concern here in switching to async data means that _languagesArray will not
99106           // be available the first time through, so things like the fetchers and
99107           // the language() function will not work immediately.
99108
99109
99110           _mainFileFetcher.get('languages').then(loadLanguagesArray)["catch"](function () {
99111             /* ignore */
99112           });
99113           var _territoryLanguages = {};
99114           _mainFileFetcher.get('territory_languages').then(function (d) {
99115             _territoryLanguages = d;
99116           })["catch"](function () {
99117             /* ignore */
99118           }); // reuse these combos
99119
99120           var langCombo = uiCombobox(context, 'localized-lang').fetcher(fetchLanguages).minItems(0);
99121
99122           var _selection = select(null);
99123
99124           var _multilingual = [];
99125
99126           var _buttonTip = uiTooltip().title(_t.html('translate.translate')).placement('left');
99127
99128           var _wikiTitles;
99129
99130           var _entityIDs = [];
99131
99132           function loadLanguagesArray(dataLanguages) {
99133             if (_languagesArray.length !== 0) return; // some conversion is needed to ensure correct OSM tags are used
99134
99135             var replacements = {
99136               sr: 'sr-Cyrl',
99137               // in OSM, `sr` implies Cyrillic
99138               'sr-Cyrl': false // `sr-Cyrl` isn't used in OSM
99139
99140             };
99141
99142             for (var code in dataLanguages) {
99143               if (replacements[code] === false) continue;
99144               var metaCode = code;
99145               if (replacements[code]) metaCode = replacements[code];
99146
99147               _languagesArray.push({
99148                 localName: _mainLocalizer.languageName(metaCode, {
99149                   localOnly: true
99150                 }),
99151                 nativeName: dataLanguages[metaCode].nativeName,
99152                 code: code,
99153                 label: _mainLocalizer.languageName(metaCode)
99154               });
99155             }
99156           }
99157
99158           function calcLocked() {
99159             // Protect name field for suggestion presets that don't display a brand/operator field
99160             var isLocked = field.id === 'name' && _entityIDs.length && _entityIDs.some(function (entityID) {
99161               var entity = context.graph().hasEntity(entityID);
99162               if (!entity) return false; // Features linked to Wikidata are likely important and should be protected
99163
99164               if (entity.tags.wikidata) return true; // Assume the name has already been confirmed if its source has been researched
99165
99166               if (entity.tags['name:etymology:wikidata']) return true; // Lock the `name` if this is a suggestion preset that assigns the name,
99167               // and the preset does not display a `brand` or `operator` field.
99168               // (For presets like hotels, car dealerships, post offices, the `name` should remain editable)
99169               // see also similar logic in `outdated_tags.js`
99170
99171               var preset = _mainPresetIndex.match(entity, context.graph());
99172
99173               if (preset) {
99174                 var isSuggestion = preset.suggestion;
99175                 var fields = preset.fields();
99176                 var showsBrandField = fields.some(function (d) {
99177                   return d.id === 'brand';
99178                 });
99179                 var showsOperatorField = fields.some(function (d) {
99180                   return d.id === 'operator';
99181                 });
99182                 var setsName = preset.addTags.name;
99183                 var setsBrandWikidata = preset.addTags['brand:wikidata'];
99184                 var setsOperatorWikidata = preset.addTags['operator:wikidata'];
99185                 return isSuggestion && setsName && (setsBrandWikidata && !showsBrandField || setsOperatorWikidata && !showsOperatorField);
99186               }
99187
99188               return false;
99189             });
99190
99191             field.locked(isLocked);
99192           } // update _multilingual, maintaining the existing order
99193
99194
99195           function calcMultilingual(tags) {
99196             var existingLangsOrdered = _multilingual.map(function (item) {
99197               return item.lang;
99198             });
99199
99200             var existingLangs = new Set(existingLangsOrdered.filter(Boolean));
99201
99202             for (var k in tags) {
99203               var m = k.match(/^(.*):(.*)$/);
99204
99205               if (m && m[1] === field.key && m[2]) {
99206                 var item = {
99207                   lang: m[2],
99208                   value: tags[k]
99209                 };
99210
99211                 if (existingLangs.has(item.lang)) {
99212                   // update the value
99213                   _multilingual[existingLangsOrdered.indexOf(item.lang)].value = item.value;
99214                   existingLangs["delete"](item.lang);
99215                 } else {
99216                   _multilingual.push(item);
99217                 }
99218               }
99219             } // Don't remove items based on deleted tags, since this makes the UI
99220             // disappear unexpectedly when clearing values - #8164
99221
99222
99223             _multilingual.forEach(function (item) {
99224               if (item.lang && existingLangs.has(item.lang)) {
99225                 item.value = '';
99226               }
99227             });
99228           }
99229
99230           function localized(selection) {
99231             _selection = selection;
99232             calcLocked();
99233             var isLocked = field.locked();
99234             var wrap = selection.selectAll('.form-field-input-wrap').data([0]); // enter/update
99235
99236             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
99237             input = wrap.selectAll('.localized-main').data([0]); // enter/update
99238
99239             input = input.enter().append('input').attr('type', 'text').attr('id', field.domId).attr('class', 'localized-main').call(utilNoAuto).merge(input);
99240             input.classed('disabled', !!isLocked).attr('readonly', isLocked || null).on('input', change(true)).on('blur', change()).on('change', change());
99241             var translateButton = wrap.selectAll('.localized-add').data([0]);
99242             translateButton = translateButton.enter().append('button').attr('class', 'localized-add form-field-button').attr('aria-label', _t('icons.plus')).call(svgIcon('#iD-icon-plus')).merge(translateButton);
99243             translateButton.classed('disabled', !!isLocked).call(isLocked ? _buttonTip.destroy : _buttonTip).on('click', addNew);
99244
99245             if (_tags && !_multilingual.length) {
99246               calcMultilingual(_tags);
99247             }
99248
99249             localizedInputs = selection.selectAll('.localized-multilingual').data([0]);
99250             localizedInputs = localizedInputs.enter().append('div').attr('class', 'localized-multilingual').merge(localizedInputs);
99251             localizedInputs.call(renderMultilingual);
99252             localizedInputs.selectAll('button, input').classed('disabled', !!isLocked).attr('readonly', isLocked || null);
99253             selection.selectAll('.combobox-caret').classed('nope', true);
99254
99255             function addNew(d3_event) {
99256               d3_event.preventDefault();
99257               if (field.locked()) return;
99258               var defaultLang = _mainLocalizer.languageCode().toLowerCase();
99259
99260               var langExists = _multilingual.find(function (datum) {
99261                 return datum.lang === defaultLang;
99262               });
99263
99264               var isLangEn = defaultLang.indexOf('en') > -1;
99265
99266               if (isLangEn || langExists) {
99267                 defaultLang = '';
99268                 langExists = _multilingual.find(function (datum) {
99269                   return datum.lang === defaultLang;
99270                 });
99271               }
99272
99273               if (!langExists) {
99274                 // prepend the value so it appears at the top
99275                 _multilingual.unshift({
99276                   lang: defaultLang,
99277                   value: ''
99278                 });
99279
99280                 localizedInputs.call(renderMultilingual);
99281               }
99282             }
99283
99284             function change(onInput) {
99285               return function (d3_event) {
99286                 if (field.locked()) {
99287                   d3_event.preventDefault();
99288                   return;
99289                 }
99290
99291                 var val = utilGetSetValue(select(this));
99292                 if (!onInput) val = context.cleanTagValue(val); // don't override multiple values with blank string
99293
99294                 if (!val && Array.isArray(_tags[field.key])) return;
99295                 var t = {};
99296                 t[field.key] = val || undefined;
99297                 dispatch.call('change', this, t, onInput);
99298               };
99299             }
99300           }
99301
99302           function key(lang) {
99303             return field.key + ':' + lang;
99304           }
99305
99306           function changeLang(d3_event, d) {
99307             var tags = {}; // make sure unrecognized suffixes are lowercase - #7156
99308
99309             var lang = utilGetSetValue(select(this)).toLowerCase();
99310
99311             var language = _languagesArray.find(function (d) {
99312               return d.label.toLowerCase() === lang || d.localName && d.localName.toLowerCase() === lang || d.nativeName && d.nativeName.toLowerCase() === lang;
99313             });
99314
99315             if (language) lang = language.code;
99316
99317             if (d.lang && d.lang !== lang) {
99318               tags[key(d.lang)] = undefined;
99319             }
99320
99321             var newKey = lang && context.cleanTagKey(key(lang));
99322             var value = utilGetSetValue(select(this.parentNode).selectAll('.localized-value'));
99323
99324             if (newKey && value) {
99325               tags[newKey] = value;
99326             } else if (newKey && _wikiTitles && _wikiTitles[d.lang]) {
99327               tags[newKey] = _wikiTitles[d.lang];
99328             }
99329
99330             d.lang = lang;
99331             dispatch.call('change', this, tags);
99332           }
99333
99334           function changeValue(d3_event, d) {
99335             if (!d.lang) return;
99336             var value = context.cleanTagValue(utilGetSetValue(select(this))) || undefined; // don't override multiple values with blank string
99337
99338             if (!value && Array.isArray(d.value)) return;
99339             var t = {};
99340             t[key(d.lang)] = value;
99341             d.value = value;
99342             dispatch.call('change', this, t);
99343           }
99344
99345           function fetchLanguages(value, cb) {
99346             var v = value.toLowerCase(); // show the user's language first
99347
99348             var langCodes = [_mainLocalizer.localeCode(), _mainLocalizer.languageCode()];
99349
99350             if (_countryCode && _territoryLanguages[_countryCode]) {
99351               langCodes = langCodes.concat(_territoryLanguages[_countryCode]);
99352             }
99353
99354             var langItems = [];
99355             langCodes.forEach(function (code) {
99356               var langItem = _languagesArray.find(function (item) {
99357                 return item.code === code;
99358               });
99359
99360               if (langItem) langItems.push(langItem);
99361             });
99362             langItems = utilArrayUniq(langItems.concat(_languagesArray));
99363             cb(langItems.filter(function (d) {
99364               return d.label.toLowerCase().indexOf(v) >= 0 || d.localName && d.localName.toLowerCase().indexOf(v) >= 0 || d.nativeName && d.nativeName.toLowerCase().indexOf(v) >= 0 || d.code.toLowerCase().indexOf(v) >= 0;
99365             }).map(function (d) {
99366               return {
99367                 value: d.label
99368               };
99369             }));
99370           }
99371
99372           function renderMultilingual(selection) {
99373             var entries = selection.selectAll('div.entry').data(_multilingual, function (d) {
99374               return d.lang;
99375             });
99376             entries.exit().style('top', '0').style('max-height', '240px').transition().duration(200).style('opacity', '0').style('max-height', '0px').remove();
99377             var entriesEnter = entries.enter().append('div').attr('class', 'entry').each(function (_, index) {
99378               var wrap = select(this);
99379               var domId = utilUniqueDomId(index);
99380               var label = wrap.append('label').attr('class', 'field-label').attr('for', domId);
99381               var text = label.append('span').attr('class', 'label-text');
99382               text.append('span').attr('class', 'label-textvalue').call(_t.append('translate.localized_translation_label'));
99383               text.append('span').attr('class', 'label-textannotation');
99384               label.append('button').attr('class', 'remove-icon-multilingual').attr('title', _t('icons.remove')).on('click', function (d3_event, d) {
99385                 if (field.locked()) return;
99386                 d3_event.preventDefault(); // remove the UI item manually
99387
99388                 _multilingual.splice(_multilingual.indexOf(d), 1);
99389
99390                 var langKey = d.lang && key(d.lang);
99391
99392                 if (langKey && langKey in _tags) {
99393                   delete _tags[langKey]; // remove from entity tags
99394
99395                   var t = {};
99396                   t[langKey] = undefined;
99397                   dispatch.call('change', this, t);
99398                   return;
99399                 }
99400
99401                 renderMultilingual(selection);
99402               }).call(svgIcon('#iD-operation-delete'));
99403               wrap.append('input').attr('class', 'localized-lang').attr('id', domId).attr('type', 'text').attr('placeholder', _t('translate.localized_translation_language')).on('blur', changeLang).on('change', changeLang).call(langCombo);
99404               wrap.append('input').attr('type', 'text').attr('class', 'localized-value').on('blur', changeValue).on('change', changeValue);
99405             });
99406             entriesEnter.style('margin-top', '0px').style('max-height', '0px').style('opacity', '0').transition().duration(200).style('margin-top', '10px').style('max-height', '240px').style('opacity', '1').on('end', function () {
99407               select(this).style('max-height', '').style('overflow', 'visible');
99408             });
99409             entries = entries.merge(entriesEnter);
99410             entries.order(); // allow removing the entry UIs even if there isn't a tag to remove
99411
99412             entries.classed('present', true);
99413             utilGetSetValue(entries.select('.localized-lang'), function (d) {
99414               var langItem = _languagesArray.find(function (item) {
99415                 return item.code === d.lang;
99416               });
99417
99418               if (langItem) return langItem.label;
99419               return d.lang;
99420             });
99421             utilGetSetValue(entries.select('.localized-value'), function (d) {
99422               return typeof d.value === 'string' ? d.value : '';
99423             }).attr('title', function (d) {
99424               return Array.isArray(d.value) ? d.value.filter(Boolean).join('\n') : null;
99425             }).attr('placeholder', function (d) {
99426               return Array.isArray(d.value) ? _t('inspector.multiple_values') : _t('translate.localized_translation_name');
99427             }).classed('mixed', function (d) {
99428               return Array.isArray(d.value);
99429             });
99430           }
99431
99432           localized.tags = function (tags) {
99433             _tags = tags; // Fetch translations from wikipedia
99434
99435             if (typeof tags.wikipedia === 'string' && !_wikiTitles) {
99436               _wikiTitles = {};
99437               var wm = tags.wikipedia.match(/([^:]+):(.+)/);
99438
99439               if (wm && wm[0] && wm[1]) {
99440                 wikipedia.translations(wm[1], wm[2], function (err, d) {
99441                   if (err || !d) return;
99442                   _wikiTitles = d;
99443                 });
99444               }
99445             }
99446
99447             var isMixed = Array.isArray(tags[field.key]);
99448             utilGetSetValue(input, typeof tags[field.key] === 'string' ? tags[field.key] : '').attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : undefined).attr('placeholder', isMixed ? _t('inspector.multiple_values') : field.placeholder()).classed('mixed', isMixed);
99449             calcMultilingual(tags);
99450
99451             _selection.call(localized);
99452           };
99453
99454           localized.focus = function () {
99455             input.node().focus();
99456           };
99457
99458           localized.entityIDs = function (val) {
99459             if (!arguments.length) return _entityIDs;
99460             _entityIDs = val;
99461             _multilingual = [];
99462             loadCountryCode();
99463             return localized;
99464           };
99465
99466           function loadCountryCode() {
99467             var extent = combinedEntityExtent();
99468             var countryCode = extent && iso1A2Code(extent.center());
99469             _countryCode = countryCode && countryCode.toLowerCase();
99470           }
99471
99472           function combinedEntityExtent() {
99473             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
99474           }
99475
99476           return utilRebind(localized, dispatch, 'on');
99477         }
99478
99479         function uiFieldRoadheight(field, context) {
99480           var dispatch = dispatch$8('change');
99481           var primaryUnitInput = select(null);
99482           var primaryInput = select(null);
99483           var secondaryInput = select(null);
99484           var secondaryUnitInput = select(null);
99485           var _entityIDs = [];
99486
99487           var _tags;
99488
99489           var _isImperial;
99490
99491           var primaryUnits = [{
99492             value: 'm',
99493             title: _t('inspector.roadheight.meter')
99494           }, {
99495             value: 'ft',
99496             title: _t('inspector.roadheight.foot')
99497           }];
99498           var unitCombo = uiCombobox(context, 'roadheight-unit').data(primaryUnits);
99499
99500           function roadheight(selection) {
99501             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99502             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
99503             primaryInput = wrap.selectAll('input.roadheight-number').data([0]);
99504             primaryInput = primaryInput.enter().append('input').attr('type', 'text').attr('class', 'roadheight-number').attr('id', field.domId).call(utilNoAuto).merge(primaryInput);
99505             primaryInput.on('change', change).on('blur', change);
99506             var loc = combinedEntityExtent().center();
99507             _isImperial = roadHeightUnit(loc) === 'ft';
99508             primaryUnitInput = wrap.selectAll('input.roadheight-unit').data([0]);
99509             primaryUnitInput = primaryUnitInput.enter().append('input').attr('type', 'text').attr('class', 'roadheight-unit').call(unitCombo).merge(primaryUnitInput);
99510             primaryUnitInput.on('blur', changeUnits).on('change', changeUnits);
99511             secondaryInput = wrap.selectAll('input.roadheight-secondary-number').data([0]);
99512             secondaryInput = secondaryInput.enter().append('input').attr('type', 'text').attr('class', 'roadheight-secondary-number').call(utilNoAuto).merge(secondaryInput);
99513             secondaryInput.on('change', change).on('blur', change);
99514             secondaryUnitInput = wrap.selectAll('input.roadheight-secondary-unit').data([0]);
99515             secondaryUnitInput = secondaryUnitInput.enter().append('input').attr('type', 'text').call(utilNoAuto).classed('disabled', true).classed('roadheight-secondary-unit', true).attr('readonly', 'readonly').merge(secondaryUnitInput);
99516
99517             function changeUnits() {
99518               _isImperial = utilGetSetValue(primaryUnitInput) === 'ft';
99519               utilGetSetValue(primaryUnitInput, _isImperial ? 'ft' : 'm');
99520               setUnitSuggestions();
99521               change();
99522             }
99523           }
99524
99525           function setUnitSuggestions() {
99526             utilGetSetValue(primaryUnitInput, _isImperial ? 'ft' : 'm');
99527           }
99528
99529           function change() {
99530             var tag = {};
99531             var primaryValue = utilGetSetValue(primaryInput).trim();
99532             var secondaryValue = utilGetSetValue(secondaryInput).trim(); // don't override multiple values with blank string
99533
99534             if (!primaryValue && !secondaryValue && Array.isArray(_tags[field.key])) return;
99535
99536             if (!primaryValue && !secondaryValue) {
99537               tag[field.key] = undefined;
99538             } else if (isNaN(primaryValue) || isNaN(secondaryValue) || !_isImperial) {
99539               tag[field.key] = context.cleanTagValue(primaryValue);
99540             } else {
99541               if (primaryValue !== '') {
99542                 primaryValue = context.cleanTagValue(primaryValue + '\'');
99543               }
99544
99545               if (secondaryValue !== '') {
99546                 secondaryValue = context.cleanTagValue(secondaryValue + '"');
99547               }
99548
99549               tag[field.key] = primaryValue + secondaryValue;
99550             }
99551
99552             dispatch.call('change', this, tag);
99553           }
99554
99555           roadheight.tags = function (tags) {
99556             _tags = tags;
99557             var primaryValue = tags[field.key];
99558             var secondaryValue;
99559             var isMixed = Array.isArray(primaryValue);
99560
99561             if (!isMixed) {
99562               if (primaryValue && (primaryValue.indexOf('\'') >= 0 || primaryValue.indexOf('"') >= 0)) {
99563                 secondaryValue = primaryValue.match(/(-?[\d.]+)"/);
99564
99565                 if (secondaryValue !== null) {
99566                   secondaryValue = secondaryValue[1];
99567                 }
99568
99569                 primaryValue = primaryValue.match(/(-?[\d.]+)'/);
99570
99571                 if (primaryValue !== null) {
99572                   primaryValue = primaryValue[1];
99573                 }
99574
99575                 _isImperial = true;
99576               } else if (primaryValue) {
99577                 _isImperial = false;
99578               }
99579             }
99580
99581             setUnitSuggestions();
99582             utilGetSetValue(primaryInput, typeof primaryValue === 'string' ? primaryValue : '').attr('title', isMixed ? primaryValue.filter(Boolean).join('\n') : null).attr('placeholder', isMixed ? _t('inspector.multiple_values') : _t('inspector.unknown')).classed('mixed', isMixed);
99583             utilGetSetValue(secondaryInput, typeof secondaryValue === 'string' ? secondaryValue : '').attr('placeholder', isMixed ? _t('inspector.multiple_values') : _isImperial ? '0' : null).classed('mixed', isMixed).classed('disabled', !_isImperial).attr('readonly', _isImperial ? null : 'readonly');
99584             secondaryUnitInput.attr('value', _isImperial ? _t('inspector.roadheight.inch') : null);
99585           };
99586
99587           roadheight.focus = function () {
99588             primaryInput.node().focus();
99589           };
99590
99591           roadheight.entityIDs = function (val) {
99592             _entityIDs = val;
99593           };
99594
99595           function combinedEntityExtent() {
99596             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
99597           }
99598
99599           return utilRebind(roadheight, dispatch, 'on');
99600         }
99601
99602         function uiFieldRoadspeed(field, context) {
99603           var dispatch = dispatch$8('change');
99604           var unitInput = select(null);
99605           var input = select(null);
99606           var _entityIDs = [];
99607
99608           var _tags;
99609
99610           var _isImperial;
99611
99612           var speedCombo = uiCombobox(context, 'roadspeed');
99613           var unitCombo = uiCombobox(context, 'roadspeed-unit').data(['km/h', 'mph'].map(comboValues));
99614           var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120];
99615           var imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
99616
99617           function roadspeed(selection) {
99618             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99619             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
99620             input = wrap.selectAll('input.roadspeed-number').data([0]);
99621             input = input.enter().append('input').attr('type', 'text').attr('class', 'roadspeed-number').attr('id', field.domId).call(utilNoAuto).call(speedCombo).merge(input);
99622             input.on('change', change).on('blur', change);
99623             var loc = combinedEntityExtent().center();
99624             _isImperial = roadSpeedUnit(loc) === 'mph';
99625             unitInput = wrap.selectAll('input.roadspeed-unit').data([0]);
99626             unitInput = unitInput.enter().append('input').attr('type', 'text').attr('class', 'roadspeed-unit').attr('aria-label', _t('inspector.speed_unit')).call(unitCombo).merge(unitInput);
99627             unitInput.on('blur', changeUnits).on('change', changeUnits);
99628
99629             function changeUnits() {
99630               _isImperial = utilGetSetValue(unitInput) === 'mph';
99631               utilGetSetValue(unitInput, _isImperial ? 'mph' : 'km/h');
99632               setUnitSuggestions();
99633               change();
99634             }
99635           }
99636
99637           function setUnitSuggestions() {
99638             speedCombo.data((_isImperial ? imperialValues : metricValues).map(comboValues));
99639             utilGetSetValue(unitInput, _isImperial ? 'mph' : 'km/h');
99640           }
99641
99642           function comboValues(d) {
99643             return {
99644               value: d.toString(),
99645               title: d.toString()
99646             };
99647           }
99648
99649           function change() {
99650             var tag = {};
99651             var value = utilGetSetValue(input).trim(); // don't override multiple values with blank string
99652
99653             if (!value && Array.isArray(_tags[field.key])) return;
99654
99655             if (!value) {
99656               tag[field.key] = undefined;
99657             } else if (isNaN(value) || !_isImperial) {
99658               tag[field.key] = context.cleanTagValue(value);
99659             } else {
99660               tag[field.key] = context.cleanTagValue(value + ' mph');
99661             }
99662
99663             dispatch.call('change', this, tag);
99664           }
99665
99666           roadspeed.tags = function (tags) {
99667             _tags = tags;
99668             var value = tags[field.key];
99669             var isMixed = Array.isArray(value);
99670
99671             if (!isMixed) {
99672               if (value && value.indexOf('mph') >= 0) {
99673                 value = parseInt(value, 10).toString();
99674                 _isImperial = true;
99675               } else if (value) {
99676                 _isImperial = false;
99677               }
99678             }
99679
99680             setUnitSuggestions();
99681             utilGetSetValue(input, typeof value === 'string' ? value : '').attr('title', isMixed ? value.filter(Boolean).join('\n') : null).attr('placeholder', isMixed ? _t('inspector.multiple_values') : field.placeholder()).classed('mixed', isMixed);
99682           };
99683
99684           roadspeed.focus = function () {
99685             input.node().focus();
99686           };
99687
99688           roadspeed.entityIDs = function (val) {
99689             _entityIDs = val;
99690           };
99691
99692           function combinedEntityExtent() {
99693             return _entityIDs && _entityIDs.length && utilTotalExtent(_entityIDs, context.graph());
99694           }
99695
99696           return utilRebind(roadspeed, dispatch, 'on');
99697         }
99698
99699         function uiFieldRadio(field, context) {
99700           var dispatch = dispatch$8('change');
99701           var placeholder = select(null);
99702           var wrap = select(null);
99703           var labels = select(null);
99704           var radios = select(null);
99705           var radioData = (field.options || field.keys).slice(); // shallow copy
99706
99707           var typeField;
99708           var layerField;
99709           var _oldType = {};
99710           var _entityIDs = [];
99711
99712           function selectedKey() {
99713             var node = wrap.selectAll('.form-field-input-radio label.active input');
99714             return !node.empty() && node.datum();
99715           }
99716
99717           function radio(selection) {
99718             selection.classed('preset-radio', true);
99719             wrap = selection.selectAll('.form-field-input-wrap').data([0]);
99720             var enter = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-radio');
99721             enter.append('span').attr('class', 'placeholder');
99722             wrap = wrap.merge(enter);
99723             placeholder = wrap.selectAll('.placeholder');
99724             labels = wrap.selectAll('label').data(radioData);
99725             enter = labels.enter().append('label');
99726             enter.append('input').attr('type', 'radio').attr('name', field.id).attr('value', function (d) {
99727               return field.t('options.' + d, {
99728                 'default': d
99729               });
99730             }).attr('checked', false);
99731             enter.append('span').html(function (d) {
99732               return field.t.html('options.' + d, {
99733                 'default': d
99734               });
99735             });
99736             labels = labels.merge(enter);
99737             radios = labels.selectAll('input').on('change', changeRadio);
99738           }
99739
99740           function structureExtras(selection, tags) {
99741             var selected = selectedKey() || tags.layer !== undefined;
99742             var type = _mainPresetIndex.field(selected);
99743             var layer = _mainPresetIndex.field('layer');
99744             var showLayer = selected === 'bridge' || selected === 'tunnel' || tags.layer !== undefined;
99745             var extrasWrap = selection.selectAll('.structure-extras-wrap').data(selected ? [0] : []);
99746             extrasWrap.exit().remove();
99747             extrasWrap = extrasWrap.enter().append('div').attr('class', 'structure-extras-wrap').merge(extrasWrap);
99748             var list = extrasWrap.selectAll('ul').data([0]);
99749             list = list.enter().append('ul').attr('class', 'rows').merge(list); // Type
99750
99751             if (type) {
99752               if (!typeField || typeField.id !== selected) {
99753                 typeField = uiField(context, type, _entityIDs, {
99754                   wrap: false
99755                 }).on('change', changeType);
99756               }
99757
99758               typeField.tags(tags);
99759             } else {
99760               typeField = null;
99761             }
99762
99763             var typeItem = list.selectAll('.structure-type-item').data(typeField ? [typeField] : [], function (d) {
99764               return d.id;
99765             }); // Exit
99766
99767             typeItem.exit().remove(); // Enter
99768
99769             var typeEnter = typeItem.enter().insert('li', ':first-child').attr('class', 'labeled-input structure-type-item');
99770             typeEnter.append('span').attr('class', 'label structure-label-type').attr('for', 'preset-input-' + selected).call(_t.append('inspector.radio.structure.type'));
99771             typeEnter.append('div').attr('class', 'structure-input-type-wrap'); // Update
99772
99773             typeItem = typeItem.merge(typeEnter);
99774
99775             if (typeField) {
99776               typeItem.selectAll('.structure-input-type-wrap').call(typeField.render);
99777             } // Layer
99778
99779
99780             if (layer && showLayer) {
99781               if (!layerField) {
99782                 layerField = uiField(context, layer, _entityIDs, {
99783                   wrap: false
99784                 }).on('change', changeLayer);
99785               }
99786
99787               layerField.tags(tags);
99788               field.keys = utilArrayUnion(field.keys, ['layer']);
99789             } else {
99790               layerField = null;
99791               field.keys = field.keys.filter(function (k) {
99792                 return k !== 'layer';
99793               });
99794             }
99795
99796             var layerItem = list.selectAll('.structure-layer-item').data(layerField ? [layerField] : []); // Exit
99797
99798             layerItem.exit().remove(); // Enter
99799
99800             var layerEnter = layerItem.enter().append('li').attr('class', 'labeled-input structure-layer-item');
99801             layerEnter.append('span').attr('class', 'label structure-label-layer').attr('for', 'preset-input-layer').call(_t.append('inspector.radio.structure.layer'));
99802             layerEnter.append('div').attr('class', 'structure-input-layer-wrap'); // Update
99803
99804             layerItem = layerItem.merge(layerEnter);
99805
99806             if (layerField) {
99807               layerItem.selectAll('.structure-input-layer-wrap').call(layerField.render);
99808             }
99809           }
99810
99811           function changeType(t, onInput) {
99812             var key = selectedKey();
99813             if (!key) return;
99814             var val = t[key];
99815
99816             if (val !== 'no') {
99817               _oldType[key] = val;
99818             }
99819
99820             if (field.type === 'structureRadio') {
99821               // remove layer if it should not be set
99822               if (val === 'no' || key !== 'bridge' && key !== 'tunnel' || key === 'tunnel' && val === 'building_passage') {
99823                 t.layer = undefined;
99824               } // add layer if it should be set
99825
99826
99827               if (t.layer === undefined) {
99828                 if (key === 'bridge' && val !== 'no') {
99829                   t.layer = '1';
99830                 }
99831
99832                 if (key === 'tunnel' && val !== 'no' && val !== 'building_passage') {
99833                   t.layer = '-1';
99834                 }
99835               }
99836             }
99837
99838             dispatch.call('change', this, t, onInput);
99839           }
99840
99841           function changeLayer(t, onInput) {
99842             if (t.layer === '0') {
99843               t.layer = undefined;
99844             }
99845
99846             dispatch.call('change', this, t, onInput);
99847           }
99848
99849           function changeRadio() {
99850             var t = {};
99851             var activeKey;
99852
99853             if (field.key) {
99854               t[field.key] = undefined;
99855             }
99856
99857             radios.each(function (d) {
99858               var active = select(this).property('checked');
99859               if (active) activeKey = d;
99860
99861               if (field.key) {
99862                 if (active) t[field.key] = d;
99863               } else {
99864                 var val = _oldType[activeKey] || 'yes';
99865                 t[d] = active ? val : undefined;
99866               }
99867             });
99868
99869             if (field.type === 'structureRadio') {
99870               if (activeKey === 'bridge') {
99871                 t.layer = '1';
99872               } else if (activeKey === 'tunnel' && t.tunnel !== 'building_passage') {
99873                 t.layer = '-1';
99874               } else {
99875                 t.layer = undefined;
99876               }
99877             }
99878
99879             dispatch.call('change', this, t);
99880           }
99881
99882           radio.tags = function (tags) {
99883             function isOptionChecked(d) {
99884               if (field.key) {
99885                 return tags[field.key] === d;
99886               }
99887
99888               return !!(typeof tags[d] === 'string' && tags[d].toLowerCase() !== 'no');
99889             }
99890
99891             function isMixed(d) {
99892               if (field.key) {
99893                 return Array.isArray(tags[field.key]) && tags[field.key].includes(d);
99894               }
99895
99896               return Array.isArray(tags[d]);
99897             }
99898
99899             radios.property('checked', function (d) {
99900               return isOptionChecked(d) && (field.key || field.options.filter(isOptionChecked).length === 1);
99901             });
99902             labels.classed('active', function (d) {
99903               if (field.key) {
99904                 return Array.isArray(tags[field.key]) && tags[field.key].includes(d) || tags[field.key] === d;
99905               }
99906
99907               return Array.isArray(tags[d]) && tags[d].some(function (v) {
99908                 return typeof v === 'string' && v.toLowerCase() !== 'no';
99909               }) || !!(typeof tags[d] === 'string' && tags[d].toLowerCase() !== 'no');
99910             }).classed('mixed', isMixed).attr('title', function (d) {
99911               return isMixed(d) ? _t('inspector.unshared_value_tooltip') : null;
99912             });
99913             var selection = radios.filter(function () {
99914               return this.checked;
99915             });
99916
99917             if (selection.empty()) {
99918               placeholder.call(_t.append('inspector.none'));
99919             } else {
99920               placeholder.text(selection.attr('value'));
99921               _oldType[selection.datum()] = tags[selection.datum()];
99922             }
99923
99924             if (field.type === 'structureRadio') {
99925               // For waterways without a tunnel tag, set 'culvert' as
99926               // the _oldType to default to if the user picks 'tunnel'
99927               if (!!tags.waterway && !_oldType.tunnel) {
99928                 _oldType.tunnel = 'culvert';
99929               }
99930
99931               wrap.call(structureExtras, tags);
99932             }
99933           };
99934
99935           radio.focus = function () {
99936             radios.node().focus();
99937           };
99938
99939           radio.entityIDs = function (val) {
99940             if (!arguments.length) return _entityIDs;
99941             _entityIDs = val;
99942             _oldType = {};
99943             return radio;
99944           };
99945
99946           radio.isAllowed = function () {
99947             return _entityIDs.length === 1;
99948           };
99949
99950           return utilRebind(radio, dispatch, 'on');
99951         }
99952
99953         function uiFieldRestrictions(field, context) {
99954           var dispatch = dispatch$8('change');
99955           var breathe = behaviorBreathe();
99956           corePreferences('turn-restriction-via-way', null); // remove old key
99957
99958           var storedViaWay = corePreferences('turn-restriction-via-way0'); // use new key #6922
99959
99960           var storedDistance = corePreferences('turn-restriction-distance');
99961
99962           var _maxViaWay = storedViaWay !== null ? +storedViaWay : 0;
99963
99964           var _maxDistance = storedDistance ? +storedDistance : 30;
99965
99966           var _initialized = false;
99967
99968           var _parent = select(null); // the entire field
99969
99970
99971           var _container = select(null); // just the map
99972
99973
99974           var _oldTurns;
99975
99976           var _graph;
99977
99978           var _vertexID;
99979
99980           var _intersection;
99981
99982           var _fromWayID;
99983
99984           var _lastXPos;
99985
99986           function restrictions(selection) {
99987             _parent = selection; // try to reuse the intersection, but always rebuild it if the graph has changed
99988
99989             if (_vertexID && (context.graph() !== _graph || !_intersection)) {
99990               _graph = context.graph();
99991               _intersection = osmIntersection(_graph, _vertexID, _maxDistance);
99992             } // It's possible for there to be no actual intersection here.
99993             // for example, a vertex of two `highway=path`
99994             // In this case, hide the field.
99995
99996
99997             var isOK = _intersection && _intersection.vertices.length && // has vertices
99998             _intersection.vertices // has the vertex that the user selected
99999             .filter(function (vertex) {
100000               return vertex.id === _vertexID;
100001             }).length && _intersection.ways.length > 2 && // has more than 2 ways
100002             _intersection.ways // has more than 1 TO way
100003             .filter(function (way) {
100004               return way.__to;
100005             }).length > 1; // Also hide in the case where
100006
100007             select(selection.node().parentNode).classed('hide', !isOK); // if form field is hidden or has detached from dom, clean up.
100008
100009             if (!isOK || !context.container().select('.inspector-wrap.inspector-hidden').empty() || !selection.node().parentNode || !selection.node().parentNode.parentNode) {
100010               selection.call(restrictions.off);
100011               return;
100012             }
100013
100014             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
100015             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
100016             var container = wrap.selectAll('.restriction-container').data([0]); // enter
100017
100018             var containerEnter = container.enter().append('div').attr('class', 'restriction-container');
100019             containerEnter.append('div').attr('class', 'restriction-help'); // update
100020
100021             _container = containerEnter.merge(container).call(renderViewer);
100022             var controls = wrap.selectAll('.restriction-controls').data([0]); // enter/update
100023
100024             controls.enter().append('div').attr('class', 'restriction-controls-container').append('div').attr('class', 'restriction-controls').merge(controls).call(renderControls);
100025           }
100026
100027           function renderControls(selection) {
100028             var distControl = selection.selectAll('.restriction-distance').data([0]);
100029             distControl.exit().remove();
100030             var distControlEnter = distControl.enter().append('div').attr('class', 'restriction-control restriction-distance');
100031             distControlEnter.append('span').attr('class', 'restriction-control-label restriction-distance-label').call(_t.append('restriction.controls.distance', {
100032               suffix: ':'
100033             }));
100034             distControlEnter.append('input').attr('class', 'restriction-distance-input').attr('type', 'range').attr('min', '20').attr('max', '50').attr('step', '5');
100035             distControlEnter.append('span').attr('class', 'restriction-distance-text'); // update
100036
100037             selection.selectAll('.restriction-distance-input').property('value', _maxDistance).on('input', function () {
100038               var val = select(this).property('value');
100039               _maxDistance = +val;
100040               _intersection = null;
100041
100042               _container.selectAll('.layer-osm .layer-turns *').remove();
100043
100044               corePreferences('turn-restriction-distance', _maxDistance);
100045
100046               _parent.call(restrictions);
100047             });
100048             selection.selectAll('.restriction-distance-text').call(displayMaxDistance(_maxDistance));
100049             var viaControl = selection.selectAll('.restriction-via-way').data([0]);
100050             viaControl.exit().remove();
100051             var viaControlEnter = viaControl.enter().append('div').attr('class', 'restriction-control restriction-via-way');
100052             viaControlEnter.append('span').attr('class', 'restriction-control-label restriction-via-way-label').call(_t.append('restriction.controls.via', {
100053               suffix: ':'
100054             }));
100055             viaControlEnter.append('input').attr('class', 'restriction-via-way-input').attr('type', 'range').attr('min', '0').attr('max', '2').attr('step', '1');
100056             viaControlEnter.append('span').attr('class', 'restriction-via-way-text'); // update
100057
100058             selection.selectAll('.restriction-via-way-input').property('value', _maxViaWay).on('input', function () {
100059               var val = select(this).property('value');
100060               _maxViaWay = +val;
100061
100062               _container.selectAll('.layer-osm .layer-turns *').remove();
100063
100064               corePreferences('turn-restriction-via-way0', _maxViaWay);
100065
100066               _parent.call(restrictions);
100067             });
100068             selection.selectAll('.restriction-via-way-text').call(displayMaxVia(_maxViaWay));
100069           }
100070
100071           function renderViewer(selection) {
100072             if (!_intersection) return;
100073             var vgraph = _intersection.graph;
100074             var filter = utilFunctor(true);
100075             var projection = geoRawMercator(); // Reflow warning: `utilGetDimensions` calls `getBoundingClientRect`
100076             // Instead of asking the restriction-container for its dimensions,
100077             //  we can ask the .sidebar, which can have its dimensions cached.
100078             // width: calc as sidebar - padding
100079             // height: hardcoded (from `80_app.css`)
100080             // var d = utilGetDimensions(selection);
100081
100082             var sdims = utilGetDimensions(context.container().select('.sidebar'));
100083             var d = [sdims[0] - 50, 370];
100084             var c = geoVecScale(d, 0.5);
100085             var z = 22;
100086             projection.scale(geoZoomToScale(z)); // Calculate extent of all key vertices
100087
100088             var extent = geoExtent();
100089
100090             for (var i = 0; i < _intersection.vertices.length; i++) {
100091               extent._extend(_intersection.vertices[i].extent());
100092             }
100093
100094             var padTop = 35; // reserve top space for hint text
100095             // If this is a large intersection, adjust zoom to fit extent
100096
100097             if (_intersection.vertices.length > 1) {
100098               var hPadding = Math.min(160, Math.max(110, d[0] * 0.4));
100099               var vPadding = 160;
100100               var tl = projection([extent[0][0], extent[1][1]]);
100101               var br = projection([extent[1][0], extent[0][1]]);
100102               var hFactor = (br[0] - tl[0]) / (d[0] - hPadding);
100103               var vFactor = (br[1] - tl[1]) / (d[1] - vPadding - padTop);
100104               var hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2;
100105               var vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2;
100106               z = z - Math.max(hZoomDiff, vZoomDiff);
100107               projection.scale(geoZoomToScale(z));
100108             }
100109
100110             var extentCenter = projection(extent.center());
100111             extentCenter[1] = extentCenter[1] - padTop / 2;
100112             projection.translate(geoVecSubtract(c, extentCenter)).clipExtent([[0, 0], d]);
100113             var drawLayers = svgLayers(projection, context).only(['osm', 'touch']).dimensions(d);
100114             var drawVertices = svgVertices(projection, context);
100115             var drawLines = svgLines(projection, context);
100116             var drawTurns = svgTurns(projection, context);
100117             var firstTime = selection.selectAll('.surface').empty();
100118             selection.call(drawLayers);
100119             var surface = selection.selectAll('.surface').classed('tr', true);
100120
100121             if (firstTime) {
100122               _initialized = true;
100123               surface.call(breathe);
100124             } // This can happen if we've lowered the detail while a FROM way
100125             // is selected, and that way is no longer part of the intersection.
100126
100127
100128             if (_fromWayID && !vgraph.hasEntity(_fromWayID)) {
100129               _fromWayID = null;
100130               _oldTurns = null;
100131             }
100132
100133             surface.call(utilSetDimensions, d).call(drawVertices, vgraph, _intersection.vertices, filter, extent, z).call(drawLines, vgraph, _intersection.ways, filter).call(drawTurns, vgraph, _intersection.turns(_fromWayID, _maxViaWay));
100134             surface.on('click.restrictions', click).on('mouseover.restrictions', mouseover);
100135             surface.selectAll('.selected').classed('selected', false);
100136             surface.selectAll('.related').classed('related', false);
100137             var way;
100138
100139             if (_fromWayID) {
100140               way = vgraph.entity(_fromWayID);
100141               surface.selectAll('.' + _fromWayID).classed('selected', true).classed('related', true);
100142             }
100143
100144             document.addEventListener('resizeWindow', function () {
100145               utilSetDimensions(_container, null);
100146               redraw(1);
100147             }, false);
100148             updateHints(null);
100149
100150             function click(d3_event) {
100151               surface.call(breathe.off).call(breathe);
100152               var datum = d3_event.target.__data__;
100153               var entity = datum && datum.properties && datum.properties.entity;
100154
100155               if (entity) {
100156                 datum = entity;
100157               }
100158
100159               if (datum instanceof osmWay && (datum.__from || datum.__via)) {
100160                 _fromWayID = datum.id;
100161                 _oldTurns = null;
100162                 redraw();
100163               } else if (datum instanceof osmTurn) {
100164                 var actions, extraActions, turns, i;
100165                 var restrictionType = osmInferRestriction(vgraph, datum, projection);
100166
100167                 if (datum.restrictionID && !datum.direct) {
100168                   return;
100169                 } else if (datum.restrictionID && !datum.only) {
100170                   // NO -> ONLY
100171                   var seen = {};
100172                   var datumOnly = JSON.parse(JSON.stringify(datum)); // deep clone the datum
100173
100174                   datumOnly.only = true; // but change this property
100175
100176                   restrictionType = restrictionType.replace(/^no/, 'only'); // Adding an ONLY restriction should destroy all other direct restrictions from the FROM towards the VIA.
100177                   // We will remember them in _oldTurns, and restore them if the user clicks again.
100178
100179                   turns = _intersection.turns(_fromWayID, 2);
100180                   extraActions = [];
100181                   _oldTurns = [];
100182
100183                   for (i = 0; i < turns.length; i++) {
100184                     var turn = turns[i];
100185                     if (seen[turn.restrictionID]) continue; // avoid deleting the turn twice (#4968, #4928)
100186
100187                     if (turn.direct && turn.path[1] === datum.path[1]) {
100188                       seen[turns[i].restrictionID] = true;
100189                       turn.restrictionType = osmInferRestriction(vgraph, turn, projection);
100190
100191                       _oldTurns.push(turn);
100192
100193                       extraActions.push(actionUnrestrictTurn(turn));
100194                     }
100195                   }
100196
100197                   actions = _intersection.actions.concat(extraActions, [actionRestrictTurn(datumOnly, restrictionType), _t('operations.restriction.annotation.create')]);
100198                 } else if (datum.restrictionID) {
100199                   // ONLY -> Allowed
100200                   // Restore whatever restrictions we might have destroyed by cycling thru the ONLY state.
100201                   // This relies on the assumption that the intersection was already split up when we
100202                   // performed the previous action (NO -> ONLY), so the IDs in _oldTurns shouldn't have changed.
100203                   turns = _oldTurns || [];
100204                   extraActions = [];
100205
100206                   for (i = 0; i < turns.length; i++) {
100207                     if (turns[i].key !== datum.key) {
100208                       extraActions.push(actionRestrictTurn(turns[i], turns[i].restrictionType));
100209                     }
100210                   }
100211
100212                   _oldTurns = null;
100213                   actions = _intersection.actions.concat(extraActions, [actionUnrestrictTurn(datum), _t('operations.restriction.annotation.delete')]);
100214                 } else {
100215                   // Allowed -> NO
100216                   actions = _intersection.actions.concat([actionRestrictTurn(datum, restrictionType), _t('operations.restriction.annotation.create')]);
100217                 }
100218
100219                 context.perform.apply(context, actions); // At this point the datum will be changed, but will have same key..
100220                 // Refresh it and update the help..
100221
100222                 var s = surface.selectAll('.' + datum.key);
100223                 datum = s.empty() ? null : s.datum();
100224                 updateHints(datum);
100225               } else {
100226                 _fromWayID = null;
100227                 _oldTurns = null;
100228                 redraw();
100229               }
100230             }
100231
100232             function mouseover(d3_event) {
100233               var datum = d3_event.target.__data__;
100234               updateHints(datum);
100235             }
100236
100237             _lastXPos = _lastXPos || sdims[0];
100238
100239             function redraw(minChange) {
100240               var xPos = -1;
100241
100242               if (minChange) {
100243                 xPos = utilGetDimensions(context.container().select('.sidebar'))[0];
100244               }
100245
100246               if (!minChange || minChange && Math.abs(xPos - _lastXPos) >= minChange) {
100247                 if (context.hasEntity(_vertexID)) {
100248                   _lastXPos = xPos;
100249
100250                   _container.call(renderViewer);
100251                 }
100252               }
100253             }
100254
100255             function highlightPathsFrom(wayID) {
100256               surface.selectAll('.related').classed('related', false).classed('allow', false).classed('restrict', false).classed('only', false);
100257               surface.selectAll('.' + wayID).classed('related', true);
100258
100259               if (wayID) {
100260                 var turns = _intersection.turns(wayID, _maxViaWay);
100261
100262                 for (var i = 0; i < turns.length; i++) {
100263                   var turn = turns[i];
100264                   var ids = [turn.to.way];
100265                   var klass = turn.no ? 'restrict' : turn.only ? 'only' : 'allow';
100266
100267                   if (turn.only || turns.length === 1) {
100268                     if (turn.via.ways) {
100269                       ids = ids.concat(turn.via.ways);
100270                     }
100271                   } else if (turn.to.way === wayID) {
100272                     continue;
100273                   }
100274
100275                   surface.selectAll(utilEntitySelector(ids)).classed('related', true).classed('allow', klass === 'allow').classed('restrict', klass === 'restrict').classed('only', klass === 'only');
100276                 }
100277               }
100278             }
100279
100280             function updateHints(datum) {
100281               var help = _container.selectAll('.restriction-help').html('');
100282
100283               var placeholders = {};
100284               ['from', 'via', 'to'].forEach(function (k) {
100285                 placeholders[k] = {
100286                   html: '<span class="qualifier">' + _t('restriction.help.' + k) + '</span>'
100287                 };
100288               });
100289               var entity = datum && datum.properties && datum.properties.entity;
100290
100291               if (entity) {
100292                 datum = entity;
100293               }
100294
100295               if (_fromWayID) {
100296                 way = vgraph.entity(_fromWayID);
100297                 surface.selectAll('.' + _fromWayID).classed('selected', true).classed('related', true);
100298               } // Hovering a way
100299
100300
100301               if (datum instanceof osmWay && datum.__from) {
100302                 way = datum;
100303                 highlightPathsFrom(_fromWayID ? null : way.id);
100304                 surface.selectAll('.' + way.id).classed('related', true);
100305                 var clickSelect = !_fromWayID || _fromWayID !== way.id;
100306                 help.append('div') // "Click to select FROM {fromName}." / "FROM {fromName}"
100307                 .html(_t.html('restriction.help.' + (clickSelect ? 'select_from_name' : 'from_name'), {
100308                   from: placeholders.from,
100309                   fromName: displayName(way.id, vgraph)
100310                 })); // Hovering a turn arrow
100311               } else if (datum instanceof osmTurn) {
100312                 var restrictionType = osmInferRestriction(vgraph, datum, projection);
100313                 var turnType = restrictionType.replace(/^(only|no)\_/, '');
100314                 var indirect = datum.direct === false ? _t.html('restriction.help.indirect') : '';
100315                 var klass, turnText, nextText;
100316
100317                 if (datum.no) {
100318                   klass = 'restrict';
100319                   turnText = _t.html('restriction.help.turn.no_' + turnType, {
100320                     indirect: indirect
100321                   });
100322                   nextText = _t.html('restriction.help.turn.only_' + turnType, {
100323                     indirect: ''
100324                   });
100325                 } else if (datum.only) {
100326                   klass = 'only';
100327                   turnText = _t.html('restriction.help.turn.only_' + turnType, {
100328                     indirect: indirect
100329                   });
100330                   nextText = _t.html('restriction.help.turn.allowed_' + turnType, {
100331                     indirect: ''
100332                   });
100333                 } else {
100334                   klass = 'allow';
100335                   turnText = _t.html('restriction.help.turn.allowed_' + turnType, {
100336                     indirect: indirect
100337                   });
100338                   nextText = _t.html('restriction.help.turn.no_' + turnType, {
100339                     indirect: ''
100340                   });
100341                 }
100342
100343                 help.append('div') // "NO Right Turn (indirect)"
100344                 .attr('class', 'qualifier ' + klass).html(turnText);
100345                 help.append('div') // "FROM {fromName} TO {toName}"
100346                 .html(_t.html('restriction.help.from_name_to_name', {
100347                   from: placeholders.from,
100348                   fromName: displayName(datum.from.way, vgraph),
100349                   to: placeholders.to,
100350                   toName: displayName(datum.to.way, vgraph)
100351                 }));
100352
100353                 if (datum.via.ways && datum.via.ways.length) {
100354                   var names = [];
100355
100356                   for (var i = 0; i < datum.via.ways.length; i++) {
100357                     var prev = names[names.length - 1];
100358                     var curr = displayName(datum.via.ways[i], vgraph);
100359
100360                     if (!prev || curr !== prev) {
100361                       // collapse identical names
100362                       names.push(curr);
100363                     }
100364                   }
100365
100366                   help.append('div') // "VIA {viaNames}"
100367                   .html(_t.html('restriction.help.via_names', {
100368                     via: placeholders.via,
100369                     viaNames: names.join(', ')
100370                   }));
100371                 }
100372
100373                 if (!indirect) {
100374                   help.append('div') // Click for "No Right Turn"
100375                   .html(_t.html('restriction.help.toggle', {
100376                     turn: {
100377                       html: nextText.trim()
100378                     }
100379                   }));
100380                 }
100381
100382                 highlightPathsFrom(null);
100383                 var alongIDs = datum.path.slice();
100384                 surface.selectAll(utilEntitySelector(alongIDs)).classed('related', true).classed('allow', klass === 'allow').classed('restrict', klass === 'restrict').classed('only', klass === 'only'); // Hovering empty surface
100385               } else {
100386                 highlightPathsFrom(null);
100387
100388                 if (_fromWayID) {
100389                   help.append('div') // "FROM {fromName}"
100390                   .html(_t.html('restriction.help.from_name', {
100391                     from: placeholders.from,
100392                     fromName: displayName(_fromWayID, vgraph)
100393                   }));
100394                 } else {
100395                   help.append('div') // "Click to select a FROM segment."
100396                   .html(_t.html('restriction.help.select_from', {
100397                     from: placeholders.from
100398                   }));
100399                 }
100400               }
100401             }
100402           }
100403
100404           function displayMaxDistance(maxDist) {
100405             return function (selection) {
100406               var isImperial = !_mainLocalizer.usesMetric();
100407               var opts;
100408
100409               if (isImperial) {
100410                 var distToFeet = {
100411                   // imprecise conversion for prettier display
100412                   20: 70,
100413                   25: 85,
100414                   30: 100,
100415                   35: 115,
100416                   40: 130,
100417                   45: 145,
100418                   50: 160
100419                 }[maxDist];
100420                 opts = {
100421                   distance: _t('units.feet', {
100422                     quantity: distToFeet
100423                   })
100424                 };
100425               } else {
100426                 opts = {
100427                   distance: _t('units.meters', {
100428                     quantity: maxDist
100429                   })
100430                 };
100431               }
100432
100433               return selection.html('').call(_t.append('restriction.controls.distance_up_to', opts));
100434             };
100435           }
100436
100437           function displayMaxVia(maxVia) {
100438             return function (selection) {
100439               selection = selection.html('');
100440               return maxVia === 0 ? selection.call(_t.append('restriction.controls.via_node_only')) : maxVia === 1 ? selection.call(_t.append('restriction.controls.via_up_to_one')) : selection.call(_t.append('restriction.controls.via_up_to_two'));
100441             };
100442           }
100443
100444           function displayName(entityID, graph) {
100445             var entity = graph.entity(entityID);
100446             var name = utilDisplayName(entity) || '';
100447             var matched = _mainPresetIndex.match(entity, graph);
100448             var type = matched && matched.name() || utilDisplayType(entity.id);
100449             return name || type;
100450           }
100451
100452           restrictions.entityIDs = function (val) {
100453             _intersection = null;
100454             _fromWayID = null;
100455             _oldTurns = null;
100456             _vertexID = val[0];
100457           };
100458
100459           restrictions.tags = function () {};
100460
100461           restrictions.focus = function () {};
100462
100463           restrictions.off = function (selection) {
100464             if (!_initialized) return;
100465             selection.selectAll('.surface').call(breathe.off).on('click.restrictions', null).on('mouseover.restrictions', null);
100466             select(window).on('resize.restrictions', null);
100467           };
100468
100469           return utilRebind(restrictions, dispatch, 'on');
100470         }
100471         uiFieldRestrictions.supportsMultiselection = false;
100472
100473         function uiFieldTextarea(field, context) {
100474           var dispatch = dispatch$8('change');
100475           var input = select(null);
100476
100477           var _tags;
100478
100479           function textarea(selection) {
100480             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
100481             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
100482             input = wrap.selectAll('textarea').data([0]);
100483             input = input.enter().append('textarea').attr('id', field.domId).call(utilNoAuto).on('input', change(true)).on('blur', change()).on('change', change()).merge(input);
100484           }
100485
100486           function change(onInput) {
100487             return function () {
100488               var val = utilGetSetValue(input);
100489               if (!onInput) val = context.cleanTagValue(val); // don't override multiple values with blank string
100490
100491               if (!val && Array.isArray(_tags[field.key])) return;
100492               var t = {};
100493               t[field.key] = val || undefined;
100494               dispatch.call('change', this, t, onInput);
100495             };
100496           }
100497
100498           textarea.tags = function (tags) {
100499             _tags = tags;
100500             var isMixed = Array.isArray(tags[field.key]);
100501             utilGetSetValue(input, !isMixed && tags[field.key] ? tags[field.key] : '').attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : undefined).attr('placeholder', isMixed ? _t('inspector.multiple_values') : field.placeholder() || _t('inspector.unknown')).classed('mixed', isMixed);
100502           };
100503
100504           textarea.focus = function () {
100505             input.node().focus();
100506           };
100507
100508           return utilRebind(textarea, dispatch, 'on');
100509         }
100510
100511         function uiFieldWikidata(field, context) {
100512           var wikidata = services.wikidata;
100513           var dispatch = dispatch$8('change');
100514
100515           var _selection = select(null);
100516
100517           var _searchInput = select(null);
100518
100519           var _qid = null;
100520           var _wikidataEntity = null;
100521           var _wikiURL = '';
100522           var _entityIDs = [];
100523
100524           var _wikipediaKey = field.keys && field.keys.find(function (key) {
100525             return key.includes('wikipedia');
100526           }),
100527               _hintKey = field.key === 'wikidata' ? 'name' : field.key.split(':')[0];
100528
100529           var combobox = uiCombobox(context, 'combo-' + field.safeid).caseSensitive(true).minItems(1);
100530
100531           function wiki(selection) {
100532             _selection = selection;
100533             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
100534             wrap = wrap.enter().append('div').attr('class', 'form-field-input-wrap form-field-input-' + field.type).merge(wrap);
100535             var list = wrap.selectAll('ul').data([0]);
100536             list = list.enter().append('ul').attr('class', 'rows').merge(list);
100537             var searchRow = list.selectAll('li.wikidata-search').data([0]);
100538             var searchRowEnter = searchRow.enter().append('li').attr('class', 'wikidata-search');
100539             searchRowEnter.append('input').attr('type', 'text').attr('id', field.domId).style('flex', '1').call(utilNoAuto).on('focus', function () {
100540               var node = select(this).node();
100541               node.setSelectionRange(0, node.value.length);
100542             }).on('blur', function () {
100543               setLabelForEntity();
100544             }).call(combobox.fetcher(fetchWikidataItems));
100545             combobox.on('accept', function (d) {
100546               if (d) {
100547                 _qid = d.id;
100548                 change();
100549               }
100550             }).on('cancel', function () {
100551               setLabelForEntity();
100552             });
100553             searchRowEnter.append('button').attr('class', 'form-field-button wiki-link').attr('title', _t('icons.view_on', {
100554               domain: 'wikidata.org'
100555             })).call(svgIcon('#iD-icon-out-link')).on('click', function (d3_event) {
100556               d3_event.preventDefault();
100557               if (_wikiURL) window.open(_wikiURL, '_blank');
100558             });
100559             searchRow = searchRow.merge(searchRowEnter);
100560             _searchInput = searchRow.select('input');
100561             var wikidataProperties = ['description', 'identifier'];
100562             var items = list.selectAll('li.labeled-input').data(wikidataProperties); // Enter
100563
100564             var enter = items.enter().append('li').attr('class', function (d) {
100565               return 'labeled-input preset-wikidata-' + d;
100566             });
100567             enter.append('span').attr('class', 'label').html(function (d) {
100568               return _t.html('wikidata.' + d);
100569             });
100570             enter.append('input').attr('type', 'text').call(utilNoAuto).classed('disabled', 'true').attr('readonly', 'true');
100571             enter.append('button').attr('class', 'form-field-button').attr('title', _t('icons.copy')).call(svgIcon('#iD-operation-copy')).on('click', function (d3_event) {
100572               d3_event.preventDefault();
100573               select(this.parentNode).select('input').node().select();
100574               document.execCommand('copy');
100575             });
100576           }
100577
100578           function fetchWikidataItems(q, callback) {
100579             if (!q && _hintKey) {
100580               // other tags may be good search terms
100581               for (var i in _entityIDs) {
100582                 var entity = context.hasEntity(_entityIDs[i]);
100583
100584                 if (entity.tags[_hintKey]) {
100585                   q = entity.tags[_hintKey];
100586                   break;
100587                 }
100588               }
100589             }
100590
100591             wikidata.itemsForSearchQuery(q, function (err, data) {
100592               if (err) return;
100593
100594               for (var i in data) {
100595                 data[i].value = data[i].label + ' (' + data[i].id + ')';
100596                 data[i].title = data[i].description;
100597               }
100598
100599               if (callback) callback(data);
100600             });
100601           }
100602
100603           function change() {
100604             var syncTags = {};
100605             syncTags[field.key] = _qid;
100606             dispatch.call('change', this, syncTags); // attempt asynchronous update of wikidata tag..
100607
100608             var initGraph = context.graph();
100609             var initEntityIDs = _entityIDs;
100610             wikidata.entityByQID(_qid, function (err, entity) {
100611               if (err) return; // If graph has changed, we can't apply this update.
100612
100613               if (context.graph() !== initGraph) return;
100614               if (!entity.sitelinks) return;
100615               var langs = wikidata.languagesToQuery(); // use the label and description languages as fallbacks
100616
100617               ['labels', 'descriptions'].forEach(function (key) {
100618                 if (!entity[key]) return;
100619                 var valueLangs = Object.keys(entity[key]);
100620                 if (valueLangs.length === 0) return;
100621                 var valueLang = valueLangs[0];
100622
100623                 if (langs.indexOf(valueLang) === -1) {
100624                   langs.push(valueLang);
100625                 }
100626               });
100627               var newWikipediaValue;
100628
100629               if (_wikipediaKey) {
100630                 var foundPreferred;
100631
100632                 for (var i in langs) {
100633                   var lang = langs[i];
100634                   var siteID = lang.replace('-', '_') + 'wiki';
100635
100636                   if (entity.sitelinks[siteID]) {
100637                     foundPreferred = true;
100638                     newWikipediaValue = lang + ':' + entity.sitelinks[siteID].title; // use the first match
100639
100640                     break;
100641                   }
100642                 }
100643
100644                 if (!foundPreferred) {
100645                   // No wikipedia sites available in the user's language or the fallback languages,
100646                   // default to any wikipedia sitelink
100647                   var wikiSiteKeys = Object.keys(entity.sitelinks).filter(function (site) {
100648                     return site.endsWith('wiki');
100649                   });
100650
100651                   if (wikiSiteKeys.length === 0) {
100652                     // if no wikipedia pages are linked to this wikidata entity, delete that tag
100653                     newWikipediaValue = null;
100654                   } else {
100655                     var wikiLang = wikiSiteKeys[0].slice(0, -4).replace('_', '-');
100656                     var wikiTitle = entity.sitelinks[wikiSiteKeys[0]].title;
100657                     newWikipediaValue = wikiLang + ':' + wikiTitle;
100658                   }
100659                 }
100660               }
100661
100662               if (newWikipediaValue) {
100663                 newWikipediaValue = context.cleanTagValue(newWikipediaValue);
100664               }
100665
100666               if (typeof newWikipediaValue === 'undefined') return;
100667               var actions = initEntityIDs.map(function (entityID) {
100668                 var entity = context.hasEntity(entityID);
100669                 if (!entity) return null;
100670                 var currTags = Object.assign({}, entity.tags); // shallow copy
100671
100672                 if (newWikipediaValue === null) {
100673                   if (!currTags[_wikipediaKey]) return null;
100674                   delete currTags[_wikipediaKey];
100675                 } else {
100676                   currTags[_wikipediaKey] = newWikipediaValue;
100677                 }
100678
100679                 return actionChangeTags(entityID, currTags);
100680               }).filter(Boolean);
100681               if (!actions.length) return; // Coalesce the update of wikidata tag into the previous tag change
100682
100683               context.overwrite(function actionUpdateWikipediaTags(graph) {
100684                 actions.forEach(function (action) {
100685                   graph = action(graph);
100686                 });
100687                 return graph;
100688               }, context.history().undoAnnotation()); // do not dispatch.call('change') here, because entity_editor
100689               // changeTags() is not intended to be called asynchronously
100690             });
100691           }
100692
100693           function setLabelForEntity() {
100694             var label = '';
100695
100696             if (_wikidataEntity) {
100697               label = entityPropertyForDisplay(_wikidataEntity, 'labels');
100698
100699               if (label.length === 0) {
100700                 label = _wikidataEntity.id.toString();
100701               }
100702             }
100703
100704             utilGetSetValue(_searchInput, label);
100705           }
100706
100707           wiki.tags = function (tags) {
100708             var isMixed = Array.isArray(tags[field.key]);
100709
100710             _searchInput.attr('title', isMixed ? tags[field.key].filter(Boolean).join('\n') : null).attr('placeholder', isMixed ? _t('inspector.multiple_values') : '').classed('mixed', isMixed);
100711
100712             _qid = typeof tags[field.key] === 'string' && tags[field.key] || '';
100713
100714             if (!/^Q[0-9]*$/.test(_qid)) {
100715               // not a proper QID
100716               unrecognized();
100717               return;
100718             } // QID value in correct format
100719
100720
100721             _wikiURL = 'https://wikidata.org/wiki/' + _qid;
100722             wikidata.entityByQID(_qid, function (err, entity) {
100723               if (err) {
100724                 unrecognized();
100725                 return;
100726               }
100727
100728               _wikidataEntity = entity;
100729               setLabelForEntity();
100730               var description = entityPropertyForDisplay(entity, 'descriptions');
100731
100732               _selection.select('button.wiki-link').classed('disabled', false);
100733
100734               _selection.select('.preset-wikidata-description').style('display', function () {
100735                 return description.length > 0 ? 'flex' : 'none';
100736               }).select('input').attr('value', description);
100737
100738               _selection.select('.preset-wikidata-identifier').style('display', function () {
100739                 return entity.id ? 'flex' : 'none';
100740               }).select('input').attr('value', entity.id);
100741             }); // not a proper QID
100742
100743             function unrecognized() {
100744               _wikidataEntity = null;
100745               setLabelForEntity();
100746
100747               _selection.select('.preset-wikidata-description').style('display', 'none');
100748
100749               _selection.select('.preset-wikidata-identifier').style('display', 'none');
100750
100751               _selection.select('button.wiki-link').classed('disabled', true);
100752
100753               if (_qid && _qid !== '') {
100754                 _wikiURL = 'https://wikidata.org/wiki/Special:Search?search=' + _qid;
100755               } else {
100756                 _wikiURL = '';
100757               }
100758             }
100759           };
100760
100761           function entityPropertyForDisplay(wikidataEntity, propKey) {
100762             if (!wikidataEntity[propKey]) return '';
100763             var propObj = wikidataEntity[propKey];
100764             var langKeys = Object.keys(propObj);
100765             if (langKeys.length === 0) return ''; // sorted by priority, since we want to show the user's language first if possible
100766
100767             var langs = wikidata.languagesToQuery();
100768
100769             for (var i in langs) {
100770               var lang = langs[i];
100771               var valueObj = propObj[lang];
100772               if (valueObj && valueObj.value && valueObj.value.length > 0) return valueObj.value;
100773             } // default to any available value
100774
100775
100776             return propObj[langKeys[0]].value;
100777           }
100778
100779           wiki.entityIDs = function (val) {
100780             if (!arguments.length) return _entityIDs;
100781             _entityIDs = val;
100782             return wiki;
100783           };
100784
100785           wiki.focus = function () {
100786             _searchInput.node().focus();
100787           };
100788
100789           return utilRebind(wiki, dispatch, 'on');
100790         }
100791
100792         function uiFieldWikipedia(field, context) {
100793           var _arguments = arguments;
100794           var dispatch = dispatch$8('change');
100795           var wikipedia = services.wikipedia;
100796           var wikidata = services.wikidata;
100797
100798           var _langInput = select(null);
100799
100800           var _titleInput = select(null);
100801
100802           var _wikiURL = '';
100803
100804           var _entityIDs;
100805
100806           var _tags;
100807
100808           var _dataWikipedia = [];
100809           _mainFileFetcher.get('wmf_sitematrix').then(function (d) {
100810             _dataWikipedia = d;
100811             if (_tags) updateForTags(_tags);
100812           })["catch"](function () {
100813             /* ignore */
100814           });
100815           var langCombo = uiCombobox(context, 'wikipedia-lang').fetcher(function (value, callback) {
100816             var v = value.toLowerCase();
100817             callback(_dataWikipedia.filter(function (d) {
100818               return d[0].toLowerCase().indexOf(v) >= 0 || d[1].toLowerCase().indexOf(v) >= 0 || d[2].toLowerCase().indexOf(v) >= 0;
100819             }).map(function (d) {
100820               return {
100821                 value: d[1]
100822               };
100823             }));
100824           });
100825           var titleCombo = uiCombobox(context, 'wikipedia-title').fetcher(function (value, callback) {
100826             if (!value) {
100827               value = '';
100828
100829               for (var i in _entityIDs) {
100830                 var entity = context.hasEntity(_entityIDs[i]);
100831
100832                 if (entity.tags.name) {
100833                   value = entity.tags.name;
100834                   break;
100835                 }
100836               }
100837             }
100838
100839             var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
100840             searchfn(language()[2], value, function (query, data) {
100841               callback(data.map(function (d) {
100842                 return {
100843                   value: d
100844                 };
100845               }));
100846             });
100847           });
100848
100849           function wiki(selection) {
100850             var wrap = selection.selectAll('.form-field-input-wrap').data([0]);
100851             wrap = wrap.enter().append('div').attr('class', "form-field-input-wrap form-field-input-".concat(field.type)).merge(wrap);
100852             var langContainer = wrap.selectAll('.wiki-lang-container').data([0]);
100853             langContainer = langContainer.enter().append('div').attr('class', 'wiki-lang-container').merge(langContainer);
100854             _langInput = langContainer.selectAll('input.wiki-lang').data([0]);
100855             _langInput = _langInput.enter().append('input').attr('type', 'text').attr('class', 'wiki-lang').attr('placeholder', _t('translate.localized_translation_language')).call(utilNoAuto).call(langCombo).merge(_langInput);
100856
100857             _langInput.on('blur', changeLang).on('change', changeLang);
100858
100859             var titleContainer = wrap.selectAll('.wiki-title-container').data([0]);
100860             titleContainer = titleContainer.enter().append('div').attr('class', 'wiki-title-container').merge(titleContainer);
100861             _titleInput = titleContainer.selectAll('input.wiki-title').data([0]);
100862             _titleInput = _titleInput.enter().append('input').attr('type', 'text').attr('class', 'wiki-title').attr('id', field.domId).call(utilNoAuto).call(titleCombo).merge(_titleInput);
100863
100864             _titleInput.on('blur', function () {
100865               change(true);
100866             }).on('change', function () {
100867               change(false);
100868             });
100869
100870             var link = titleContainer.selectAll('.wiki-link').data([0]);
100871             link = link.enter().append('button').attr('class', 'form-field-button wiki-link').attr('title', _t('icons.view_on', {
100872               domain: 'wikipedia.org'
100873             })).call(svgIcon('#iD-icon-out-link')).merge(link);
100874             link.on('click', function (d3_event) {
100875               d3_event.preventDefault();
100876               if (_wikiURL) window.open(_wikiURL, '_blank');
100877             });
100878           }
100879
100880           function defaultLanguageInfo(skipEnglishFallback) {
100881             var langCode = _mainLocalizer.languageCode().toLowerCase();
100882
100883             for (var i in _dataWikipedia) {
100884               var d = _dataWikipedia[i]; // default to the language of iD's current locale
100885
100886               if (d[2] === langCode) return d;
100887             } // fallback to English
100888
100889
100890             return skipEnglishFallback ? ['', '', ''] : ['English', 'English', 'en'];
100891           }
100892
100893           function language(skipEnglishFallback) {
100894             var value = utilGetSetValue(_langInput).toLowerCase();
100895
100896             for (var i in _dataWikipedia) {
100897               var d = _dataWikipedia[i]; // return the language already set in the UI, if supported
100898
100899               if (d[0].toLowerCase() === value || d[1].toLowerCase() === value || d[2] === value) return d;
100900             } // fallback to English
100901
100902
100903             return defaultLanguageInfo(skipEnglishFallback);
100904           }
100905
100906           function changeLang() {
100907             utilGetSetValue(_langInput, language()[1]);
100908             change(true);
100909           }
100910
100911           function change(skipWikidata) {
100912             var value = utilGetSetValue(_titleInput);
100913             var m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/);
100914
100915             var langInfo = m && _dataWikipedia.find(function (d) {
100916               return m[1] === d[2];
100917             });
100918
100919             var syncTags = {};
100920
100921             if (langInfo) {
100922               var nativeLangName = langInfo[1]; // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
100923
100924               value = decodeURIComponent(m[2]).replace(/_/g, ' ');
100925
100926               if (m[3]) {
100927                 var anchor; // try {
100928                 // leave this out for now - #6232
100929                 // Best-effort `anchordecode:` implementation
100930                 // anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
100931                 // } catch (e) {
100932
100933                 anchor = decodeURIComponent(m[3]); // }
100934
100935                 value += '#' + anchor.replace(/_/g, ' ');
100936               }
100937
100938               value = value.slice(0, 1).toUpperCase() + value.slice(1);
100939               utilGetSetValue(_langInput, nativeLangName);
100940               utilGetSetValue(_titleInput, value);
100941             }
100942
100943             if (value) {
100944               syncTags.wikipedia = context.cleanTagValue(language()[2] + ':' + value);
100945             } else {
100946               syncTags.wikipedia = undefined;
100947             }
100948
100949             dispatch.call('change', this, syncTags);
100950             if (skipWikidata || !value || !language()[2]) return; // attempt asynchronous update of wikidata tag..
100951
100952             var initGraph = context.graph();
100953             var initEntityIDs = _entityIDs;
100954             wikidata.itemsByTitle(language()[2], value, function (err, data) {
100955               if (err || !data || !Object.keys(data).length) return; // If graph has changed, we can't apply this update.
100956
100957               if (context.graph() !== initGraph) return;
100958               var qids = Object.keys(data);
100959               var value = qids && qids.find(function (id) {
100960                 return id.match(/^Q\d+$/);
100961               });
100962               var actions = initEntityIDs.map(function (entityID) {
100963                 var entity = context.entity(entityID).tags;
100964                 var currTags = Object.assign({}, entity); // shallow copy
100965
100966                 if (currTags.wikidata !== value) {
100967                   currTags.wikidata = value;
100968                   return actionChangeTags(entityID, currTags);
100969                 }
100970
100971                 return null;
100972               }).filter(Boolean);
100973               if (!actions.length) return; // Coalesce the update of wikidata tag into the previous tag change
100974
100975               context.overwrite(function actionUpdateWikidataTags(graph) {
100976                 actions.forEach(function (action) {
100977                   graph = action(graph);
100978                 });
100979                 return graph;
100980               }, context.history().undoAnnotation()); // do not dispatch.call('change') here, because entity_editor
100981               // changeTags() is not intended to be called asynchronously
100982             });
100983           }
100984
100985           wiki.tags = function (tags) {
100986             _tags = tags;
100987             updateForTags(tags);
100988           };
100989
100990           function updateForTags(tags) {
100991             var value = typeof tags[field.key] === 'string' ? tags[field.key] : ''; // Expect tag format of `tagLang:tagArticleTitle`, e.g. `fr:Paris`, with
100992             // optional suffix of `#anchor`
100993
100994             var m = value.match(/([^:]+):([^#]+)(?:#(.+))?/);
100995             var tagLang = m && m[1];
100996             var tagArticleTitle = m && m[2];
100997             var anchor = m && m[3];
100998
100999             var tagLangInfo = tagLang && _dataWikipedia.find(function (d) {
101000               return tagLang === d[2];
101001             }); // value in correct format
101002
101003
101004             if (tagLangInfo) {
101005               var nativeLangName = tagLangInfo[1];
101006               utilGetSetValue(_langInput, nativeLangName);
101007               utilGetSetValue(_titleInput, tagArticleTitle + (anchor ? '#' + anchor : ''));
101008
101009               if (anchor) {
101010                 try {
101011                   // Best-effort `anchorencode:` implementation
101012                   anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
101013                 } catch (e) {
101014                   anchor = anchor.replace(/ /g, '_');
101015                 }
101016               }
101017
101018               _wikiURL = 'https://' + tagLang + '.wikipedia.org/wiki/' + tagArticleTitle.replace(/ /g, '_') + (anchor ? '#' + anchor : ''); // unrecognized value format
101019             } else {
101020               utilGetSetValue(_titleInput, value);
101021
101022               if (value && value !== '') {
101023                 utilGetSetValue(_langInput, '');
101024                 var defaultLangInfo = defaultLanguageInfo();
101025                 _wikiURL = "https://".concat(defaultLangInfo[2], ".wikipedia.org/w/index.php?fulltext=1&search=").concat(value);
101026               } else {
101027                 var shownOrDefaultLangInfo = language(true
101028                 /* skipEnglishFallback */
101029                 );
101030                 utilGetSetValue(_langInput, shownOrDefaultLangInfo[1]);
101031                 _wikiURL = '';
101032               }
101033             }
101034           }
101035
101036           wiki.entityIDs = function (val) {
101037             if (!_arguments.length) return _entityIDs;
101038             _entityIDs = val;
101039             return wiki;
101040           };
101041
101042           wiki.focus = function () {
101043             _titleInput.node().focus();
101044           };
101045
101046           return utilRebind(wiki, dispatch, 'on');
101047         }
101048         uiFieldWikipedia.supportsMultiselection = false;
101049
101050         var uiFields = {
101051           access: uiFieldAccess,
101052           address: uiFieldAddress,
101053           check: uiFieldCheck,
101054           combo: uiFieldCombo,
101055           cycleway: uiFieldCycleway,
101056           defaultCheck: uiFieldCheck,
101057           email: uiFieldText,
101058           identifier: uiFieldText,
101059           lanes: uiFieldLanes,
101060           localized: uiFieldLocalized,
101061           roadheight: uiFieldRoadheight,
101062           roadspeed: uiFieldRoadspeed,
101063           manyCombo: uiFieldCombo,
101064           multiCombo: uiFieldCombo,
101065           networkCombo: uiFieldCombo,
101066           number: uiFieldText,
101067           onewayCheck: uiFieldCheck,
101068           radio: uiFieldRadio,
101069           restrictions: uiFieldRestrictions,
101070           semiCombo: uiFieldCombo,
101071           structureRadio: uiFieldRadio,
101072           tel: uiFieldText,
101073           text: uiFieldText,
101074           textarea: uiFieldTextarea,
101075           typeCombo: uiFieldCombo,
101076           url: uiFieldText,
101077           wikidata: uiFieldWikidata,
101078           wikipedia: uiFieldWikipedia
101079         };
101080
101081         function uiField(context, presetField, entityIDs, options) {
101082           options = Object.assign({
101083             show: true,
101084             wrap: true,
101085             remove: true,
101086             revert: true,
101087             info: true
101088           }, options);
101089           var dispatch = dispatch$8('change', 'revert');
101090           var field = Object.assign({}, presetField); // shallow copy
101091
101092           field.domId = utilUniqueDomId('form-field-' + field.safeid);
101093           var _show = options.show;
101094           var _state = '';
101095           var _tags = {};
101096
101097           var _entityExtent;
101098
101099           if (entityIDs && entityIDs.length) {
101100             _entityExtent = entityIDs.reduce(function (extent, entityID) {
101101               var entity = context.graph().entity(entityID);
101102               return extent.extend(entity.extent(context.graph()));
101103             }, geoExtent());
101104           }
101105
101106           var _locked = false;
101107
101108           var _lockedTip = uiTooltip().title(_t.html('inspector.lock.suggestion', {
101109             label: field.label
101110           })).placement('bottom');
101111
101112           field.keys = field.keys || [field.key]; // only create the fields that are actually being shown
101113
101114           if (_show && !field.impl) {
101115             createField();
101116           } // Creates the field.. This is done lazily,
101117           // once we know that the field will be shown.
101118
101119
101120           function createField() {
101121             field.impl = uiFields[field.type](field, context).on('change', function (t, onInput) {
101122               dispatch.call('change', field, t, onInput);
101123             });
101124
101125             if (entityIDs) {
101126               field.entityIDs = entityIDs; // if this field cares about the entities, pass them along
101127
101128               if (field.impl.entityIDs) {
101129                 field.impl.entityIDs(entityIDs);
101130               }
101131             }
101132           }
101133
101134           function isModified() {
101135             if (!entityIDs || !entityIDs.length) return false;
101136             return entityIDs.some(function (entityID) {
101137               var original = context.graph().base().entities[entityID];
101138               var latest = context.graph().entity(entityID);
101139               return field.keys.some(function (key) {
101140                 return original ? latest.tags[key] !== original.tags[key] : latest.tags[key];
101141               });
101142             });
101143           }
101144
101145           function tagsContainFieldKey() {
101146             return field.keys.some(function (key) {
101147               if (field.type === 'multiCombo') {
101148                 for (var tagKey in _tags) {
101149                   if (tagKey.indexOf(key) === 0) {
101150                     return true;
101151                   }
101152                 }
101153
101154                 return false;
101155               }
101156
101157               return _tags[key] !== undefined;
101158             });
101159           }
101160
101161           function revert(d3_event, d) {
101162             d3_event.stopPropagation();
101163             d3_event.preventDefault();
101164             if (!entityIDs || _locked) return;
101165             dispatch.call('revert', d, d.keys);
101166           }
101167
101168           function remove(d3_event, d) {
101169             d3_event.stopPropagation();
101170             d3_event.preventDefault();
101171             if (_locked) return;
101172             var t = {};
101173             d.keys.forEach(function (key) {
101174               t[key] = undefined;
101175             });
101176             dispatch.call('change', d, t);
101177           }
101178
101179           field.render = function (selection) {
101180             var container = selection.selectAll('.form-field').data([field]); // Enter
101181
101182             var enter = container.enter().append('div').attr('class', function (d) {
101183               return 'form-field form-field-' + d.safeid;
101184             }).classed('nowrap', !options.wrap);
101185
101186             if (options.wrap) {
101187               var labelEnter = enter.append('label').attr('class', 'field-label').attr('for', function (d) {
101188                 return d.domId;
101189               });
101190               var textEnter = labelEnter.append('span').attr('class', 'label-text');
101191               textEnter.append('span').attr('class', 'label-textvalue').html(function (d) {
101192                 return d.label();
101193               });
101194               textEnter.append('span').attr('class', 'label-textannotation');
101195
101196               if (options.remove) {
101197                 labelEnter.append('button').attr('class', 'remove-icon').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete'));
101198               }
101199
101200               if (options.revert) {
101201                 labelEnter.append('button').attr('class', 'modified-icon').attr('title', _t('icons.undo')).call(svgIcon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-redo' : '#iD-icon-undo'));
101202               }
101203             } // Update
101204
101205
101206             container = container.merge(enter);
101207             container.select('.field-label > .remove-icon') // propagate bound data
101208             .on('click', remove);
101209             container.select('.field-label > .modified-icon') // propagate bound data
101210             .on('click', revert);
101211             container.each(function (d) {
101212               var selection = select(this);
101213
101214               if (!d.impl) {
101215                 createField();
101216               }
101217
101218               var reference, help; // instantiate field help
101219
101220               if (options.wrap && field.type === 'restrictions') {
101221                 help = uiFieldHelp(context, 'restrictions');
101222               } // instantiate tag reference
101223
101224
101225               if (options.wrap && options.info) {
101226                 var referenceKey = d.key || '';
101227
101228                 if (d.type === 'multiCombo') {
101229                   // lookup key without the trailing ':'
101230                   referenceKey = referenceKey.replace(/:$/, '');
101231                 }
101232
101233                 reference = uiTagReference(d.reference || {
101234                   key: referenceKey
101235                 });
101236
101237                 if (_state === 'hover') {
101238                   reference.showing(false);
101239                 }
101240               }
101241
101242               selection.call(d.impl); // add field help components
101243
101244               if (help) {
101245                 selection.call(help.body).select('.field-label').call(help.button);
101246               } // add tag reference components
101247
101248
101249               if (reference) {
101250                 selection.call(reference.body).select('.field-label').call(reference.button);
101251               }
101252
101253               d.impl.tags(_tags);
101254             });
101255             container.classed('locked', _locked).classed('modified', isModified()).classed('present', tagsContainFieldKey()); // show a tip and lock icon if the field is locked
101256
101257             var annotation = container.selectAll('.field-label .label-textannotation');
101258             var icon = annotation.selectAll('.icon').data(_locked ? [0] : []);
101259             icon.exit().remove();
101260             icon.enter().append('svg').attr('class', 'icon').append('use').attr('xlink:href', '#fas-lock');
101261             container.call(_locked ? _lockedTip : _lockedTip.destroy);
101262           };
101263
101264           field.state = function (val) {
101265             if (!arguments.length) return _state;
101266             _state = val;
101267             return field;
101268           };
101269
101270           field.tags = function (val) {
101271             if (!arguments.length) return _tags;
101272             _tags = val;
101273
101274             if (tagsContainFieldKey() && !_show) {
101275               // always show a field if it has a value to display
101276               _show = true;
101277
101278               if (!field.impl) {
101279                 createField();
101280               }
101281             }
101282
101283             return field;
101284           };
101285
101286           field.locked = function (val) {
101287             if (!arguments.length) return _locked;
101288             _locked = val;
101289             return field;
101290           };
101291
101292           field.show = function () {
101293             _show = true;
101294
101295             if (!field.impl) {
101296               createField();
101297             }
101298
101299             if (field["default"] && field.key && _tags[field.key] !== field["default"]) {
101300               var t = {};
101301               t[field.key] = field["default"];
101302               dispatch.call('change', this, t);
101303             }
101304           }; // A shown field has a visible UI, a non-shown field is in the 'Add field' dropdown
101305
101306
101307           field.isShown = function () {
101308             return _show;
101309           }; // An allowed field can appear in the UI or in the 'Add field' dropdown.
101310           // A non-allowed field is hidden from the user altogether
101311
101312
101313           field.isAllowed = function () {
101314             if (entityIDs && entityIDs.length > 1 && uiFields[field.type].supportsMultiselection === false) return false;
101315             if (field.geometry && !entityIDs.every(function (entityID) {
101316               return field.matchGeometry(context.graph().geometry(entityID));
101317             })) return false;
101318
101319             if (entityIDs && _entityExtent && field.locationSetID) {
101320               // is field allowed in this location?
101321               var validLocations = _mainLocations.locationsAt(_entityExtent.center());
101322               if (!validLocations[field.locationSetID]) return false;
101323             }
101324
101325             var prerequisiteTag = field.prerequisiteTag;
101326
101327             if (entityIDs && !tagsContainFieldKey() && // ignore tagging prerequisites if a value is already present
101328             prerequisiteTag) {
101329               if (!entityIDs.every(function (entityID) {
101330                 var entity = context.graph().entity(entityID);
101331
101332                 if (prerequisiteTag.key) {
101333                   var value = entity.tags[prerequisiteTag.key];
101334                   if (!value) return false;
101335
101336                   if (prerequisiteTag.valueNot) {
101337                     return prerequisiteTag.valueNot !== value;
101338                   }
101339
101340                   if (prerequisiteTag.value) {
101341                     return prerequisiteTag.value === value;
101342                   }
101343                 } else if (prerequisiteTag.keyNot) {
101344                   if (entity.tags[prerequisiteTag.keyNot]) return false;
101345                 }
101346
101347                 return true;
101348               })) return false;
101349             }
101350
101351             return true;
101352           };
101353
101354           field.focus = function () {
101355             if (field.impl) {
101356               field.impl.focus();
101357             }
101358           };
101359
101360           return utilRebind(field, dispatch, 'on');
101361         }
101362
101363         function uiFormFields(context) {
101364           var moreCombo = uiCombobox(context, 'more-fields').minItems(1);
101365           var _fieldsArr = [];
101366           var _lastPlaceholder = '';
101367           var _state = '';
101368           var _klass = '';
101369
101370           function formFields(selection) {
101371             var allowedFields = _fieldsArr.filter(function (field) {
101372               return field.isAllowed();
101373             });
101374
101375             var shown = allowedFields.filter(function (field) {
101376               return field.isShown();
101377             });
101378             var notShown = allowedFields.filter(function (field) {
101379               return !field.isShown();
101380             });
101381             var container = selection.selectAll('.form-fields-container').data([0]);
101382             container = container.enter().append('div').attr('class', 'form-fields-container ' + (_klass || '')).merge(container);
101383             var fields = container.selectAll('.wrap-form-field').data(shown, function (d) {
101384               return d.id + (d.entityIDs ? d.entityIDs.join() : '');
101385             });
101386             fields.exit().remove(); // Enter
101387
101388             var enter = fields.enter().append('div').attr('class', function (d) {
101389               return 'wrap-form-field wrap-form-field-' + d.safeid;
101390             }); // Update
101391
101392             fields = fields.merge(enter);
101393             fields.order().each(function (d) {
101394               select(this).call(d.render);
101395             });
101396             var titles = [];
101397             var moreFields = notShown.map(function (field) {
101398               var title = field.title();
101399               titles.push(title);
101400               var terms = field.terms();
101401               if (field.key) terms.push(field.key);
101402               if (field.keys) terms = terms.concat(field.keys);
101403               return {
101404                 display: field.label(),
101405                 value: title,
101406                 title: title,
101407                 field: field,
101408                 terms: terms
101409               };
101410             });
101411             var placeholder = titles.slice(0, 3).join(', ') + (titles.length > 3 ? '…' : '');
101412             var more = selection.selectAll('.more-fields').data(_state === 'hover' || moreFields.length === 0 ? [] : [0]);
101413             more.exit().remove();
101414             var moreEnter = more.enter().append('div').attr('class', 'more-fields').append('label');
101415             moreEnter.append('span').call(_t.append('inspector.add_fields'));
101416             more = moreEnter.merge(more);
101417             var input = more.selectAll('.value').data([0]);
101418             input.exit().remove();
101419             input = input.enter().append('input').attr('class', 'value').attr('type', 'text').attr('placeholder', placeholder).call(utilNoAuto).merge(input);
101420             input.call(utilGetSetValue, '').call(moreCombo.data(moreFields).on('accept', function (d) {
101421               if (!d) return; // user entered something that was not matched
101422
101423               var field = d.field;
101424               field.show();
101425               selection.call(formFields); // rerender
101426
101427               field.focus();
101428             })); // avoid updating placeholder excessively (triggers style recalc)
101429
101430             if (_lastPlaceholder !== placeholder) {
101431               input.attr('placeholder', placeholder);
101432               _lastPlaceholder = placeholder;
101433             }
101434           }
101435
101436           formFields.fieldsArr = function (val) {
101437             if (!arguments.length) return _fieldsArr;
101438             _fieldsArr = val || [];
101439             return formFields;
101440           };
101441
101442           formFields.state = function (val) {
101443             if (!arguments.length) return _state;
101444             _state = val;
101445             return formFields;
101446           };
101447
101448           formFields.klass = function (val) {
101449             if (!arguments.length) return _klass;
101450             _klass = val;
101451             return formFields;
101452           };
101453
101454           return formFields;
101455         }
101456
101457         function uiChangesetEditor(context) {
101458           var dispatch = dispatch$8('change');
101459           var formFields = uiFormFields(context);
101460           var commentCombo = uiCombobox(context, 'comment').caseSensitive(true);
101461
101462           var _fieldsArr;
101463
101464           var _tags;
101465
101466           var _changesetID;
101467
101468           function changesetEditor(selection) {
101469             render(selection);
101470           }
101471
101472           function render(selection) {
101473             var initial = false;
101474
101475             if (!_fieldsArr) {
101476               initial = true;
101477               var presets = _mainPresetIndex;
101478               _fieldsArr = [uiField(context, presets.field('comment'), null, {
101479                 show: true,
101480                 revert: false
101481               }), uiField(context, presets.field('source'), null, {
101482                 show: false,
101483                 revert: false
101484               }), uiField(context, presets.field('hashtags'), null, {
101485                 show: false,
101486                 revert: false
101487               })];
101488
101489               _fieldsArr.forEach(function (field) {
101490                 field.on('change', function (t, onInput) {
101491                   dispatch.call('change', field, undefined, t, onInput);
101492                 });
101493               });
101494             }
101495
101496             _fieldsArr.forEach(function (field) {
101497               field.tags(_tags);
101498             });
101499
101500             selection.call(formFields.fieldsArr(_fieldsArr));
101501
101502             if (initial) {
101503               var commentField = selection.select('.form-field-comment textarea');
101504               var commentNode = commentField.node();
101505
101506               if (commentNode) {
101507                 commentNode.focus();
101508                 commentNode.select();
101509               } // trigger a 'blur' event so that comment field can be cleaned
101510               // and checked for hashtags, even if retrieved from localstorage
101511
101512
101513               utilTriggerEvent(commentField, 'blur');
101514               var osm = context.connection();
101515
101516               if (osm) {
101517                 osm.userChangesets(function (err, changesets) {
101518                   if (err) return;
101519                   var comments = changesets.map(function (changeset) {
101520                     var comment = changeset.tags.comment;
101521                     return comment ? {
101522                       title: comment,
101523                       value: comment
101524                     } : null;
101525                   }).filter(Boolean);
101526                   commentField.call(commentCombo.data(utilArrayUniqBy(comments, 'title')));
101527                 });
101528               }
101529             } // Add warning if comment mentions Google
101530
101531
101532             var hasGoogle = _tags.comment.match(/google/i);
101533
101534             var commentWarning = selection.select('.form-field-comment').selectAll('.comment-warning').data(hasGoogle ? [0] : []);
101535             commentWarning.exit().transition().duration(200).style('opacity', 0).remove();
101536             var commentEnter = commentWarning.enter().insert('div', '.tag-reference-body').attr('class', 'field-warning comment-warning').style('opacity', 0);
101537             commentEnter.append('a').attr('target', '_blank').call(svgIcon('#iD-icon-alert', 'inline')).attr('href', _t('commit.google_warning_link')).append('span').call(_t.append('commit.google_warning'));
101538             commentEnter.transition().duration(200).style('opacity', 1);
101539           }
101540
101541           changesetEditor.tags = function (_) {
101542             if (!arguments.length) return _tags;
101543             _tags = _; // Don't reset _fieldsArr here.
101544
101545             return changesetEditor;
101546           };
101547
101548           changesetEditor.changesetID = function (_) {
101549             if (!arguments.length) return _changesetID;
101550             if (_changesetID === _) return changesetEditor;
101551             _changesetID = _;
101552             _fieldsArr = null;
101553             return changesetEditor;
101554           };
101555
101556           return utilRebind(changesetEditor, dispatch, 'on');
101557         }
101558
101559         var JXON = new function () {
101560           var sValueProp = 'keyValue',
101561               sAttributesProp = 'keyAttributes',
101562               sAttrPref = '@',
101563
101564           /* you can customize these values */
101565           aCache = [],
101566               rIsNull = /^\s*$/,
101567               rIsBool = /^(?:true|false)$/i;
101568
101569           function parseText(sValue) {
101570             if (rIsNull.test(sValue)) {
101571               return null;
101572             }
101573
101574             if (rIsBool.test(sValue)) {
101575               return sValue.toLowerCase() === 'true';
101576             }
101577
101578             if (isFinite(sValue)) {
101579               return parseFloat(sValue);
101580             }
101581
101582             if (isFinite(Date.parse(sValue))) {
101583               return new Date(sValue);
101584             }
101585
101586             return sValue;
101587           }
101588
101589           function EmptyTree() {}
101590
101591           EmptyTree.prototype.toString = function () {
101592             return 'null';
101593           };
101594
101595           EmptyTree.prototype.valueOf = function () {
101596             return null;
101597           };
101598
101599           function objectify(vValue) {
101600             return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
101601           }
101602
101603           function createObjTree(oParentNode, nVerb, bFreeze, bNesteAttr) {
101604             var nLevelStart = aCache.length,
101605                 bChildren = oParentNode.hasChildNodes(),
101606                 bAttributes = oParentNode.hasAttributes(),
101607                 bHighVerb = Boolean(nVerb & 2);
101608             var sProp,
101609                 vContent,
101610                 nLength = 0,
101611                 sCollectedTxt = '',
101612                 vResult = bHighVerb ? {} :
101613             /* put here the default value for empty nodes: */
101614             true;
101615
101616             if (bChildren) {
101617               for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
101618                 oNode = oParentNode.childNodes.item(nItem);
101619
101620                 if (oNode.nodeType === 4) {
101621                   /* nodeType is 'CDATASection' (4) */
101622                   sCollectedTxt += oNode.nodeValue;
101623                 } else if (oNode.nodeType === 3) {
101624                   /* nodeType is 'Text' (3) */
101625                   sCollectedTxt += oNode.nodeValue.trim();
101626                 } else if (oNode.nodeType === 1 && !oNode.prefix) {
101627                   /* nodeType is 'Element' (1) */
101628                   aCache.push(oNode);
101629                 }
101630               }
101631             }
101632
101633             var nLevelEnd = aCache.length,
101634                 vBuiltVal = parseText(sCollectedTxt);
101635
101636             if (!bHighVerb && (bChildren || bAttributes)) {
101637               vResult = nVerb === 0 ? objectify(vBuiltVal) : {};
101638             }
101639
101640             for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
101641               sProp = aCache[nElId].nodeName.toLowerCase();
101642               vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
101643
101644               if (vResult.hasOwnProperty(sProp)) {
101645                 if (vResult[sProp].constructor !== Array) {
101646                   vResult[sProp] = [vResult[sProp]];
101647                 }
101648
101649                 vResult[sProp].push(vContent);
101650               } else {
101651                 vResult[sProp] = vContent;
101652                 nLength++;
101653               }
101654             }
101655
101656             if (bAttributes) {
101657               var nAttrLen = oParentNode.attributes.length,
101658                   sAPrefix = bNesteAttr ? '' : sAttrPref,
101659                   oAttrParent = bNesteAttr ? {} : vResult;
101660
101661               for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
101662                 oAttrib = oParentNode.attributes.item(nAttrib);
101663                 oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
101664               }
101665
101666               if (bNesteAttr) {
101667                 if (bFreeze) {
101668                   Object.freeze(oAttrParent);
101669                 }
101670
101671                 vResult[sAttributesProp] = oAttrParent;
101672                 nLength -= nAttrLen - 1;
101673               }
101674             }
101675
101676             if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
101677               vResult[sValueProp] = vBuiltVal;
101678             } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
101679               vResult = vBuiltVal;
101680             }
101681
101682             if (bFreeze && (bHighVerb || nLength > 0)) {
101683               Object.freeze(vResult);
101684             }
101685
101686             aCache.length = nLevelStart;
101687             return vResult;
101688           }
101689
101690           function loadObjTree(oXMLDoc, oParentEl, oParentObj) {
101691             var vValue, oChild;
101692
101693             if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
101694               oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString()));
101695               /* verbosity level is 0 */
101696             } else if (oParentObj.constructor === Date) {
101697               oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));
101698             }
101699
101700             for (var sName in oParentObj) {
101701               vValue = oParentObj[sName];
101702
101703               if (isFinite(sName) || vValue instanceof Function) {
101704                 continue;
101705               }
101706               /* verbosity level is 0 */
101707
101708
101709               if (sName === sValueProp) {
101710                 if (vValue !== null && vValue !== true) {
101711                   oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue)));
101712                 }
101713               } else if (sName === sAttributesProp) {
101714                 /* verbosity level is 3 */
101715                 for (var sAttrib in vValue) {
101716                   oParentEl.setAttribute(sAttrib, vValue[sAttrib]);
101717                 }
101718               } else if (sName.charAt(0) === sAttrPref) {
101719                 oParentEl.setAttribute(sName.slice(1), vValue);
101720               } else if (vValue.constructor === Array) {
101721                 for (var nItem = 0; nItem < vValue.length; nItem++) {
101722                   oChild = oXMLDoc.createElement(sName);
101723                   loadObjTree(oXMLDoc, oChild, vValue[nItem]);
101724                   oParentEl.appendChild(oChild);
101725                 }
101726               } else {
101727                 oChild = oXMLDoc.createElement(sName);
101728
101729                 if (vValue instanceof Object) {
101730                   loadObjTree(oXMLDoc, oChild, vValue);
101731                 } else if (vValue !== null && vValue !== true) {
101732                   oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
101733                 }
101734
101735                 oParentEl.appendChild(oChild);
101736               }
101737             }
101738           }
101739
101740           this.build = function (oXMLParent, nVerbosity
101741           /* optional */
101742           , bFreeze
101743           /* optional */
101744           , bNesteAttributes
101745           /* optional */
101746           ) {
101747             var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 :
101748             /* put here the default verbosity level: */
101749             1;
101750
101751             return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);
101752           };
101753
101754           this.unbuild = function (oObjTree) {
101755             var oNewDoc = document.implementation.createDocument('', '', null);
101756             loadObjTree(oNewDoc, oNewDoc, oObjTree);
101757             return oNewDoc;
101758           };
101759
101760           this.stringify = function (oObjTree) {
101761             return new XMLSerializer().serializeToString(JXON.unbuild(oObjTree));
101762           };
101763         }(); // var myObject = JXON.build(doc);
101764         // we got our javascript object! try: alert(JSON.stringify(myObject));
101765         // var newDoc = JXON.unbuild(myObject);
101766         // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
101767
101768         function uiSectionChanges(context) {
101769           var detected = utilDetect();
101770           var _discardTags = {};
101771           _mainFileFetcher.get('discarded').then(function (d) {
101772             _discardTags = d;
101773           })["catch"](function () {
101774             /* ignore */
101775           });
101776           var section = uiSection('changes-list', context).label(function () {
101777             var history = context.history();
101778             var summary = history.difference().summary();
101779             return _t.html('inspector.title_count', {
101780               title: {
101781                 html: _t.html('commit.changes')
101782               },
101783               count: summary.length
101784             });
101785           }).disclosureContent(renderDisclosureContent);
101786
101787           function renderDisclosureContent(selection) {
101788             var history = context.history();
101789             var summary = history.difference().summary();
101790             var container = selection.selectAll('.commit-section').data([0]);
101791             var containerEnter = container.enter().append('div').attr('class', 'commit-section');
101792             containerEnter.append('ul').attr('class', 'changeset-list');
101793             container = containerEnter.merge(container);
101794             var items = container.select('ul').selectAll('li').data(summary);
101795             var itemsEnter = items.enter().append('li').attr('class', 'change-item');
101796             var buttons = itemsEnter.append('button').on('mouseover', mouseover).on('mouseout', mouseout).on('click', click);
101797             buttons.each(function (d) {
101798               select(this).call(svgIcon('#iD-icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
101799             });
101800             buttons.append('span').attr('class', 'change-type').html(function (d) {
101801               return _t.html('commit.' + d.changeType) + ' ';
101802             });
101803             buttons.append('strong').attr('class', 'entity-type').text(function (d) {
101804               var matched = _mainPresetIndex.match(d.entity, d.graph);
101805               return matched && matched.name() || utilDisplayType(d.entity.id);
101806             });
101807             buttons.append('span').attr('class', 'entity-name').text(function (d) {
101808               var name = utilDisplayName(d.entity) || '',
101809                   string = '';
101810
101811               if (name !== '') {
101812                 string += ':';
101813               }
101814
101815               return string += ' ' + name;
101816             });
101817             items = itemsEnter.merge(items); // Download changeset link
101818
101819             var changeset = new osmChangeset().update({
101820               id: undefined
101821             });
101822             var changes = history.changes(actionDiscardTags(history.difference(), _discardTags));
101823             delete changeset.id; // Export without chnageset_id
101824
101825             var data = JXON.stringify(changeset.osmChangeJXON(changes));
101826             var blob = new Blob([data], {
101827               type: 'text/xml;charset=utf-8;'
101828             });
101829             var fileName = 'changes.osc';
101830             var linkEnter = container.selectAll('.download-changes').data([0]).enter().append('a').attr('class', 'download-changes');
101831
101832             if (detected.download) {
101833               // All except IE11 and Edge
101834               linkEnter // download the data as a file
101835               .attr('href', window.URL.createObjectURL(blob)).attr('download', fileName);
101836             } else {
101837               // IE11 and Edge
101838               linkEnter // open data uri in a new tab
101839               .attr('target', '_blank').on('click.download', function () {
101840                 navigator.msSaveBlob(blob, fileName);
101841               });
101842             }
101843
101844             linkEnter.call(svgIcon('#iD-icon-load', 'inline')).append('span').call(_t.append('commit.download_changes'));
101845
101846             function mouseover(d) {
101847               if (d.entity) {
101848                 context.surface().selectAll(utilEntityOrMemberSelector([d.entity.id], context.graph())).classed('hover', true);
101849               }
101850             }
101851
101852             function mouseout() {
101853               context.surface().selectAll('.hover').classed('hover', false);
101854             }
101855
101856             function click(d3_event, change) {
101857               if (change.changeType !== 'deleted') {
101858                 var entity = change.entity;
101859                 context.map().zoomToEase(entity);
101860                 context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph())).classed('hover', true);
101861               }
101862             }
101863           }
101864
101865           return section;
101866         }
101867
101868         function uiCommitWarnings(context) {
101869           function commitWarnings(selection) {
101870             var issuesBySeverity = context.validator().getIssuesBySeverity({
101871               what: 'edited',
101872               where: 'all',
101873               includeDisabledRules: true
101874             });
101875
101876             for (var severity in issuesBySeverity) {
101877               var issues = issuesBySeverity[severity];
101878
101879               if (severity !== 'error') {
101880                 // exclude 'fixme' and similar - #8603
101881                 issues = issues.filter(function (issue) {
101882                   return issue.type !== 'help_request';
101883                 });
101884               }
101885
101886               var section = severity + '-section';
101887               var issueItem = severity + '-item';
101888               var container = selection.selectAll('.' + section).data(issues.length ? [0] : []);
101889               container.exit().remove();
101890               var containerEnter = container.enter().append('div').attr('class', 'modal-section ' + section + ' fillL2');
101891               containerEnter.append('h3').html(severity === 'warning' ? _t.html('commit.warnings') : _t.html('commit.errors'));
101892               containerEnter.append('ul').attr('class', 'changeset-list');
101893               container = containerEnter.merge(container);
101894               var items = container.select('ul').selectAll('li').data(issues, function (d) {
101895                 return d.key;
101896               });
101897               items.exit().remove();
101898               var itemsEnter = items.enter().append('li').attr('class', issueItem);
101899               var buttons = itemsEnter.append('button').on('mouseover', function (d3_event, d) {
101900                 if (d.entityIds) {
101901                   context.surface().selectAll(utilEntityOrMemberSelector(d.entityIds, context.graph())).classed('hover', true);
101902                 }
101903               }).on('mouseout', function () {
101904                 context.surface().selectAll('.hover').classed('hover', false);
101905               }).on('click', function (d3_event, d) {
101906                 context.validator().focusIssue(d);
101907               });
101908               buttons.call(svgIcon('#iD-icon-alert', 'pre-text'));
101909               buttons.append('strong').attr('class', 'issue-message');
101910               buttons.filter(function (d) {
101911                 return d.tooltip;
101912               }).call(uiTooltip().title(function (d) {
101913                 return d.tooltip;
101914               }).placement('top'));
101915               items = itemsEnter.merge(items);
101916               items.selectAll('.issue-message').html(function (d) {
101917                 return d.message(context);
101918               });
101919             }
101920           }
101921
101922           return commitWarnings;
101923         }
101924
101925         var readOnlyTags = [/^changesets_count$/, /^created_by$/, /^ideditor:/, /^imagery_used$/, /^host$/, /^locale$/, /^warnings:/, /^resolved:/, /^closed:note$/, /^closed:keepright$/, /^closed:improveosm:/, /^closed:osmose:/]; // treat most punctuation (except -, _, +, &) as hashtag delimiters - #4398
101926         // from https://stackoverflow.com/a/25575009
101927
101928         var hashtagRegex = /(#[^\u2000-\u206F\u2E00-\u2E7F\s\\'!"#$%()*,.\/:;<=>?@\[\]^`{|}~]+)/g;
101929         function uiCommit(context) {
101930           var dispatch = dispatch$8('cancel');
101931
101932           var _userDetails;
101933
101934           var _selection;
101935
101936           var changesetEditor = uiChangesetEditor(context).on('change', changeTags);
101937           var rawTagEditor = uiSectionRawTagEditor('changeset-tag-editor', context).on('change', changeTags).readOnlyTags(readOnlyTags);
101938           var commitChanges = uiSectionChanges(context);
101939           var commitWarnings = uiCommitWarnings(context);
101940
101941           function commit(selection) {
101942             _selection = selection; // Initialize changeset if one does not exist yet.
101943
101944             if (!context.changeset) initChangeset();
101945             loadDerivedChangesetTags();
101946             selection.call(render);
101947           }
101948
101949           function initChangeset() {
101950             // expire stored comment, hashtags, source after cutoff datetime - #3947 #4899
101951             var commentDate = +corePreferences('commentDate') || 0;
101952             var currDate = Date.now();
101953             var cutoff = 2 * 86400 * 1000; // 2 days
101954
101955             if (commentDate > currDate || currDate - commentDate > cutoff) {
101956               corePreferences('comment', null);
101957               corePreferences('hashtags', null);
101958               corePreferences('source', null);
101959             } // load in explicitly-set values, if any
101960
101961
101962             if (context.defaultChangesetComment()) {
101963               corePreferences('comment', context.defaultChangesetComment());
101964               corePreferences('commentDate', Date.now());
101965             }
101966
101967             if (context.defaultChangesetSource()) {
101968               corePreferences('source', context.defaultChangesetSource());
101969               corePreferences('commentDate', Date.now());
101970             }
101971
101972             if (context.defaultChangesetHashtags()) {
101973               corePreferences('hashtags', context.defaultChangesetHashtags());
101974               corePreferences('commentDate', Date.now());
101975             }
101976
101977             var detected = utilDetect();
101978             var tags = {
101979               comment: corePreferences('comment') || '',
101980               created_by: context.cleanTagValue('iD ' + context.version),
101981               host: context.cleanTagValue(detected.host),
101982               locale: context.cleanTagValue(_mainLocalizer.localeCode())
101983             }; // call findHashtags initially - this will remove stored
101984             // hashtags if any hashtags are found in the comment - #4304
101985
101986             findHashtags(tags, true);
101987             var hashtags = corePreferences('hashtags');
101988
101989             if (hashtags) {
101990               tags.hashtags = hashtags;
101991             }
101992
101993             var source = corePreferences('source');
101994
101995             if (source) {
101996               tags.source = source;
101997             }
101998
101999             var photoOverlaysUsed = context.history().photoOverlaysUsed();
102000
102001             if (photoOverlaysUsed.length) {
102002               var sources = (tags.source || '').split(';'); // include this tag for any photo layer
102003
102004               if (sources.indexOf('streetlevel imagery') === -1) {
102005                 sources.push('streetlevel imagery');
102006               } // add the photo overlays used during editing as sources
102007
102008
102009               photoOverlaysUsed.forEach(function (photoOverlay) {
102010                 if (sources.indexOf(photoOverlay) === -1) {
102011                   sources.push(photoOverlay);
102012                 }
102013               });
102014               tags.source = context.cleanTagValue(sources.join(';'));
102015             }
102016
102017             context.changeset = new osmChangeset({
102018               tags: tags
102019             });
102020           } // Calculates read-only metadata tags based on the user's editing session and applies
102021           // them to the changeset.
102022
102023
102024           function loadDerivedChangesetTags() {
102025             var osm = context.connection();
102026             if (!osm) return;
102027             var tags = Object.assign({}, context.changeset.tags); // shallow copy
102028             // assign tags for imagery used
102029
102030             var imageryUsed = context.cleanTagValue(context.history().imageryUsed().join(';'));
102031             tags.imagery_used = imageryUsed || 'None'; // assign tags for closed issues and notes
102032
102033             var osmClosed = osm.getClosedIDs();
102034             var itemType;
102035
102036             if (osmClosed.length) {
102037               tags['closed:note'] = context.cleanTagValue(osmClosed.join(';'));
102038             }
102039
102040             if (services.keepRight) {
102041               var krClosed = services.keepRight.getClosedIDs();
102042
102043               if (krClosed.length) {
102044                 tags['closed:keepright'] = context.cleanTagValue(krClosed.join(';'));
102045               }
102046             }
102047
102048             if (services.improveOSM) {
102049               var iOsmClosed = services.improveOSM.getClosedCounts();
102050
102051               for (itemType in iOsmClosed) {
102052                 tags['closed:improveosm:' + itemType] = context.cleanTagValue(iOsmClosed[itemType].toString());
102053               }
102054             }
102055
102056             if (services.osmose) {
102057               var osmoseClosed = services.osmose.getClosedCounts();
102058
102059               for (itemType in osmoseClosed) {
102060                 tags['closed:osmose:' + itemType] = context.cleanTagValue(osmoseClosed[itemType].toString());
102061               }
102062             } // remove existing issue counts
102063
102064
102065             for (var key in tags) {
102066               if (key.match(/(^warnings:)|(^resolved:)/)) {
102067                 delete tags[key];
102068               }
102069             }
102070
102071             function addIssueCounts(issues, prefix) {
102072               var issuesByType = utilArrayGroupBy(issues, 'type');
102073
102074               for (var issueType in issuesByType) {
102075                 var issuesOfType = issuesByType[issueType];
102076
102077                 if (issuesOfType[0].subtype) {
102078                   var issuesBySubtype = utilArrayGroupBy(issuesOfType, 'subtype');
102079
102080                   for (var issueSubtype in issuesBySubtype) {
102081                     var issuesOfSubtype = issuesBySubtype[issueSubtype];
102082                     tags[prefix + ':' + issueType + ':' + issueSubtype] = context.cleanTagValue(issuesOfSubtype.length.toString());
102083                   }
102084                 } else {
102085                   tags[prefix + ':' + issueType] = context.cleanTagValue(issuesOfType.length.toString());
102086                 }
102087               }
102088             } // add counts of warnings generated by the user's edits
102089
102090
102091             var warnings = context.validator().getIssuesBySeverity({
102092               what: 'edited',
102093               where: 'all',
102094               includeIgnored: true,
102095               includeDisabledRules: true
102096             }).warning.filter(function (issue) {
102097               return issue.type !== 'help_request';
102098             }); // exclude 'fixme' and similar - #8603
102099
102100             addIssueCounts(warnings, 'warnings'); // add counts of issues resolved by the user's edits
102101
102102             var resolvedIssues = context.validator().getResolvedIssues();
102103             addIssueCounts(resolvedIssues, 'resolved');
102104             context.changeset = context.changeset.update({
102105               tags: tags
102106             });
102107           }
102108
102109           function render(selection) {
102110             var osm = context.connection();
102111             if (!osm) return;
102112             var header = selection.selectAll('.header').data([0]);
102113             var headerTitle = header.enter().append('div').attr('class', 'header fillL');
102114             headerTitle.append('div').append('h2').call(_t.append('commit.title'));
102115             headerTitle.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
102116               dispatch.call('cancel', this);
102117             }).call(svgIcon('#iD-icon-close'));
102118             var body = selection.selectAll('.body').data([0]);
102119             body = body.enter().append('div').attr('class', 'body').merge(body); // Changeset Section
102120
102121             var changesetSection = body.selectAll('.changeset-editor').data([0]);
102122             changesetSection = changesetSection.enter().append('div').attr('class', 'modal-section changeset-editor').merge(changesetSection);
102123             changesetSection.call(changesetEditor.changesetID(context.changeset.id).tags(context.changeset.tags)); // Warnings
102124
102125             body.call(commitWarnings); // Upload Explanation
102126
102127             var saveSection = body.selectAll('.save-section').data([0]);
102128             saveSection = saveSection.enter().append('div').attr('class', 'modal-section save-section fillL').merge(saveSection);
102129             var prose = saveSection.selectAll('.commit-info').data([0]);
102130
102131             if (prose.enter().size()) {
102132               // first time, make sure to update user details in prose
102133               _userDetails = null;
102134             }
102135
102136             prose = prose.enter().append('p').attr('class', 'commit-info').call(_t.append('commit.upload_explanation')).merge(prose); // always check if this has changed, but only update prose.html()
102137             // if needed, because it can trigger a style recalculation
102138
102139             osm.userDetails(function (err, user) {
102140               if (err) return;
102141               if (_userDetails === user) return; // no change
102142
102143               _userDetails = user;
102144               var userLink = select(document.createElement('div'));
102145
102146               if (user.image_url) {
102147                 userLink.append('img').attr('src', user.image_url).attr('class', 'icon pre-text user-icon');
102148               }
102149
102150               userLink.append('a').attr('class', 'user-info').text(user.display_name).attr('href', osm.userURL(user.display_name)).attr('target', '_blank');
102151               prose.html(_t.html('commit.upload_explanation_with_user', {
102152                 user: {
102153                   html: userLink.html()
102154                 }
102155               }));
102156             }); // Request Review
102157
102158             var requestReview = saveSection.selectAll('.request-review').data([0]); // Enter
102159
102160             var requestReviewEnter = requestReview.enter().append('div').attr('class', 'request-review');
102161             var requestReviewDomId = utilUniqueDomId('commit-input-request-review');
102162             var labelEnter = requestReviewEnter.append('label').attr('for', requestReviewDomId);
102163
102164             if (!labelEnter.empty()) {
102165               labelEnter.call(uiTooltip().title(_t.html('commit.request_review_info')).placement('top'));
102166             }
102167
102168             labelEnter.append('input').attr('type', 'checkbox').attr('id', requestReviewDomId);
102169             labelEnter.append('span').call(_t.append('commit.request_review')); // Update
102170
102171             requestReview = requestReview.merge(requestReviewEnter);
102172             var requestReviewInput = requestReview.selectAll('input').property('checked', isReviewRequested(context.changeset.tags)).on('change', toggleRequestReview); // Buttons
102173
102174             var buttonSection = saveSection.selectAll('.buttons').data([0]); // enter
102175
102176             var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons fillL');
102177             buttonEnter.append('button').attr('class', 'secondary-action button cancel-button').append('span').attr('class', 'label').call(_t.append('commit.cancel'));
102178             var uploadButton = buttonEnter.append('button').attr('class', 'action button save-button');
102179             uploadButton.append('span').attr('class', 'label').call(_t.append('commit.save'));
102180             var uploadBlockerTooltipText = getUploadBlockerMessage(); // update
102181
102182             buttonSection = buttonSection.merge(buttonEnter);
102183             buttonSection.selectAll('.cancel-button').on('click.cancel', function () {
102184               dispatch.call('cancel', this);
102185             });
102186             buttonSection.selectAll('.save-button').classed('disabled', uploadBlockerTooltipText !== null).on('click.save', function () {
102187               if (!select(this).classed('disabled')) {
102188                 this.blur(); // avoid keeping focus on the button - #4641
102189
102190                 for (var key in context.changeset.tags) {
102191                   // remove any empty keys before upload
102192                   if (!key) delete context.changeset.tags[key];
102193                 }
102194
102195                 context.uploader().save(context.changeset);
102196               }
102197             }); // remove any existing tooltip
102198
102199             uiTooltip().destroyAny(buttonSection.selectAll('.save-button'));
102200
102201             if (uploadBlockerTooltipText) {
102202               buttonSection.selectAll('.save-button').call(uiTooltip().title(uploadBlockerTooltipText).placement('top'));
102203             } // Raw Tag Editor
102204
102205
102206             var tagSection = body.selectAll('.tag-section.raw-tag-editor').data([0]);
102207             tagSection = tagSection.enter().append('div').attr('class', 'modal-section tag-section raw-tag-editor').merge(tagSection);
102208             tagSection.call(rawTagEditor.tags(Object.assign({}, context.changeset.tags)) // shallow copy
102209             .render);
102210             var changesSection = body.selectAll('.commit-changes-section').data([0]);
102211             changesSection = changesSection.enter().append('div').attr('class', 'modal-section commit-changes-section').merge(changesSection); // Change summary
102212
102213             changesSection.call(commitChanges.render);
102214
102215             function toggleRequestReview() {
102216               var rr = requestReviewInput.property('checked');
102217               updateChangeset({
102218                 review_requested: rr ? 'yes' : undefined
102219               });
102220               tagSection.call(rawTagEditor.tags(Object.assign({}, context.changeset.tags)) // shallow copy
102221               .render);
102222             }
102223           }
102224
102225           function getUploadBlockerMessage() {
102226             var errors = context.validator().getIssuesBySeverity({
102227               what: 'edited',
102228               where: 'all'
102229             }).error;
102230
102231             if (errors.length) {
102232               return _t('commit.outstanding_errors_message', {
102233                 count: errors.length
102234               });
102235             } else {
102236               var hasChangesetComment = context.changeset && context.changeset.tags.comment && context.changeset.tags.comment.trim().length;
102237
102238               if (!hasChangesetComment) {
102239                 return _t('commit.comment_needed_message');
102240               }
102241             }
102242
102243             return null;
102244           }
102245
102246           function changeTags(_, changed, onInput) {
102247             if (changed.hasOwnProperty('comment')) {
102248               if (changed.comment === undefined) {
102249                 changed.comment = '';
102250               }
102251
102252               if (!onInput) {
102253                 corePreferences('comment', changed.comment);
102254                 corePreferences('commentDate', Date.now());
102255               }
102256             }
102257
102258             if (changed.hasOwnProperty('source')) {
102259               if (changed.source === undefined) {
102260                 corePreferences('source', null);
102261               } else if (!onInput) {
102262                 corePreferences('source', changed.source);
102263                 corePreferences('commentDate', Date.now());
102264               }
102265             } // no need to update `prefs` for `hashtags` here since it's done in `updateChangeset`
102266
102267
102268             updateChangeset(changed, onInput);
102269
102270             if (_selection) {
102271               _selection.call(render);
102272             }
102273           }
102274
102275           function findHashtags(tags, commentOnly) {
102276             var detectedHashtags = commentHashtags();
102277
102278             if (detectedHashtags.length) {
102279               // always remove stored hashtags if there are hashtags in the comment - #4304
102280               corePreferences('hashtags', null);
102281             }
102282
102283             if (!detectedHashtags.length || !commentOnly) {
102284               detectedHashtags = detectedHashtags.concat(hashtagHashtags());
102285             }
102286
102287             var allLowerCase = new Set();
102288             return detectedHashtags.filter(function (hashtag) {
102289               // Compare tags as lowercase strings, but keep original case tags
102290               var lowerCase = hashtag.toLowerCase();
102291
102292               if (!allLowerCase.has(lowerCase)) {
102293                 allLowerCase.add(lowerCase);
102294                 return true;
102295               }
102296
102297               return false;
102298             }); // Extract hashtags from `comment`
102299
102300             function commentHashtags() {
102301               var matches = (tags.comment || '').replace(/http\S*/g, '') // drop anything that looks like a URL - #4289
102302               .match(hashtagRegex);
102303               return matches || [];
102304             } // Extract and clean hashtags from `hashtags`
102305
102306
102307             function hashtagHashtags() {
102308               var matches = (tags.hashtags || '').split(/[,;\s]+/).map(function (s) {
102309                 if (s[0] !== '#') {
102310                   s = '#' + s;
102311                 } // prepend '#'
102312
102313
102314                 var matched = s.match(hashtagRegex);
102315                 return matched && matched[0];
102316               }).filter(Boolean); // exclude falsy
102317
102318               return matches || [];
102319             }
102320           }
102321
102322           function isReviewRequested(tags) {
102323             var rr = tags.review_requested;
102324             if (rr === undefined) return false;
102325             rr = rr.trim().toLowerCase();
102326             return !(rr === '' || rr === 'no');
102327           }
102328
102329           function updateChangeset(changed, onInput) {
102330             var tags = Object.assign({}, context.changeset.tags); // shallow copy
102331
102332             Object.keys(changed).forEach(function (k) {
102333               var v = changed[k];
102334               k = context.cleanTagKey(k);
102335               if (readOnlyTags.indexOf(k) !== -1) return;
102336
102337               if (v === undefined) {
102338                 delete tags[k];
102339               } else if (onInput) {
102340                 tags[k] = v;
102341               } else {
102342                 tags[k] = context.cleanTagValue(v);
102343               }
102344             });
102345
102346             if (!onInput) {
102347               // when changing the comment, override hashtags with any found in comment.
102348               var commentOnly = changed.hasOwnProperty('comment') && changed.comment !== '';
102349               var arr = findHashtags(tags, commentOnly);
102350
102351               if (arr.length) {
102352                 tags.hashtags = context.cleanTagValue(arr.join(';'));
102353                 corePreferences('hashtags', tags.hashtags);
102354               } else {
102355                 delete tags.hashtags;
102356                 corePreferences('hashtags', null);
102357               }
102358             } // always update userdetails, just in case user reauthenticates as someone else
102359
102360
102361             if (_userDetails && _userDetails.changesets_count !== undefined) {
102362               var changesetsCount = parseInt(_userDetails.changesets_count, 10) + 1; // #4283
102363
102364               tags.changesets_count = String(changesetsCount); // first 100 edits - new user
102365
102366               if (changesetsCount <= 100) {
102367                 var s;
102368                 s = corePreferences('walkthrough_completed');
102369
102370                 if (s) {
102371                   tags['ideditor:walkthrough_completed'] = s;
102372                 }
102373
102374                 s = corePreferences('walkthrough_progress');
102375
102376                 if (s) {
102377                   tags['ideditor:walkthrough_progress'] = s;
102378                 }
102379
102380                 s = corePreferences('walkthrough_started');
102381
102382                 if (s) {
102383                   tags['ideditor:walkthrough_started'] = s;
102384                 }
102385               }
102386             } else {
102387               delete tags.changesets_count;
102388             }
102389
102390             if (!fastDeepEqual(context.changeset.tags, tags)) {
102391               context.changeset = context.changeset.update({
102392                 tags: tags
102393               });
102394             }
102395           }
102396
102397           commit.reset = function () {
102398             context.changeset = null;
102399           };
102400
102401           return utilRebind(commit, dispatch, 'on');
102402         }
102403
102404         function uiConfirm(selection) {
102405           var modalSelection = uiModal(selection);
102406           modalSelection.select('.modal').classed('modal-alert', true);
102407           var section = modalSelection.select('.content');
102408           section.append('div').attr('class', 'modal-section header');
102409           section.append('div').attr('class', 'modal-section message-text');
102410           var buttons = section.append('div').attr('class', 'modal-section buttons cf');
102411
102412           modalSelection.okButton = function () {
102413             buttons.append('button').attr('class', 'button ok-button action').on('click.confirm', function () {
102414               modalSelection.remove();
102415             }).call(_t.append('confirm.okay')).node().focus();
102416             return modalSelection;
102417           };
102418
102419           return modalSelection;
102420         }
102421
102422         function uiConflicts(context) {
102423           var dispatch = dispatch$8('cancel', 'save');
102424           var keybinding = utilKeybinding('conflicts');
102425
102426           var _origChanges;
102427
102428           var _conflictList;
102429
102430           var _shownConflictIndex;
102431
102432           function keybindingOn() {
102433             select(document).call(keybinding.on('⎋', cancel, true));
102434           }
102435
102436           function keybindingOff() {
102437             select(document).call(keybinding.unbind);
102438           }
102439
102440           function tryAgain() {
102441             keybindingOff();
102442             dispatch.call('save');
102443           }
102444
102445           function cancel() {
102446             keybindingOff();
102447             dispatch.call('cancel');
102448           }
102449
102450           function conflicts(selection) {
102451             keybindingOn();
102452             var headerEnter = selection.selectAll('.header').data([0]).enter().append('div').attr('class', 'header fillL');
102453             headerEnter.append('button').attr('class', 'fr').attr('title', _t('icons.close')).on('click', cancel).call(svgIcon('#iD-icon-close'));
102454             headerEnter.append('h2').call(_t.append('save.conflict.header'));
102455             var bodyEnter = selection.selectAll('.body').data([0]).enter().append('div').attr('class', 'body fillL');
102456             var conflictsHelpEnter = bodyEnter.append('div').attr('class', 'conflicts-help').call(_t.append('save.conflict.help')); // Download changes link
102457
102458             var detected = utilDetect();
102459             var changeset = new osmChangeset();
102460             delete changeset.id; // Export without changeset_id
102461
102462             var data = JXON.stringify(changeset.osmChangeJXON(_origChanges));
102463             var blob = new Blob([data], {
102464               type: 'text/xml;charset=utf-8;'
102465             });
102466             var fileName = 'changes.osc';
102467             var linkEnter = conflictsHelpEnter.selectAll('.download-changes').append('a').attr('class', 'download-changes');
102468
102469             if (detected.download) {
102470               // All except IE11 and Edge
102471               linkEnter // download the data as a file
102472               .attr('href', window.URL.createObjectURL(blob)).attr('download', fileName);
102473             } else {
102474               // IE11 and Edge
102475               linkEnter // open data uri in a new tab
102476               .attr('target', '_blank').on('click.download', function () {
102477                 navigator.msSaveBlob(blob, fileName);
102478               });
102479             }
102480
102481             linkEnter.call(svgIcon('#iD-icon-load', 'inline')).append('span').call(_t.append('save.conflict.download_changes'));
102482             bodyEnter.append('div').attr('class', 'conflict-container fillL3').call(showConflict, 0);
102483             bodyEnter.append('div').attr('class', 'conflicts-done').attr('opacity', 0).style('display', 'none').call(_t.append('save.conflict.done'));
102484             var buttonsEnter = bodyEnter.append('div').attr('class', 'buttons col12 joined conflicts-buttons');
102485             buttonsEnter.append('button').attr('disabled', _conflictList.length > 1).attr('class', 'action conflicts-button col6').call(_t.append('save.title')).on('click.try_again', tryAgain);
102486             buttonsEnter.append('button').attr('class', 'secondary-action conflicts-button col6').call(_t.append('confirm.cancel')).on('click.cancel', cancel);
102487           }
102488
102489           function showConflict(selection, index) {
102490             index = utilWrap(index, _conflictList.length);
102491             _shownConflictIndex = index;
102492             var parent = select(selection.node().parentNode); // enable save button if this is the last conflict being reviewed..
102493
102494             if (index === _conflictList.length - 1) {
102495               window.setTimeout(function () {
102496                 parent.select('.conflicts-button').attr('disabled', null);
102497                 parent.select('.conflicts-done').transition().attr('opacity', 1).style('display', 'block');
102498               }, 250);
102499             }
102500
102501             var conflict = selection.selectAll('.conflict').data([_conflictList[index]]);
102502             conflict.exit().remove();
102503             var conflictEnter = conflict.enter().append('div').attr('class', 'conflict');
102504             conflictEnter.append('h4').attr('class', 'conflict-count').call(_t.append('save.conflict.count', {
102505               num: index + 1,
102506               total: _conflictList.length
102507             }));
102508             conflictEnter.append('a').attr('class', 'conflict-description').attr('href', '#').text(function (d) {
102509               return d.name;
102510             }).on('click', function (d3_event, d) {
102511               d3_event.preventDefault();
102512               zoomToEntity(d.id);
102513             });
102514             var details = conflictEnter.append('div').attr('class', 'conflict-detail-container');
102515             details.append('ul').attr('class', 'conflict-detail-list').selectAll('li').data(function (d) {
102516               return d.details || [];
102517             }).enter().append('li').attr('class', 'conflict-detail-item').html(function (d) {
102518               return d;
102519             });
102520             details.append('div').attr('class', 'conflict-choices').call(addChoices);
102521             details.append('div').attr('class', 'conflict-nav-buttons joined cf').selectAll('button').data(['previous', 'next']).enter().append('button').html(function (d) {
102522               return _t.html('save.conflict.' + d);
102523             }).attr('class', 'conflict-nav-button action col6').attr('disabled', function (d, i) {
102524               return i === 0 && index === 0 || i === 1 && index === _conflictList.length - 1 || null;
102525             }).on('click', function (d3_event, d) {
102526               d3_event.preventDefault();
102527               var container = parent.selectAll('.conflict-container');
102528               var sign = d === 'previous' ? -1 : 1;
102529               container.selectAll('.conflict').remove();
102530               container.call(showConflict, index + sign);
102531             });
102532           }
102533
102534           function addChoices(selection) {
102535             var choices = selection.append('ul').attr('class', 'layer-list').selectAll('li').data(function (d) {
102536               return d.choices || [];
102537             }); // enter
102538
102539             var choicesEnter = choices.enter().append('li').attr('class', 'layer');
102540             var labelEnter = choicesEnter.append('label');
102541             labelEnter.append('input').attr('type', 'radio').attr('name', function (d) {
102542               return d.id;
102543             }).on('change', function (d3_event, d) {
102544               var ul = this.parentNode.parentNode.parentNode;
102545               ul.__data__.chosen = d.id;
102546               choose(d3_event, ul, d);
102547             });
102548             labelEnter.append('span').text(function (d) {
102549               return d.text;
102550             }); // update
102551
102552             choicesEnter.merge(choices).each(function (d) {
102553               var ul = this.parentNode;
102554
102555               if (ul.__data__.chosen === d.id) {
102556                 choose(null, ul, d);
102557               }
102558             });
102559           }
102560
102561           function choose(d3_event, ul, datum) {
102562             if (d3_event) d3_event.preventDefault();
102563             select(ul).selectAll('li').classed('active', function (d) {
102564               return d === datum;
102565             }).selectAll('input').property('checked', function (d) {
102566               return d === datum;
102567             });
102568             var extent = geoExtent();
102569             var entity;
102570             entity = context.graph().hasEntity(datum.id);
102571             if (entity) extent._extend(entity.extent(context.graph()));
102572             datum.action();
102573             entity = context.graph().hasEntity(datum.id);
102574             if (entity) extent._extend(entity.extent(context.graph()));
102575             zoomToEntity(datum.id, extent);
102576           }
102577
102578           function zoomToEntity(id, extent) {
102579             context.surface().selectAll('.hover').classed('hover', false);
102580             var entity = context.graph().hasEntity(id);
102581
102582             if (entity) {
102583               if (extent) {
102584                 context.map().trimmedExtent(extent);
102585               } else {
102586                 context.map().zoomToEase(entity);
102587               }
102588
102589               context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph())).classed('hover', true);
102590             }
102591           } // The conflict list should be an array of objects like:
102592           // {
102593           //     id: id,
102594           //     name: entityName(local),
102595           //     details: merge.conflicts(),
102596           //     chosen: 1,
102597           //     choices: [
102598           //         choice(id, keepMine, forceLocal),
102599           //         choice(id, keepTheirs, forceRemote)
102600           //     ]
102601           // }
102602
102603
102604           conflicts.conflictList = function (_) {
102605             if (!arguments.length) return _conflictList;
102606             _conflictList = _;
102607             return conflicts;
102608           };
102609
102610           conflicts.origChanges = function (_) {
102611             if (!arguments.length) return _origChanges;
102612             _origChanges = _;
102613             return conflicts;
102614           };
102615
102616           conflicts.shownEntityIds = function () {
102617             if (_conflictList && typeof _shownConflictIndex === 'number') {
102618               return [_conflictList[_shownConflictIndex].id];
102619             }
102620
102621             return [];
102622           };
102623
102624           return utilRebind(conflicts, dispatch, 'on');
102625         }
102626
102627         function uiSectionEntityIssues(context) {
102628           // Does the user prefer to expand the active issue?  Useful for viewing tag diff.
102629           // Expand by default so first timers see it - #6408, #8143
102630           var preference = corePreferences('entity-issues.reference.expanded');
102631
102632           var _expanded = preference === null ? true : preference === 'true';
102633
102634           var _entityIDs = [];
102635           var _issues = [];
102636
102637           var _activeIssueID;
102638
102639           var section = uiSection('entity-issues', context).shouldDisplay(function () {
102640             return _issues.length > 0;
102641           }).label(function () {
102642             return _t.html('inspector.title_count', {
102643               title: {
102644                 html: _t.html('issues.list_title')
102645               },
102646               count: _issues.length
102647             });
102648           }).disclosureContent(renderDisclosureContent);
102649           context.validator().on('validated.entity_issues', function () {
102650             // Refresh on validated events
102651             reloadIssues();
102652             section.reRender();
102653           }).on('focusedIssue.entity_issues', function (issue) {
102654             makeActiveIssue(issue.id);
102655           });
102656
102657           function reloadIssues() {
102658             _issues = context.validator().getSharedEntityIssues(_entityIDs, {
102659               includeDisabledRules: true
102660             });
102661           }
102662
102663           function makeActiveIssue(issueID) {
102664             _activeIssueID = issueID;
102665             section.selection().selectAll('.issue-container').classed('active', function (d) {
102666               return d.id === _activeIssueID;
102667             });
102668           }
102669
102670           function renderDisclosureContent(selection) {
102671             selection.classed('grouped-items-area', true);
102672             _activeIssueID = _issues.length > 0 ? _issues[0].id : null;
102673             var containers = selection.selectAll('.issue-container').data(_issues, function (d) {
102674               return d.key;
102675             }); // Exit
102676
102677             containers.exit().remove(); // Enter
102678
102679             var containersEnter = containers.enter().append('div').attr('class', 'issue-container');
102680             var itemsEnter = containersEnter.append('div').attr('class', function (d) {
102681               return 'issue severity-' + d.severity;
102682             }).on('mouseover.highlight', function (d3_event, d) {
102683               // don't hover-highlight the selected entity
102684               var ids = d.entityIds.filter(function (e) {
102685                 return _entityIDs.indexOf(e) === -1;
102686               });
102687               utilHighlightEntities(ids, true, context);
102688             }).on('mouseout.highlight', function (d3_event, d) {
102689               var ids = d.entityIds.filter(function (e) {
102690                 return _entityIDs.indexOf(e) === -1;
102691               });
102692               utilHighlightEntities(ids, false, context);
102693             });
102694             var labelsEnter = itemsEnter.append('div').attr('class', 'issue-label');
102695             var textEnter = labelsEnter.append('button').attr('class', 'issue-text').on('click', function (d3_event, d) {
102696               makeActiveIssue(d.id); // expand only the clicked item
102697
102698               var extent = d.extent(context.graph());
102699
102700               if (extent) {
102701                 var setZoom = Math.max(context.map().zoom(), 19);
102702                 context.map().unobscuredCenterZoomEase(extent.center(), setZoom);
102703               }
102704             });
102705             textEnter.each(function (d) {
102706               var iconName = '#iD-icon-' + (d.severity === 'warning' ? 'alert' : 'error');
102707               select(this).call(svgIcon(iconName, 'issue-icon'));
102708             });
102709             textEnter.append('span').attr('class', 'issue-message');
102710             var infoButton = labelsEnter.append('button').attr('class', 'issue-info-button').attr('title', _t('icons.information')).call(svgIcon('#iD-icon-inspect'));
102711             infoButton.on('click', function (d3_event) {
102712               d3_event.stopPropagation();
102713               d3_event.preventDefault();
102714               this.blur(); // avoid keeping focus on the button - #4641
102715
102716               var container = select(this.parentNode.parentNode.parentNode);
102717               var info = container.selectAll('.issue-info');
102718               var isExpanded = info.classed('expanded');
102719               _expanded = !isExpanded;
102720               corePreferences('entity-issues.reference.expanded', _expanded); // update preference
102721
102722               if (isExpanded) {
102723                 info.transition().duration(200).style('max-height', '0px').style('opacity', '0').on('end', function () {
102724                   info.classed('expanded', false);
102725                 });
102726               } else {
102727                 info.classed('expanded', true).transition().duration(200).style('max-height', '200px').style('opacity', '1').on('end', function () {
102728                   info.style('max-height', null);
102729                 });
102730               }
102731             });
102732             itemsEnter.append('ul').attr('class', 'issue-fix-list');
102733             containersEnter.append('div').attr('class', 'issue-info' + (_expanded ? ' expanded' : '')).style('max-height', _expanded ? null : '0').style('opacity', _expanded ? '1' : '0').each(function (d) {
102734               if (typeof d.reference === 'function') {
102735                 select(this).call(d.reference);
102736               } else {
102737                 select(this).call(_t.append('inspector.no_documentation_key'));
102738               }
102739             }); // Update
102740
102741             containers = containers.merge(containersEnter).classed('active', function (d) {
102742               return d.id === _activeIssueID;
102743             });
102744             containers.selectAll('.issue-message').html(function (d) {
102745               return d.message(context);
102746             }); // fixes
102747
102748             var fixLists = containers.selectAll('.issue-fix-list');
102749             var fixes = fixLists.selectAll('.issue-fix-item').data(function (d) {
102750               return d.fixes ? d.fixes(context) : [];
102751             }, function (fix) {
102752               return fix.id;
102753             });
102754             fixes.exit().remove();
102755             var fixesEnter = fixes.enter().append('li').attr('class', 'issue-fix-item');
102756             var buttons = fixesEnter.append('button').on('click', function (d3_event, d) {
102757               // not all fixes are actionable
102758               if (select(this).attr('disabled') || !d.onClick) return; // Don't run another fix for this issue within a second of running one
102759               // (Necessary for "Select a feature type" fix. Most fixes should only ever run once)
102760
102761               if (d.issue.dateLastRanFix && new Date() - d.issue.dateLastRanFix < 1000) return;
102762               d.issue.dateLastRanFix = new Date(); // remove hover-highlighting
102763
102764               utilHighlightEntities(d.issue.entityIds.concat(d.entityIds), false, context);
102765               new Promise(function (resolve, reject) {
102766                 d.onClick(context, resolve, reject);
102767
102768                 if (d.onClick.length <= 1) {
102769                   // if the fix doesn't take any completion parameters then consider it resolved
102770                   resolve();
102771                 }
102772               }).then(function () {
102773                 // revalidate whenever the fix has finished running successfully
102774                 context.validator().validate();
102775               });
102776             }).on('mouseover.highlight', function (d3_event, d) {
102777               utilHighlightEntities(d.entityIds, true, context);
102778             }).on('mouseout.highlight', function (d3_event, d) {
102779               utilHighlightEntities(d.entityIds, false, context);
102780             });
102781             buttons.each(function (d) {
102782               var iconName = d.icon || 'iD-icon-wrench';
102783
102784               if (iconName.startsWith('maki')) {
102785                 iconName += '-15';
102786               }
102787
102788               select(this).call(svgIcon('#' + iconName, 'fix-icon'));
102789             });
102790             buttons.append('span').attr('class', 'fix-message').html(function (d) {
102791               return d.title;
102792             });
102793             fixesEnter.merge(fixes).selectAll('button').classed('actionable', function (d) {
102794               return d.onClick;
102795             }).attr('disabled', function (d) {
102796               return d.onClick ? null : 'true';
102797             }).attr('title', function (d) {
102798               if (d.disabledReason) {
102799                 return d.disabledReason;
102800               }
102801
102802               return null;
102803             });
102804           }
102805
102806           section.entityIDs = function (val) {
102807             if (!arguments.length) return _entityIDs;
102808
102809             if (!_entityIDs || !val || !utilArrayIdentical(_entityIDs, val)) {
102810               _entityIDs = val;
102811               _activeIssueID = null;
102812               reloadIssues();
102813             }
102814
102815             return section;
102816           };
102817
102818           return section;
102819         }
102820
102821         function uiPresetIcon() {
102822           var _preset;
102823
102824           var _geometry;
102825
102826           var _sizeClass = 'medium';
102827
102828           function isSmall() {
102829             return _sizeClass === 'small';
102830           }
102831
102832           function presetIcon(selection) {
102833             selection.each(render);
102834           }
102835
102836           function getIcon(p, geom) {
102837             if (isSmall() && p.isFallback && p.isFallback()) return 'iD-icon-' + p.id;
102838             if (p.icon) return p.icon;
102839             if (geom === 'line') return 'iD-other-line';
102840             if (geom === 'vertex') return p.isFallback() ? '' : 'temaki-vertex';
102841             if (isSmall() && geom === 'point') return '';
102842             return 'maki-marker-stroked';
102843           }
102844
102845           function renderPointBorder(container, drawPoint) {
102846             var pointBorder = container.selectAll('.preset-icon-point-border').data(drawPoint ? [0] : []);
102847             pointBorder.exit().remove();
102848             var pointBorderEnter = pointBorder.enter();
102849             var w = 40;
102850             var h = 40;
102851             pointBorderEnter.append('svg').attr('class', 'preset-icon-fill preset-icon-point-border').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h)).append('path').attr('transform', 'translate(11.5, 8)').attr('d', 'M 17,8 C 17,13 11,21 8.5,23.5 C 6,21 0,13 0,8 C 0,4 4,-0.5 8.5,-0.5 C 13,-0.5 17,4 17,8 z');
102852             pointBorder = pointBorderEnter.merge(pointBorder);
102853           }
102854
102855           function renderCategoryBorder(container, category) {
102856             var categoryBorder = container.selectAll('.preset-icon-category-border').data(category ? [0] : []);
102857             categoryBorder.exit().remove();
102858             var categoryBorderEnter = categoryBorder.enter();
102859             var d = 60;
102860             var svgEnter = categoryBorderEnter.append('svg').attr('class', 'preset-icon-fill preset-icon-category-border').attr('width', d).attr('height', d).attr('viewBox', "0 0 ".concat(d, " ").concat(d));
102861             svgEnter.append('path').attr('class', 'area').attr('d', 'M9.5,7.5 L25.5,7.5 L28.5,12.5 L49.5,12.5 C51.709139,12.5 53.5,14.290861 53.5,16.5 L53.5,43.5 C53.5,45.709139 51.709139,47.5 49.5,47.5 L10.5,47.5 C8.290861,47.5 6.5,45.709139 6.5,43.5 L6.5,12.5 L9.5,7.5 Z');
102862             categoryBorder = categoryBorderEnter.merge(categoryBorder);
102863
102864             if (category) {
102865               categoryBorder.selectAll('path').attr('class', "area ".concat(category.id));
102866             }
102867           }
102868
102869           function renderCircleFill(container, drawVertex) {
102870             var vertexFill = container.selectAll('.preset-icon-fill-vertex').data(drawVertex ? [0] : []);
102871             vertexFill.exit().remove();
102872             var vertexFillEnter = vertexFill.enter();
102873             var w = 60;
102874             var h = 60;
102875             var d = 40;
102876             vertexFillEnter.append('svg').attr('class', 'preset-icon-fill preset-icon-fill-vertex').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h)).append('circle').attr('cx', w / 2).attr('cy', h / 2).attr('r', d / 2);
102877             vertexFill = vertexFillEnter.merge(vertexFill);
102878           }
102879
102880           function renderSquareFill(container, drawArea, tagClasses) {
102881             var fill = container.selectAll('.preset-icon-fill-area').data(drawArea ? [0] : []);
102882             fill.exit().remove();
102883             var fillEnter = fill.enter();
102884             var d = isSmall() ? 40 : 60;
102885             var w = d;
102886             var h = d;
102887             var l = d * 2 / 3;
102888             var c1 = (w - l) / 2;
102889             var c2 = c1 + l;
102890             fillEnter = fillEnter.append('svg').attr('class', 'preset-icon-fill preset-icon-fill-area').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h));
102891             ['fill', 'stroke'].forEach(function (klass) {
102892               fillEnter.append('path').attr('d', "M".concat(c1, " ").concat(c1, " L").concat(c1, " ").concat(c2, " L").concat(c2, " ").concat(c2, " L").concat(c2, " ").concat(c1, " Z")).attr('class', "area ".concat(klass));
102893             });
102894             var rVertex = 2.5;
102895             [[c1, c1], [c1, c2], [c2, c2], [c2, c1]].forEach(function (point) {
102896               fillEnter.append('circle').attr('class', 'vertex').attr('cx', point[0]).attr('cy', point[1]).attr('r', rVertex);
102897             });
102898
102899             if (!isSmall()) {
102900               var rMidpoint = 1.25;
102901               [[c1, w / 2], [c2, w / 2], [h / 2, c1], [h / 2, c2]].forEach(function (point) {
102902                 fillEnter.append('circle').attr('class', 'midpoint').attr('cx', point[0]).attr('cy', point[1]).attr('r', rMidpoint);
102903               });
102904             }
102905
102906             fill = fillEnter.merge(fill);
102907             fill.selectAll('path.stroke').attr('class', "area stroke ".concat(tagClasses));
102908             fill.selectAll('path.fill').attr('class', "area fill ".concat(tagClasses));
102909           }
102910
102911           function renderLine(container, drawLine, tagClasses) {
102912             var line = container.selectAll('.preset-icon-line').data(drawLine ? [0] : []);
102913             line.exit().remove();
102914             var lineEnter = line.enter();
102915             var d = isSmall() ? 40 : 60; // draw the line parametrically
102916
102917             var w = d;
102918             var h = d;
102919             var y = Math.round(d * 0.72);
102920             var l = Math.round(d * 0.6);
102921             var r = 2.5;
102922             var x1 = (w - l) / 2;
102923             var x2 = x1 + l;
102924             lineEnter = lineEnter.append('svg').attr('class', 'preset-icon-line').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h));
102925             ['casing', 'stroke'].forEach(function (klass) {
102926               lineEnter.append('path').attr('d', "M".concat(x1, " ").concat(y, " L").concat(x2, " ").concat(y)).attr('class', "line ".concat(klass));
102927             });
102928             [[x1 - 1, y], [x2 + 1, y]].forEach(function (point) {
102929               lineEnter.append('circle').attr('class', 'vertex').attr('cx', point[0]).attr('cy', point[1]).attr('r', r);
102930             });
102931             line = lineEnter.merge(line);
102932             line.selectAll('path.stroke').attr('class', "line stroke ".concat(tagClasses));
102933             line.selectAll('path.casing').attr('class', "line casing ".concat(tagClasses));
102934           }
102935
102936           function renderRoute(container, drawRoute, p) {
102937             var route = container.selectAll('.preset-icon-route').data(drawRoute ? [0] : []);
102938             route.exit().remove();
102939             var routeEnter = route.enter();
102940             var d = isSmall() ? 40 : 60; // draw the route parametrically
102941
102942             var w = d;
102943             var h = d;
102944             var y1 = Math.round(d * 0.80);
102945             var y2 = Math.round(d * 0.68);
102946             var l = Math.round(d * 0.6);
102947             var r = 2;
102948             var x1 = (w - l) / 2;
102949             var x2 = x1 + l / 3;
102950             var x3 = x2 + l / 3;
102951             var x4 = x3 + l / 3;
102952             routeEnter = routeEnter.append('svg').attr('class', 'preset-icon-route').attr('width', w).attr('height', h).attr('viewBox', "0 0 ".concat(w, " ").concat(h));
102953             ['casing', 'stroke'].forEach(function (klass) {
102954               routeEnter.append('path').attr('d', "M".concat(x1, " ").concat(y1, " L").concat(x2, " ").concat(y2)).attr('class', "segment0 line ".concat(klass));
102955               routeEnter.append('path').attr('d', "M".concat(x2, " ").concat(y2, " L").concat(x3, " ").concat(y1)).attr('class', "segment1 line ".concat(klass));
102956               routeEnter.append('path').attr('d', "M".concat(x3, " ").concat(y1, " L").concat(x4, " ").concat(y2)).attr('class', "segment2 line ".concat(klass));
102957             });
102958             [[x1, y1], [x2, y2], [x3, y1], [x4, y2]].forEach(function (point) {
102959               routeEnter.append('circle').attr('class', 'vertex').attr('cx', point[0]).attr('cy', point[1]).attr('r', r);
102960             });
102961             route = routeEnter.merge(route);
102962
102963             if (drawRoute) {
102964               var routeType = p.tags.type === 'waterway' ? 'waterway' : p.tags.route;
102965               var segmentPresetIDs = routeSegments[routeType];
102966
102967               for (var i in segmentPresetIDs) {
102968                 var segmentPreset = _mainPresetIndex.item(segmentPresetIDs[i]);
102969                 var segmentTagClasses = svgTagClasses().getClassesString(segmentPreset.tags, '');
102970                 route.selectAll("path.stroke.segment".concat(i)).attr('class', "segment".concat(i, " line stroke ").concat(segmentTagClasses));
102971                 route.selectAll("path.casing.segment".concat(i)).attr('class', "segment".concat(i, " line casing ").concat(segmentTagClasses));
102972               }
102973             }
102974           }
102975
102976           function renderSvgIcon(container, picon, geom, isFramed, category, tagClasses) {
102977             var isMaki = picon && /^maki-/.test(picon);
102978             var isTemaki = picon && /^temaki-/.test(picon);
102979             var isFa = picon && /^fa[srb]-/.test(picon);
102980             var isiDIcon = picon && !(isMaki || isTemaki || isFa);
102981             var icon = container.selectAll('.preset-icon').data(picon ? [0] : []);
102982             icon.exit().remove();
102983             icon = icon.enter().append('div').attr('class', 'preset-icon').call(svgIcon('')).merge(icon);
102984             icon.attr('class', 'preset-icon ' + (geom ? geom + '-geom' : '')).classed('category', category).classed('framed', isFramed).classed('preset-icon-iD', isiDIcon);
102985             icon.selectAll('svg').attr('class', 'icon ' + picon + ' ' + (!isiDIcon && geom !== 'line' ? '' : tagClasses));
102986             var suffix = '';
102987
102988             if (isMaki) {
102989               suffix = isSmall() && geom === 'point' ? '-11' : '-15';
102990             }
102991
102992             icon.selectAll('use').attr('href', '#' + picon + suffix);
102993           }
102994
102995           function renderImageIcon(container, imageURL) {
102996             var imageIcon = container.selectAll('img.image-icon').data(imageURL ? [0] : []);
102997             imageIcon.exit().remove();
102998             imageIcon = imageIcon.enter().append('img').attr('class', 'image-icon').on('load', function () {
102999               return container.classed('showing-img', true);
103000             }).on('error', function () {
103001               return container.classed('showing-img', false);
103002             }).merge(imageIcon);
103003             imageIcon.attr('src', imageURL);
103004           } // Route icons are drawn with a zigzag annotation underneath:
103005           //     o   o
103006           //    / \ /
103007           //   o   o
103008           // This dataset defines the styles that are used to draw the zigzag segments.
103009
103010
103011           var routeSegments = {
103012             bicycle: ['highway/cycleway', 'highway/cycleway', 'highway/cycleway'],
103013             bus: ['highway/unclassified', 'highway/secondary', 'highway/primary'],
103014             trolleybus: ['highway/unclassified', 'highway/secondary', 'highway/primary'],
103015             detour: ['highway/tertiary', 'highway/residential', 'highway/unclassified'],
103016             ferry: ['route/ferry', 'route/ferry', 'route/ferry'],
103017             foot: ['highway/footway', 'highway/footway', 'highway/footway'],
103018             hiking: ['highway/path', 'highway/path', 'highway/path'],
103019             horse: ['highway/bridleway', 'highway/bridleway', 'highway/bridleway'],
103020             light_rail: ['railway/light_rail', 'railway/light_rail', 'railway/light_rail'],
103021             monorail: ['railway/monorail', 'railway/monorail', 'railway/monorail'],
103022             mtb: ['highway/path', 'highway/track', 'highway/bridleway'],
103023             pipeline: ['man_made/pipeline', 'man_made/pipeline', 'man_made/pipeline'],
103024             piste: ['piste/downhill', 'piste/hike', 'piste/nordic'],
103025             power: ['power/line', 'power/line', 'power/line'],
103026             road: ['highway/secondary', 'highway/primary', 'highway/trunk'],
103027             subway: ['railway/subway', 'railway/subway', 'railway/subway'],
103028             train: ['railway/rail', 'railway/rail', 'railway/rail'],
103029             tram: ['railway/tram', 'railway/tram', 'railway/tram'],
103030             waterway: ['waterway/stream', 'waterway/stream', 'waterway/stream']
103031           };
103032
103033           function render() {
103034             var p = _preset.apply(this, arguments);
103035
103036             var geom = _geometry ? _geometry.apply(this, arguments) : null;
103037
103038             if (geom === 'relation' && p.tags && (p.tags.type === 'route' && p.tags.route && routeSegments[p.tags.route] || p.tags.type === 'waterway')) {
103039               geom = 'route';
103040             }
103041
103042             var showThirdPartyIcons = corePreferences('preferences.privacy.thirdpartyicons') || 'true';
103043             var isFallback = isSmall() && p.isFallback && p.isFallback();
103044             var imageURL = showThirdPartyIcons === 'true' && p.imageURL;
103045             var picon = getIcon(p, geom);
103046             var isCategory = !p.setTags;
103047             var drawPoint = picon && geom === 'point' && isSmall() && !isFallback;
103048             var drawVertex = picon !== null && geom === 'vertex' && (!isSmall() || !isFallback);
103049             var drawLine = picon && geom === 'line' && !isFallback && !isCategory;
103050             var drawArea = picon && geom === 'area' && !isFallback && !isCategory;
103051             var drawRoute = picon && geom === 'route';
103052             var isFramed = drawVertex || drawArea || drawLine || drawRoute || isCategory;
103053             var tags = !isCategory ? p.setTags({}, geom) : {};
103054
103055             for (var k in tags) {
103056               if (tags[k] === '*') {
103057                 tags[k] = 'yes';
103058               }
103059             }
103060
103061             var tagClasses = svgTagClasses().getClassesString(tags, '');
103062             var selection = select(this);
103063             var container = selection.selectAll('.preset-icon-container').data([0]);
103064             container = container.enter().append('div').attr('class', "preset-icon-container ".concat(_sizeClass)).merge(container);
103065             container.classed('showing-img', !!imageURL).classed('fallback', isFallback);
103066             renderCategoryBorder(container, isCategory && p);
103067             renderPointBorder(container, drawPoint);
103068             renderCircleFill(container, drawVertex);
103069             renderSquareFill(container, drawArea, tagClasses);
103070             renderLine(container, drawLine, tagClasses);
103071             renderRoute(container, drawRoute, p);
103072             renderSvgIcon(container, picon, geom, isFramed, isCategory, tagClasses);
103073             renderImageIcon(container, imageURL);
103074           }
103075
103076           presetIcon.preset = function (val) {
103077             if (!arguments.length) return _preset;
103078             _preset = utilFunctor(val);
103079             return presetIcon;
103080           };
103081
103082           presetIcon.geometry = function (val) {
103083             if (!arguments.length) return _geometry;
103084             _geometry = utilFunctor(val);
103085             return presetIcon;
103086           };
103087
103088           presetIcon.sizeClass = function (val) {
103089             if (!arguments.length) return _sizeClass;
103090             _sizeClass = val;
103091             return presetIcon;
103092           };
103093
103094           return presetIcon;
103095         }
103096
103097         function uiSectionFeatureType(context) {
103098           var dispatch = dispatch$8('choose');
103099           var _entityIDs = [];
103100           var _presets = [];
103101
103102           var _tagReference;
103103
103104           var section = uiSection('feature-type', context).label(_t.html('inspector.feature_type')).disclosureContent(renderDisclosureContent);
103105
103106           function renderDisclosureContent(selection) {
103107             selection.classed('preset-list-item', true);
103108             selection.classed('mixed-types', _presets.length > 1);
103109             var presetButtonWrap = selection.selectAll('.preset-list-button-wrap').data([0]).enter().append('div').attr('class', 'preset-list-button-wrap');
103110             var presetButton = presetButtonWrap.append('button').attr('class', 'preset-list-button preset-reset').call(uiTooltip().title(_t.html('inspector.back_tooltip')).placement('bottom'));
103111             presetButton.append('div').attr('class', 'preset-icon-container');
103112             presetButton.append('div').attr('class', 'label').append('div').attr('class', 'label-inner');
103113             presetButtonWrap.append('div').attr('class', 'accessory-buttons');
103114             var tagReferenceBodyWrap = selection.selectAll('.tag-reference-body-wrap').data([0]);
103115             tagReferenceBodyWrap = tagReferenceBodyWrap.enter().append('div').attr('class', 'tag-reference-body-wrap').merge(tagReferenceBodyWrap); // update header
103116
103117             if (_tagReference) {
103118               selection.selectAll('.preset-list-button-wrap .accessory-buttons').style('display', _presets.length === 1 ? null : 'none').call(_tagReference.button);
103119               tagReferenceBodyWrap.style('display', _presets.length === 1 ? null : 'none').call(_tagReference.body);
103120             }
103121
103122             selection.selectAll('.preset-reset').on('click', function () {
103123               dispatch.call('choose', this, _presets);
103124             }).on('pointerdown pointerup mousedown mouseup', function (d3_event) {
103125               d3_event.preventDefault();
103126               d3_event.stopPropagation();
103127             });
103128             var geometries = entityGeometries();
103129             selection.select('.preset-list-item button').call(uiPresetIcon().geometry(_presets.length === 1 ? geometries.length === 1 && geometries[0] : null).preset(_presets.length === 1 ? _presets[0] : _mainPresetIndex.item('point')));
103130             var names = _presets.length === 1 ? [_presets[0].nameLabel(), _presets[0].subtitleLabel()].filter(Boolean) : [_t('inspector.multiple_types')];
103131             var label = selection.select('.label-inner');
103132             var nameparts = label.selectAll('.namepart').data(names, function (d) {
103133               return d;
103134             });
103135             nameparts.exit().remove();
103136             nameparts.enter().append('div').attr('class', 'namepart').html(function (d) {
103137               return d;
103138             });
103139           }
103140
103141           section.entityIDs = function (val) {
103142             if (!arguments.length) return _entityIDs;
103143             _entityIDs = val;
103144             return section;
103145           };
103146
103147           section.presets = function (val) {
103148             if (!arguments.length) return _presets; // don't reload the same preset
103149
103150             if (!utilArrayIdentical(val, _presets)) {
103151               _presets = val;
103152
103153               if (_presets.length === 1) {
103154                 _tagReference = uiTagReference(_presets[0].reference()).showing(false);
103155               }
103156             }
103157
103158             return section;
103159           };
103160
103161           function entityGeometries() {
103162             var counts = {};
103163
103164             for (var i in _entityIDs) {
103165               var geometry = context.graph().geometry(_entityIDs[i]);
103166               if (!counts[geometry]) counts[geometry] = 0;
103167               counts[geometry] += 1;
103168             }
103169
103170             return Object.keys(counts).sort(function (geom1, geom2) {
103171               return counts[geom2] - counts[geom1];
103172             });
103173           }
103174
103175           return utilRebind(section, dispatch, 'on');
103176         }
103177
103178         function uiSectionPresetFields(context) {
103179           var section = uiSection('preset-fields', context).label(_t.html('inspector.fields')).disclosureContent(renderDisclosureContent);
103180           var dispatch = dispatch$8('change', 'revert');
103181           var formFields = uiFormFields(context);
103182
103183           var _state;
103184
103185           var _fieldsArr;
103186
103187           var _presets = [];
103188
103189           var _tags;
103190
103191           var _entityIDs;
103192
103193           function renderDisclosureContent(selection) {
103194             if (!_fieldsArr) {
103195               var graph = context.graph();
103196               var geometries = Object.keys(_entityIDs.reduce(function (geoms, entityID) {
103197                 geoms[graph.entity(entityID).geometry(graph)] = true;
103198                 return geoms;
103199               }, {}));
103200               var presetsManager = _mainPresetIndex;
103201               var allFields = [];
103202               var allMoreFields = [];
103203               var sharedTotalFields;
103204
103205               _presets.forEach(function (preset) {
103206                 var fields = preset.fields();
103207                 var moreFields = preset.moreFields();
103208                 allFields = utilArrayUnion(allFields, fields);
103209                 allMoreFields = utilArrayUnion(allMoreFields, moreFields);
103210
103211                 if (!sharedTotalFields) {
103212                   sharedTotalFields = utilArrayUnion(fields, moreFields);
103213                 } else {
103214                   sharedTotalFields = sharedTotalFields.filter(function (field) {
103215                     return fields.indexOf(field) !== -1 || moreFields.indexOf(field) !== -1;
103216                   });
103217                 }
103218               });
103219
103220               var sharedFields = allFields.filter(function (field) {
103221                 return sharedTotalFields.indexOf(field) !== -1;
103222               });
103223               var sharedMoreFields = allMoreFields.filter(function (field) {
103224                 return sharedTotalFields.indexOf(field) !== -1;
103225               });
103226               _fieldsArr = [];
103227               sharedFields.forEach(function (field) {
103228                 if (field.matchAllGeometry(geometries)) {
103229                   _fieldsArr.push(uiField(context, field, _entityIDs));
103230                 }
103231               });
103232               var singularEntity = _entityIDs.length === 1 && graph.hasEntity(_entityIDs[0]);
103233
103234               if (singularEntity && singularEntity.isHighwayIntersection(graph) && presetsManager.field('restrictions')) {
103235                 _fieldsArr.push(uiField(context, presetsManager.field('restrictions'), _entityIDs));
103236               }
103237
103238               var additionalFields = utilArrayUnion(sharedMoreFields, presetsManager.universal());
103239               additionalFields.sort(function (field1, field2) {
103240                 return field1.label().localeCompare(field2.label(), _mainLocalizer.localeCode());
103241               });
103242               additionalFields.forEach(function (field) {
103243                 if (sharedFields.indexOf(field) === -1 && field.matchAllGeometry(geometries)) {
103244                   _fieldsArr.push(uiField(context, field, _entityIDs, {
103245                     show: false
103246                   }));
103247                 }
103248               });
103249
103250               _fieldsArr.forEach(function (field) {
103251                 field.on('change', function (t, onInput) {
103252                   dispatch.call('change', field, _entityIDs, t, onInput);
103253                 }).on('revert', function (keys) {
103254                   dispatch.call('revert', field, keys);
103255                 });
103256               });
103257             }
103258
103259             _fieldsArr.forEach(function (field) {
103260               field.state(_state).tags(_tags);
103261             });
103262
103263             selection.call(formFields.fieldsArr(_fieldsArr).state(_state).klass('grouped-items-area'));
103264             selection.selectAll('.wrap-form-field input').on('keydown', function (d3_event) {
103265               // if user presses enter, and combobox is not active, accept edits..
103266               if (d3_event.keyCode === 13 && // ↩ Return
103267               context.container().select('.combobox').empty()) {
103268                 context.enter(modeBrowse(context));
103269               }
103270             });
103271           }
103272
103273           section.presets = function (val) {
103274             if (!arguments.length) return _presets;
103275
103276             if (!_presets || !val || !utilArrayIdentical(_presets, val)) {
103277               _presets = val;
103278               _fieldsArr = null;
103279             }
103280
103281             return section;
103282           };
103283
103284           section.state = function (val) {
103285             if (!arguments.length) return _state;
103286             _state = val;
103287             return section;
103288           };
103289
103290           section.tags = function (val) {
103291             if (!arguments.length) return _tags;
103292             _tags = val; // Don't reset _fieldsArr here.
103293
103294             return section;
103295           };
103296
103297           section.entityIDs = function (val) {
103298             if (!arguments.length) return _entityIDs;
103299
103300             if (!val || !_entityIDs || !utilArrayIdentical(_entityIDs, val)) {
103301               _entityIDs = val;
103302               _fieldsArr = null;
103303             }
103304
103305             return section;
103306           };
103307
103308           return utilRebind(section, dispatch, 'on');
103309         }
103310
103311         function uiSectionRawMemberEditor(context) {
103312           var section = uiSection('raw-member-editor', context).shouldDisplay(function () {
103313             if (!_entityIDs || _entityIDs.length !== 1) return false;
103314             var entity = context.hasEntity(_entityIDs[0]);
103315             return entity && entity.type === 'relation';
103316           }).label(function () {
103317             var entity = context.hasEntity(_entityIDs[0]);
103318             if (!entity) return '';
103319             var gt = entity.members.length > _maxMembers ? '>' : '';
103320             var count = gt + entity.members.slice(0, _maxMembers).length;
103321             return _t.html('inspector.title_count', {
103322               title: {
103323                 html: _t.html('inspector.members')
103324               },
103325               count: count
103326             });
103327           }).disclosureContent(renderDisclosureContent);
103328           var taginfo = services.taginfo;
103329
103330           var _entityIDs;
103331
103332           var _maxMembers = 1000;
103333
103334           function downloadMember(d3_event, d) {
103335             d3_event.preventDefault(); // display the loading indicator
103336
103337             select(this.parentNode).classed('tag-reference-loading', true);
103338             context.loadEntity(d.id, function () {
103339               section.reRender();
103340             });
103341           }
103342
103343           function zoomToMember(d3_event, d) {
103344             d3_event.preventDefault();
103345             var entity = context.entity(d.id);
103346             context.map().zoomToEase(entity); // highlight the feature in case it wasn't previously on-screen
103347
103348             utilHighlightEntities([d.id], true, context);
103349           }
103350
103351           function selectMember(d3_event, d) {
103352             d3_event.preventDefault(); // remove the hover-highlight styling
103353
103354             utilHighlightEntities([d.id], false, context);
103355             var entity = context.entity(d.id);
103356             var mapExtent = context.map().extent();
103357
103358             if (!entity.intersects(mapExtent, context.graph())) {
103359               // zoom to the entity if its extent is not visible now
103360               context.map().zoomToEase(entity);
103361             }
103362
103363             context.enter(modeSelect(context, [d.id]));
103364           }
103365
103366           function changeRole(d3_event, d) {
103367             var oldRole = d.role;
103368             var newRole = context.cleanRelationRole(select(this).property('value'));
103369
103370             if (oldRole !== newRole) {
103371               var member = {
103372                 id: d.id,
103373                 type: d.type,
103374                 role: newRole
103375               };
103376               context.perform(actionChangeMember(d.relation.id, member, d.index), _t('operations.change_role.annotation', {
103377                 n: 1
103378               }));
103379               context.validator().validate();
103380             }
103381           }
103382
103383           function deleteMember(d3_event, d) {
103384             // remove the hover-highlight styling
103385             utilHighlightEntities([d.id], false, context);
103386             context.perform(actionDeleteMember(d.relation.id, d.index), _t('operations.delete_member.annotation', {
103387               n: 1
103388             }));
103389
103390             if (!context.hasEntity(d.relation.id)) {
103391               // Removing the last member will also delete the relation.
103392               // If this happens we need to exit the selection mode
103393               context.enter(modeBrowse(context));
103394             } else {
103395               // Changing the mode also runs `validate`, but otherwise we need to
103396               // rerun it manually
103397               context.validator().validate();
103398             }
103399           }
103400
103401           function renderDisclosureContent(selection) {
103402             var entityID = _entityIDs[0];
103403             var memberships = [];
103404             var entity = context.entity(entityID);
103405             entity.members.slice(0, _maxMembers).forEach(function (member, index) {
103406               memberships.push({
103407                 index: index,
103408                 id: member.id,
103409                 type: member.type,
103410                 role: member.role,
103411                 relation: entity,
103412                 member: context.hasEntity(member.id),
103413                 domId: utilUniqueDomId(entityID + '-member-' + index)
103414               });
103415             });
103416             var list = selection.selectAll('.member-list').data([0]);
103417             list = list.enter().append('ul').attr('class', 'member-list').merge(list);
103418             var items = list.selectAll('li').data(memberships, function (d) {
103419               return osmEntity.key(d.relation) + ',' + d.index + ',' + (d.member ? osmEntity.key(d.member) : 'incomplete');
103420             });
103421             items.exit().each(unbind).remove();
103422             var itemsEnter = items.enter().append('li').attr('class', 'member-row form-field').classed('member-incomplete', function (d) {
103423               return !d.member;
103424             });
103425             itemsEnter.each(function (d) {
103426               var item = select(this);
103427               var label = item.append('label').attr('class', 'field-label').attr('for', d.domId);
103428
103429               if (d.member) {
103430                 // highlight the member feature in the map while hovering on the list item
103431                 item.on('mouseover', function () {
103432                   utilHighlightEntities([d.id], true, context);
103433                 }).on('mouseout', function () {
103434                   utilHighlightEntities([d.id], false, context);
103435                 });
103436                 var labelLink = label.append('span').attr('class', 'label-text').append('a').attr('href', '#').on('click', selectMember);
103437                 labelLink.append('span').attr('class', 'member-entity-type').text(function (d) {
103438                   var matched = _mainPresetIndex.match(d.member, context.graph());
103439                   return matched && matched.name() || utilDisplayType(d.member.id);
103440                 });
103441                 labelLink.append('span').attr('class', 'member-entity-name').text(function (d) {
103442                   return utilDisplayName(d.member);
103443                 });
103444                 label.append('button').attr('title', _t('icons.remove')).attr('class', 'remove member-delete').call(svgIcon('#iD-operation-delete'));
103445                 label.append('button').attr('class', 'member-zoom').attr('title', _t('icons.zoom_to')).call(svgIcon('#iD-icon-framed-dot', 'monochrome')).on('click', zoomToMember);
103446               } else {
103447                 var labelText = label.append('span').attr('class', 'label-text');
103448                 labelText.append('span').attr('class', 'member-entity-type').call(_t.append('inspector.' + d.type, {
103449                   id: d.id
103450                 }));
103451                 labelText.append('span').attr('class', 'member-entity-name').call(_t.append('inspector.incomplete', {
103452                   id: d.id
103453                 }));
103454                 label.append('button').attr('class', 'member-download').attr('title', _t('icons.download')).call(svgIcon('#iD-icon-load')).on('click', downloadMember);
103455               }
103456             });
103457             var wrapEnter = itemsEnter.append('div').attr('class', 'form-field-input-wrap form-field-input-member');
103458             wrapEnter.append('input').attr('class', 'member-role').attr('id', function (d) {
103459               return d.domId;
103460             }).property('type', 'text').attr('placeholder', _t('inspector.role')).call(utilNoAuto);
103461
103462             if (taginfo) {
103463               wrapEnter.each(bindTypeahead);
103464             } // update
103465
103466
103467             items = items.merge(itemsEnter).order();
103468             items.select('input.member-role').property('value', function (d) {
103469               return d.role;
103470             }).on('blur', changeRole).on('change', changeRole);
103471             items.select('button.member-delete').on('click', deleteMember);
103472             var dragOrigin, targetIndex;
103473             items.call(d3_drag().on('start', function (d3_event) {
103474               dragOrigin = {
103475                 x: d3_event.x,
103476                 y: d3_event.y
103477               };
103478               targetIndex = null;
103479             }).on('drag', function (d3_event) {
103480               var x = d3_event.x - dragOrigin.x,
103481                   y = d3_event.y - dragOrigin.y;
103482               if (!select(this).classed('dragging') && // don't display drag until dragging beyond a distance threshold
103483               Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)) <= 5) return;
103484               var index = items.nodes().indexOf(this);
103485               select(this).classed('dragging', true);
103486               targetIndex = null;
103487               selection.selectAll('li.member-row').style('transform', function (d2, index2) {
103488                 var node = select(this).node();
103489
103490                 if (index === index2) {
103491                   return 'translate(' + x + 'px, ' + y + 'px)';
103492                 } else if (index2 > index && d3_event.y > node.offsetTop) {
103493                   if (targetIndex === null || index2 > targetIndex) {
103494                     targetIndex = index2;
103495                   }
103496
103497                   return 'translateY(-100%)';
103498                 } else if (index2 < index && d3_event.y < node.offsetTop + node.offsetHeight) {
103499                   if (targetIndex === null || index2 < targetIndex) {
103500                     targetIndex = index2;
103501                   }
103502
103503                   return 'translateY(100%)';
103504                 }
103505
103506                 return null;
103507               });
103508             }).on('end', function (d3_event, d) {
103509               if (!select(this).classed('dragging')) return;
103510               var index = items.nodes().indexOf(this);
103511               select(this).classed('dragging', false);
103512               selection.selectAll('li.member-row').style('transform', null);
103513
103514               if (targetIndex !== null) {
103515                 // dragged to a new position, reorder
103516                 context.perform(actionMoveMember(d.relation.id, index, targetIndex), _t('operations.reorder_members.annotation'));
103517                 context.validator().validate();
103518               }
103519             }));
103520
103521             function bindTypeahead(d) {
103522               var row = select(this);
103523               var role = row.selectAll('input.member-role');
103524               var origValue = role.property('value');
103525
103526               function sort(value, data) {
103527                 var sameletter = [];
103528                 var other = [];
103529
103530                 for (var i = 0; i < data.length; i++) {
103531                   if (data[i].value.substring(0, value.length) === value) {
103532                     sameletter.push(data[i]);
103533                   } else {
103534                     other.push(data[i]);
103535                   }
103536                 }
103537
103538                 return sameletter.concat(other);
103539               }
103540
103541               role.call(uiCombobox(context, 'member-role').fetcher(function (role, callback) {
103542                 // The `geometry` param is used in the `taginfo.js` interface for
103543                 // filtering results, as a key into the `tag_members_fractions`
103544                 // object.  If we don't know the geometry because the member is
103545                 // not yet downloaded, it's ok to guess based on type.
103546                 var geometry;
103547
103548                 if (d.member) {
103549                   geometry = context.graph().geometry(d.member.id);
103550                 } else if (d.type === 'relation') {
103551                   geometry = 'relation';
103552                 } else if (d.type === 'way') {
103553                   geometry = 'line';
103554                 } else {
103555                   geometry = 'point';
103556                 }
103557
103558                 var rtype = entity.tags.type;
103559                 taginfo.roles({
103560                   debounce: true,
103561                   rtype: rtype || '',
103562                   geometry: geometry,
103563                   query: role
103564                 }, function (err, data) {
103565                   if (!err) callback(sort(role, data));
103566                 });
103567               }).on('cancel', function () {
103568                 role.property('value', origValue);
103569               }));
103570             }
103571
103572             function unbind() {
103573               var row = select(this);
103574               row.selectAll('input.member-role').call(uiCombobox.off, context);
103575             }
103576           }
103577
103578           section.entityIDs = function (val) {
103579             if (!arguments.length) return _entityIDs;
103580             _entityIDs = val;
103581             return section;
103582           };
103583
103584           return section;
103585         }
103586
103587         function actionDeleteMembers(relationId, memberIndexes) {
103588           return function (graph) {
103589             // Remove the members in descending order so removals won't shift what members
103590             // are at the remaining indexes
103591             memberIndexes.sort(function (a, b) {
103592               return b - a;
103593             });
103594
103595             for (var i in memberIndexes) {
103596               graph = actionDeleteMember(relationId, memberIndexes[i])(graph);
103597             }
103598
103599             return graph;
103600           };
103601         }
103602
103603         function uiSectionRawMembershipEditor(context) {
103604           var section = uiSection('raw-membership-editor', context).shouldDisplay(function () {
103605             return _entityIDs && _entityIDs.length;
103606           }).label(function () {
103607             var parents = getSharedParentRelations();
103608             var gt = parents.length > _maxMemberships ? '>' : '';
103609             var count = gt + parents.slice(0, _maxMemberships).length;
103610             return _t.html('inspector.title_count', {
103611               title: {
103612                 html: _t.html('inspector.relations')
103613               },
103614               count: count
103615             });
103616           }).disclosureContent(renderDisclosureContent);
103617           var taginfo = services.taginfo;
103618           var nearbyCombo = uiCombobox(context, 'parent-relation').minItems(1).fetcher(fetchNearbyRelations).itemsMouseEnter(function (d3_event, d) {
103619             if (d.relation) utilHighlightEntities([d.relation.id], true, context);
103620           }).itemsMouseLeave(function (d3_event, d) {
103621             if (d.relation) utilHighlightEntities([d.relation.id], false, context);
103622           });
103623           var _inChange = false;
103624           var _entityIDs = [];
103625
103626           var _showBlank;
103627
103628           var _maxMemberships = 1000;
103629
103630           function getSharedParentRelations() {
103631             var parents = [];
103632
103633             for (var i = 0; i < _entityIDs.length; i++) {
103634               var entity = context.graph().hasEntity(_entityIDs[i]);
103635               if (!entity) continue;
103636
103637               if (i === 0) {
103638                 parents = context.graph().parentRelations(entity);
103639               } else {
103640                 parents = utilArrayIntersection(parents, context.graph().parentRelations(entity));
103641               }
103642
103643               if (!parents.length) break;
103644             }
103645
103646             return parents;
103647           }
103648
103649           function getMemberships() {
103650             var memberships = [];
103651             var relations = getSharedParentRelations().slice(0, _maxMemberships);
103652             var isMultiselect = _entityIDs.length > 1;
103653             var i, relation, membership, index, member, indexedMember;
103654
103655             for (i = 0; i < relations.length; i++) {
103656               relation = relations[i];
103657               membership = {
103658                 relation: relation,
103659                 members: [],
103660                 hash: osmEntity.key(relation)
103661               };
103662
103663               for (index = 0; index < relation.members.length; index++) {
103664                 member = relation.members[index];
103665
103666                 if (_entityIDs.indexOf(member.id) !== -1) {
103667                   indexedMember = Object.assign({}, member, {
103668                     index: index
103669                   });
103670                   membership.members.push(indexedMember);
103671                   membership.hash += ',' + index.toString();
103672
103673                   if (!isMultiselect) {
103674                     // For single selections, list one entry per membership per relation.
103675                     // For multiselections, list one entry per relation.
103676                     memberships.push(membership);
103677                     membership = {
103678                       relation: relation,
103679                       members: [],
103680                       hash: osmEntity.key(relation)
103681                     };
103682                   }
103683                 }
103684               }
103685
103686               if (membership.members.length) memberships.push(membership);
103687             }
103688
103689             memberships.forEach(function (membership) {
103690               membership.domId = utilUniqueDomId('membership-' + membership.relation.id);
103691               var roles = [];
103692               membership.members.forEach(function (member) {
103693                 if (roles.indexOf(member.role) === -1) roles.push(member.role);
103694               });
103695               membership.role = roles.length === 1 ? roles[0] : roles;
103696             });
103697             return memberships;
103698           }
103699
103700           function selectRelation(d3_event, d) {
103701             d3_event.preventDefault(); // remove the hover-highlight styling
103702
103703             utilHighlightEntities([d.relation.id], false, context);
103704             context.enter(modeSelect(context, [d.relation.id]));
103705           }
103706
103707           function zoomToRelation(d3_event, d) {
103708             d3_event.preventDefault();
103709             var entity = context.entity(d.relation.id);
103710             context.map().zoomToEase(entity); // highlight the relation in case it wasn't previously on-screen
103711
103712             utilHighlightEntities([d.relation.id], true, context);
103713           }
103714
103715           function changeRole(d3_event, d) {
103716             if (d === 0) return; // called on newrow (shouldn't happen)
103717
103718             if (_inChange) return; // avoid accidental recursive call #5731
103719
103720             var newRole = context.cleanRelationRole(select(this).property('value'));
103721             if (!newRole.trim() && typeof d.role !== 'string') return;
103722             var membersToUpdate = d.members.filter(function (member) {
103723               return member.role !== newRole;
103724             });
103725
103726             if (membersToUpdate.length) {
103727               _inChange = true;
103728               context.perform(function actionChangeMemberRoles(graph) {
103729                 membersToUpdate.forEach(function (member) {
103730                   var newMember = Object.assign({}, member, {
103731                     role: newRole
103732                   });
103733                   delete newMember.index;
103734                   graph = actionChangeMember(d.relation.id, newMember, member.index)(graph);
103735                 });
103736                 return graph;
103737               }, _t('operations.change_role.annotation', {
103738                 n: membersToUpdate.length
103739               }));
103740               context.validator().validate();
103741             }
103742
103743             _inChange = false;
103744           }
103745
103746           function addMembership(d, role) {
103747             this.blur(); // avoid keeping focus on the button
103748
103749             _showBlank = false;
103750
103751             function actionAddMembers(relationId, ids, role) {
103752               return function (graph) {
103753                 for (var i in ids) {
103754                   var member = {
103755                     id: ids[i],
103756                     type: graph.entity(ids[i]).type,
103757                     role: role
103758                   };
103759                   graph = actionAddMember(relationId, member)(graph);
103760                 }
103761
103762                 return graph;
103763               };
103764             }
103765
103766             if (d.relation) {
103767               context.perform(actionAddMembers(d.relation.id, _entityIDs, role), _t('operations.add_member.annotation', {
103768                 n: _entityIDs.length
103769               }));
103770               context.validator().validate();
103771             } else {
103772               var relation = osmRelation();
103773               context.perform(actionAddEntity(relation), actionAddMembers(relation.id, _entityIDs, role), _t('operations.add.annotation.relation')); // changing the mode also runs `validate`
103774
103775               context.enter(modeSelect(context, [relation.id]).newFeature(true));
103776             }
103777           }
103778
103779           function deleteMembership(d3_event, d) {
103780             this.blur(); // avoid keeping focus on the button
103781
103782             if (d === 0) return; // called on newrow (shouldn't happen)
103783             // remove the hover-highlight styling
103784
103785             utilHighlightEntities([d.relation.id], false, context);
103786             var indexes = d.members.map(function (member) {
103787               return member.index;
103788             });
103789             context.perform(actionDeleteMembers(d.relation.id, indexes), _t('operations.delete_member.annotation', {
103790               n: _entityIDs.length
103791             }));
103792             context.validator().validate();
103793           }
103794
103795           function fetchNearbyRelations(q, callback) {
103796             var newRelation = {
103797               relation: null,
103798               value: _t('inspector.new_relation'),
103799               display: _t.html('inspector.new_relation')
103800             };
103801             var entityID = _entityIDs[0];
103802             var result = [];
103803             var graph = context.graph();
103804
103805             function baseDisplayLabel(entity) {
103806               var matched = _mainPresetIndex.match(entity, graph);
103807               var presetName = matched && matched.name() || _t('inspector.relation');
103808               var entityName = utilDisplayName(entity) || '';
103809               return presetName + ' ' + entityName;
103810             }
103811
103812             var explicitRelation = q && context.hasEntity(q.toLowerCase());
103813
103814             if (explicitRelation && explicitRelation.type === 'relation' && explicitRelation.id !== entityID) {
103815               // loaded relation is specified explicitly, only show that
103816               result.push({
103817                 relation: explicitRelation,
103818                 value: baseDisplayLabel(explicitRelation) + ' ' + explicitRelation.id
103819               });
103820             } else {
103821               context.history().intersects(context.map().extent()).forEach(function (entity) {
103822                 if (entity.type !== 'relation' || entity.id === entityID) return;
103823                 var value = baseDisplayLabel(entity);
103824                 if (q && (value + ' ' + entity.id).toLowerCase().indexOf(q.toLowerCase()) === -1) return;
103825                 result.push({
103826                   relation: entity,
103827                   value: value
103828                 });
103829               });
103830               result.sort(function (a, b) {
103831                 return osmRelation.creationOrder(a.relation, b.relation);
103832               }); // Dedupe identical names by appending relation id - see #2891
103833
103834               var dupeGroups = Object.values(utilArrayGroupBy(result, 'value')).filter(function (v) {
103835                 return v.length > 1;
103836               });
103837               dupeGroups.forEach(function (group) {
103838                 group.forEach(function (obj) {
103839                   obj.value += ' ' + obj.relation.id;
103840                 });
103841               });
103842             }
103843
103844             result.forEach(function (obj) {
103845               obj.title = obj.value;
103846             });
103847             result.unshift(newRelation);
103848             callback(result);
103849           }
103850
103851           function renderDisclosureContent(selection) {
103852             var memberships = getMemberships();
103853             var list = selection.selectAll('.member-list').data([0]);
103854             list = list.enter().append('ul').attr('class', 'member-list').merge(list);
103855             var items = list.selectAll('li.member-row-normal').data(memberships, function (d) {
103856               return d.hash;
103857             });
103858             items.exit().each(unbind).remove(); // Enter
103859
103860             var itemsEnter = items.enter().append('li').attr('class', 'member-row member-row-normal form-field'); // highlight the relation in the map while hovering on the list item
103861
103862             itemsEnter.on('mouseover', function (d3_event, d) {
103863               utilHighlightEntities([d.relation.id], true, context);
103864             }).on('mouseout', function (d3_event, d) {
103865               utilHighlightEntities([d.relation.id], false, context);
103866             });
103867             var labelEnter = itemsEnter.append('label').attr('class', 'field-label').attr('for', function (d) {
103868               return d.domId;
103869             });
103870             var labelLink = labelEnter.append('span').attr('class', 'label-text').append('a').attr('href', '#').on('click', selectRelation);
103871             labelLink.append('span').attr('class', 'member-entity-type').text(function (d) {
103872               var matched = _mainPresetIndex.match(d.relation, context.graph());
103873               return matched && matched.name() || _t.html('inspector.relation');
103874             });
103875             labelLink.append('span').attr('class', 'member-entity-name').text(function (d) {
103876               return utilDisplayName(d.relation);
103877             });
103878             labelEnter.append('button').attr('class', 'remove member-delete').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete')).on('click', deleteMembership);
103879             labelEnter.append('button').attr('class', 'member-zoom').attr('title', _t('icons.zoom_to')).call(svgIcon('#iD-icon-framed-dot', 'monochrome')).on('click', zoomToRelation);
103880             var wrapEnter = itemsEnter.append('div').attr('class', 'form-field-input-wrap form-field-input-member');
103881             wrapEnter.append('input').attr('class', 'member-role').attr('id', function (d) {
103882               return d.domId;
103883             }).property('type', 'text').property('value', function (d) {
103884               return typeof d.role === 'string' ? d.role : '';
103885             }).attr('title', function (d) {
103886               return Array.isArray(d.role) ? d.role.filter(Boolean).join('\n') : d.role;
103887             }).attr('placeholder', function (d) {
103888               return Array.isArray(d.role) ? _t('inspector.multiple_roles') : _t('inspector.role');
103889             }).classed('mixed', function (d) {
103890               return Array.isArray(d.role);
103891             }).call(utilNoAuto).on('blur', changeRole).on('change', changeRole);
103892
103893             if (taginfo) {
103894               wrapEnter.each(bindTypeahead);
103895             }
103896
103897             var newMembership = list.selectAll('.member-row-new').data(_showBlank ? [0] : []); // Exit
103898
103899             newMembership.exit().remove(); // Enter
103900
103901             var newMembershipEnter = newMembership.enter().append('li').attr('class', 'member-row member-row-new form-field');
103902             var newLabelEnter = newMembershipEnter.append('label').attr('class', 'field-label');
103903             newLabelEnter.append('input').attr('placeholder', _t('inspector.choose_relation')).attr('type', 'text').attr('class', 'member-entity-input').call(utilNoAuto);
103904             newLabelEnter.append('button').attr('class', 'remove member-delete').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete')).on('click', function () {
103905               list.selectAll('.member-row-new').remove();
103906             });
103907             var newWrapEnter = newMembershipEnter.append('div').attr('class', 'form-field-input-wrap form-field-input-member');
103908             newWrapEnter.append('input').attr('class', 'member-role').property('type', 'text').attr('placeholder', _t('inspector.role')).call(utilNoAuto); // Update
103909
103910             newMembership = newMembership.merge(newMembershipEnter);
103911             newMembership.selectAll('.member-entity-input').on('blur', cancelEntity) // if it wasn't accepted normally, cancel it
103912             .call(nearbyCombo.on('accept', acceptEntity).on('cancel', cancelEntity)); // Container for the Add button
103913
103914             var addRow = selection.selectAll('.add-row').data([0]); // enter
103915
103916             var addRowEnter = addRow.enter().append('div').attr('class', 'add-row');
103917             var addRelationButton = addRowEnter.append('button').attr('class', 'add-relation').attr('aria-label', _t('inspector.add_to_relation'));
103918             addRelationButton.call(svgIcon('#iD-icon-plus', 'light'));
103919             addRelationButton.call(uiTooltip().title(_t.html('inspector.add_to_relation')).placement(_mainLocalizer.textDirection() === 'ltr' ? 'right' : 'left'));
103920             addRowEnter.append('div').attr('class', 'space-value'); // preserve space
103921
103922             addRowEnter.append('div').attr('class', 'space-buttons'); // preserve space
103923             // update
103924
103925             addRow = addRow.merge(addRowEnter);
103926             addRow.select('.add-relation').on('click', function () {
103927               _showBlank = true;
103928               section.reRender();
103929               list.selectAll('.member-entity-input').node().focus();
103930             });
103931
103932             function acceptEntity(d) {
103933               if (!d) {
103934                 cancelEntity();
103935                 return;
103936               } // remove hover-higlighting
103937
103938
103939               if (d.relation) utilHighlightEntities([d.relation.id], false, context);
103940               var role = context.cleanRelationRole(list.selectAll('.member-row-new .member-role').property('value'));
103941               addMembership(d, role);
103942             }
103943
103944             function cancelEntity() {
103945               var input = newMembership.selectAll('.member-entity-input');
103946               input.property('value', ''); // remove hover-higlighting
103947
103948               context.surface().selectAll('.highlighted').classed('highlighted', false);
103949             }
103950
103951             function bindTypeahead(d) {
103952               var row = select(this);
103953               var role = row.selectAll('input.member-role');
103954               var origValue = role.property('value');
103955
103956               function sort(value, data) {
103957                 var sameletter = [];
103958                 var other = [];
103959
103960                 for (var i = 0; i < data.length; i++) {
103961                   if (data[i].value.substring(0, value.length) === value) {
103962                     sameletter.push(data[i]);
103963                   } else {
103964                     other.push(data[i]);
103965                   }
103966                 }
103967
103968                 return sameletter.concat(other);
103969               }
103970
103971               role.call(uiCombobox(context, 'member-role').fetcher(function (role, callback) {
103972                 var rtype = d.relation.tags.type;
103973                 taginfo.roles({
103974                   debounce: true,
103975                   rtype: rtype || '',
103976                   geometry: context.graph().geometry(_entityIDs[0]),
103977                   query: role
103978                 }, function (err, data) {
103979                   if (!err) callback(sort(role, data));
103980                 });
103981               }).on('cancel', function () {
103982                 role.property('value', origValue);
103983               }));
103984             }
103985
103986             function unbind() {
103987               var row = select(this);
103988               row.selectAll('input.member-role').call(uiCombobox.off, context);
103989             }
103990           }
103991
103992           section.entityIDs = function (val) {
103993             if (!arguments.length) return _entityIDs;
103994             _entityIDs = val;
103995             _showBlank = false;
103996             return section;
103997           };
103998
103999           return section;
104000         }
104001
104002         function uiSectionSelectionList(context) {
104003           var _selectedIDs = [];
104004           var section = uiSection('selected-features', context).shouldDisplay(function () {
104005             return _selectedIDs.length > 1;
104006           }).label(function () {
104007             return _t.html('inspector.title_count', {
104008               title: {
104009                 html: _t.html('inspector.features')
104010               },
104011               count: _selectedIDs.length
104012             });
104013           }).disclosureContent(renderDisclosureContent);
104014           context.history().on('change.selectionList', function (difference) {
104015             if (difference) {
104016               section.reRender();
104017             }
104018           });
104019
104020           section.entityIDs = function (val) {
104021             if (!arguments.length) return _selectedIDs;
104022             _selectedIDs = val;
104023             return section;
104024           };
104025
104026           function selectEntity(d3_event, entity) {
104027             context.enter(modeSelect(context, [entity.id]));
104028           }
104029
104030           function deselectEntity(d3_event, entity) {
104031             var selectedIDs = _selectedIDs.slice();
104032
104033             var index = selectedIDs.indexOf(entity.id);
104034
104035             if (index > -1) {
104036               selectedIDs.splice(index, 1);
104037               context.enter(modeSelect(context, selectedIDs));
104038             }
104039           }
104040
104041           function renderDisclosureContent(selection) {
104042             var list = selection.selectAll('.feature-list').data([0]);
104043             list = list.enter().append('ul').attr('class', 'feature-list').merge(list);
104044
104045             var entities = _selectedIDs.map(function (id) {
104046               return context.hasEntity(id);
104047             }).filter(Boolean);
104048
104049             var items = list.selectAll('.feature-list-item').data(entities, osmEntity.key);
104050             items.exit().remove(); // Enter
104051
104052             var enter = items.enter().append('li').attr('class', 'feature-list-item').each(function (d) {
104053               select(this).on('mouseover', function () {
104054                 utilHighlightEntities([d.id], true, context);
104055               }).on('mouseout', function () {
104056                 utilHighlightEntities([d.id], false, context);
104057               });
104058             });
104059             var label = enter.append('button').attr('class', 'label').on('click', selectEntity);
104060             label.append('span').attr('class', 'entity-geom-icon').call(svgIcon('', 'pre-text'));
104061             label.append('span').attr('class', 'entity-type');
104062             label.append('span').attr('class', 'entity-name');
104063             enter.append('button').attr('class', 'close').attr('title', _t('icons.deselect')).on('click', deselectEntity).call(svgIcon('#iD-icon-close')); // Update
104064
104065             items = items.merge(enter);
104066             items.selectAll('.entity-geom-icon use').attr('href', function () {
104067               var entity = this.parentNode.parentNode.__data__;
104068               return '#iD-icon-' + entity.geometry(context.graph());
104069             });
104070             items.selectAll('.entity-type').text(function (entity) {
104071               return _mainPresetIndex.match(entity, context.graph()).name();
104072             });
104073             items.selectAll('.entity-name').text(function (d) {
104074               // fetch latest entity
104075               var entity = context.entity(d.id);
104076               return utilDisplayName(entity);
104077             });
104078           }
104079
104080           return section;
104081         }
104082
104083         function uiEntityEditor(context) {
104084           var dispatch = dispatch$8('choose');
104085           var _state = 'select';
104086           var _coalesceChanges = false;
104087           var _modified = false;
104088
104089           var _base;
104090
104091           var _entityIDs;
104092
104093           var _activePresets = [];
104094
104095           var _newFeature;
104096
104097           var _sections;
104098
104099           function entityEditor(selection) {
104100             var combinedTags = utilCombinedTags(_entityIDs, context.graph()); // Header
104101
104102             var header = selection.selectAll('.header').data([0]); // Enter
104103
104104             var headerEnter = header.enter().append('div').attr('class', 'header fillL');
104105             var direction = _mainLocalizer.textDirection() === 'rtl' ? 'forward' : 'backward';
104106             headerEnter.append('button').attr('class', 'preset-reset preset-choose').attr('title', _t("icons.".concat(direction))).call(svgIcon("#iD-icon-".concat(direction)));
104107             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
104108               context.enter(modeBrowse(context));
104109             }).call(svgIcon(_modified ? '#iD-icon-apply' : '#iD-icon-close'));
104110             headerEnter.append('h2'); // Update
104111
104112             header = header.merge(headerEnter);
104113             header.selectAll('h2').html(_entityIDs.length === 1 ? _t.html('inspector.edit') : _t.html('inspector.edit_features'));
104114             header.selectAll('.preset-reset').on('click', function () {
104115               dispatch.call('choose', this, _activePresets);
104116             }); // Body
104117
104118             var body = selection.selectAll('.inspector-body').data([0]); // Enter
104119
104120             var bodyEnter = body.enter().append('div').attr('class', 'entity-editor inspector-body sep-top'); // Update
104121
104122             body = body.merge(bodyEnter);
104123
104124             if (!_sections) {
104125               _sections = [uiSectionSelectionList(context), uiSectionFeatureType(context).on('choose', function (presets) {
104126                 dispatch.call('choose', this, presets);
104127               }), uiSectionEntityIssues(context), uiSectionPresetFields(context).on('change', changeTags).on('revert', revertTags), uiSectionRawTagEditor('raw-tag-editor', context).on('change', changeTags), uiSectionRawMemberEditor(context), uiSectionRawMembershipEditor(context)];
104128             }
104129
104130             _sections.forEach(function (section) {
104131               if (section.entityIDs) {
104132                 section.entityIDs(_entityIDs);
104133               }
104134
104135               if (section.presets) {
104136                 section.presets(_activePresets);
104137               }
104138
104139               if (section.tags) {
104140                 section.tags(combinedTags);
104141               }
104142
104143               if (section.state) {
104144                 section.state(_state);
104145               }
104146
104147               body.call(section.render);
104148             });
104149
104150             context.history().on('change.entity-editor', historyChanged);
104151
104152             function historyChanged(difference) {
104153               if (selection.selectAll('.entity-editor').empty()) return;
104154               if (_state === 'hide') return;
104155               var significant = !difference || difference.didChange.properties || difference.didChange.addition || difference.didChange.deletion;
104156               if (!significant) return;
104157               _entityIDs = _entityIDs.filter(context.hasEntity);
104158               if (!_entityIDs.length) return;
104159               var priorActivePreset = _activePresets.length === 1 && _activePresets[0];
104160               loadActivePresets();
104161               var graph = context.graph();
104162               entityEditor.modified(_base !== graph);
104163               entityEditor(selection);
104164
104165               if (priorActivePreset && _activePresets.length === 1 && priorActivePreset !== _activePresets[0]) {
104166                 // flash the button to indicate the preset changed
104167                 context.container().selectAll('.entity-editor button.preset-reset .label').style('background-color', '#fff').transition().duration(750).style('background-color', null);
104168               }
104169             }
104170           } // Tag changes that fire on input can all get coalesced into a single
104171           // history operation when the user leaves the field.  #2342
104172           // Use explicit entityIDs in case the selection changes before the event is fired.
104173
104174
104175           function changeTags(entityIDs, changed, onInput) {
104176             var actions = [];
104177
104178             for (var i in entityIDs) {
104179               var entityID = entityIDs[i];
104180               var entity = context.entity(entityID);
104181               var tags = Object.assign({}, entity.tags); // shallow copy
104182
104183               for (var k in changed) {
104184                 if (!k) continue;
104185                 var v = changed[k];
104186
104187                 if (_typeof(v) === 'object') {
104188                   // a "key only" tag change
104189                   tags[k] = tags[v.oldKey];
104190                 } else if (v !== undefined || tags.hasOwnProperty(k)) {
104191                   tags[k] = v;
104192                 }
104193               }
104194
104195               if (!onInput) {
104196                 tags = utilCleanTags(tags);
104197               }
104198
104199               if (!fastDeepEqual(entity.tags, tags)) {
104200                 actions.push(actionChangeTags(entityID, tags));
104201               }
104202             }
104203
104204             if (actions.length) {
104205               var combinedAction = function combinedAction(graph) {
104206                 actions.forEach(function (action) {
104207                   graph = action(graph);
104208                 });
104209                 return graph;
104210               };
104211
104212               var annotation = _t('operations.change_tags.annotation');
104213
104214               if (_coalesceChanges) {
104215                 context.overwrite(combinedAction, annotation);
104216               } else {
104217                 context.perform(combinedAction, annotation);
104218                 _coalesceChanges = !!onInput;
104219               }
104220             } // if leaving field (blur event), rerun validation
104221
104222
104223             if (!onInput) {
104224               context.validator().validate();
104225             }
104226           }
104227
104228           function revertTags(keys) {
104229             var actions = [];
104230
104231             for (var i in _entityIDs) {
104232               var entityID = _entityIDs[i];
104233               var original = context.graph().base().entities[entityID];
104234               var changed = {};
104235
104236               for (var j in keys) {
104237                 var key = keys[j];
104238                 changed[key] = original ? original.tags[key] : undefined;
104239               }
104240
104241               var entity = context.entity(entityID);
104242               var tags = Object.assign({}, entity.tags); // shallow copy
104243
104244               for (var k in changed) {
104245                 if (!k) continue;
104246                 var v = changed[k];
104247
104248                 if (v !== undefined || tags.hasOwnProperty(k)) {
104249                   tags[k] = v;
104250                 }
104251               }
104252
104253               tags = utilCleanTags(tags);
104254
104255               if (!fastDeepEqual(entity.tags, tags)) {
104256                 actions.push(actionChangeTags(entityID, tags));
104257               }
104258             }
104259
104260             if (actions.length) {
104261               var combinedAction = function combinedAction(graph) {
104262                 actions.forEach(function (action) {
104263                   graph = action(graph);
104264                 });
104265                 return graph;
104266               };
104267
104268               var annotation = _t('operations.change_tags.annotation');
104269
104270               if (_coalesceChanges) {
104271                 context.overwrite(combinedAction, annotation);
104272               } else {
104273                 context.perform(combinedAction, annotation);
104274                 _coalesceChanges = false;
104275               }
104276             }
104277
104278             context.validator().validate();
104279           }
104280
104281           entityEditor.modified = function (val) {
104282             if (!arguments.length) return _modified;
104283             _modified = val;
104284             return entityEditor;
104285           };
104286
104287           entityEditor.state = function (val) {
104288             if (!arguments.length) return _state;
104289             _state = val;
104290             return entityEditor;
104291           };
104292
104293           entityEditor.entityIDs = function (val) {
104294             if (!arguments.length) return _entityIDs; // always reload these even if the entityIDs are unchanged, since we
104295             // could be reselecting after something like dragging a node
104296
104297             _base = context.graph();
104298             _coalesceChanges = false;
104299             if (val && _entityIDs && utilArrayIdentical(_entityIDs, val)) return entityEditor; // exit early if no change
104300
104301             _entityIDs = val;
104302             loadActivePresets(true);
104303             return entityEditor.modified(false);
104304           };
104305
104306           entityEditor.newFeature = function (val) {
104307             if (!arguments.length) return _newFeature;
104308             _newFeature = val;
104309             return entityEditor;
104310           };
104311
104312           function loadActivePresets(isForNewSelection) {
104313             var graph = context.graph();
104314             var counts = {};
104315
104316             for (var i in _entityIDs) {
104317               var entity = graph.hasEntity(_entityIDs[i]);
104318               if (!entity) return;
104319               var match = _mainPresetIndex.match(entity, graph);
104320               if (!counts[match.id]) counts[match.id] = 0;
104321               counts[match.id] += 1;
104322             }
104323
104324             var matches = Object.keys(counts).sort(function (p1, p2) {
104325               return counts[p2] - counts[p1];
104326             }).map(function (pID) {
104327               return _mainPresetIndex.item(pID);
104328             });
104329
104330             if (!isForNewSelection) {
104331               // A "weak" preset doesn't set any tags. (e.g. "Address")
104332               var weakPreset = _activePresets.length === 1 && !_activePresets[0].isFallback() && Object.keys(_activePresets[0].addTags || {}).length === 0; // Don't replace a weak preset with a fallback preset (e.g. "Point")
104333
104334               if (weakPreset && matches.length === 1 && matches[0].isFallback()) return;
104335             }
104336
104337             entityEditor.presets(matches);
104338           }
104339
104340           entityEditor.presets = function (val) {
104341             if (!arguments.length) return _activePresets; // don't reload the same preset
104342
104343             if (!utilArrayIdentical(val, _activePresets)) {
104344               _activePresets = val;
104345             }
104346
104347             return entityEditor;
104348           };
104349
104350           return utilRebind(entityEditor, dispatch, 'on');
104351         }
104352
104353         var sexagesimal = {exports: {}};
104354
104355         sexagesimal.exports = element;
104356         var pair_1 = sexagesimal.exports.pair = pair;
104357         sexagesimal.exports.format = format;
104358         sexagesimal.exports.formatPair = formatPair;
104359         sexagesimal.exports.coordToDMS = coordToDMS;
104360
104361         function element(input, dims) {
104362           var result = search(input, dims);
104363           return result === null ? null : result.val;
104364         }
104365
104366         function formatPair(input) {
104367           return format(input.lat, 'lat') + ' ' + format(input.lon, 'lon');
104368         } // Is 0 North or South?
104369
104370
104371         function format(input, dim) {
104372           var dms = coordToDMS(input, dim);
104373           return dms.whole + '° ' + (dms.minutes ? dms.minutes + '\' ' : '') + (dms.seconds ? dms.seconds + '" ' : '') + dms.dir;
104374         }
104375
104376         function coordToDMS(input, dim) {
104377           var dirs = {
104378             lat: ['N', 'S'],
104379             lon: ['E', 'W']
104380           }[dim] || '';
104381           var dir = dirs[input >= 0 ? 0 : 1];
104382           var abs = Math.abs(input);
104383           var whole = Math.floor(abs);
104384           var fraction = abs - whole;
104385           var fractionMinutes = fraction * 60;
104386           var minutes = Math.floor(fractionMinutes);
104387           var seconds = Math.floor((fractionMinutes - minutes) * 60);
104388           return {
104389             whole: whole,
104390             minutes: minutes,
104391             seconds: seconds,
104392             dir: dir
104393           };
104394         }
104395
104396         function search(input, dims) {
104397           if (!dims) dims = 'NSEW';
104398           if (typeof input !== 'string') return null;
104399           input = input.toUpperCase();
104400           var regex = /^[\s\,]*([NSEW])?\s*([\-|\—|\―]?[0-9.]+)[°º˚]?\s*(?:([0-9.]+)['’′‘]\s*)?(?:([0-9.]+)(?:''|"|”|″)\s*)?([NSEW])?/;
104401           var m = input.match(regex);
104402           if (!m) return null; // no match
104403
104404           var matched = m[0]; // extract dimension.. m[1] = leading, m[5] = trailing
104405
104406           var dim;
104407
104408           if (m[1] && m[5]) {
104409             // if matched both..
104410             dim = m[1]; // keep leading
104411
104412             matched = matched.slice(0, -1); // remove trailing dimension from match
104413           } else {
104414             dim = m[1] || m[5];
104415           } // if unrecognized dimension
104416
104417
104418           if (dim && dims.indexOf(dim) === -1) return null; // extract DMS
104419
104420           var deg = m[2] ? parseFloat(m[2]) : 0;
104421           var min = m[3] ? parseFloat(m[3]) / 60 : 0;
104422           var sec = m[4] ? parseFloat(m[4]) / 3600 : 0;
104423           var sign = deg < 0 ? -1 : 1;
104424           if (dim === 'S' || dim === 'W') sign *= -1;
104425           return {
104426             val: (Math.abs(deg) + min + sec) * sign,
104427             dim: dim,
104428             matched: matched,
104429             remain: input.slice(matched.length)
104430           };
104431         }
104432
104433         function pair(input, dims) {
104434           input = input.trim();
104435           var one = search(input, dims);
104436           if (!one) return null;
104437           input = one.remain.trim();
104438           var two = search(input, dims);
104439           if (!two || two.remain) return null;
104440
104441           if (one.dim) {
104442             return swapdim(one.val, two.val, one.dim);
104443           } else {
104444             return [one.val, two.val];
104445           }
104446         }
104447
104448         function swapdim(a, b, dim) {
104449           if (dim === 'N' || dim === 'S') return [a, b];
104450           if (dim === 'W' || dim === 'E') return [b, a];
104451         }
104452
104453         function uiFeatureList(context) {
104454           var _geocodeResults;
104455
104456           function featureList(selection) {
104457             var header = selection.append('div').attr('class', 'header fillL');
104458             header.append('h2').call(_t.append('inspector.feature_list'));
104459             var searchWrap = selection.append('div').attr('class', 'search-header');
104460             searchWrap.call(svgIcon('#iD-icon-search', 'pre-text'));
104461             var search = searchWrap.append('input').attr('placeholder', _t('inspector.search')).attr('type', 'search').call(utilNoAuto).on('keypress', keypress).on('keydown', keydown).on('input', inputevent);
104462             var listWrap = selection.append('div').attr('class', 'inspector-body');
104463             var list = listWrap.append('div').attr('class', 'feature-list');
104464             context.on('exit.feature-list', clearSearch);
104465             context.map().on('drawn.feature-list', mapDrawn);
104466             context.keybinding().on(uiCmd('⌘F'), focusSearch);
104467
104468             function focusSearch(d3_event) {
104469               var mode = context.mode() && context.mode().id;
104470               if (mode !== 'browse') return;
104471               d3_event.preventDefault();
104472               search.node().focus();
104473             }
104474
104475             function keydown(d3_event) {
104476               if (d3_event.keyCode === 27) {
104477                 // escape
104478                 search.node().blur();
104479               }
104480             }
104481
104482             function keypress(d3_event) {
104483               var q = search.property('value'),
104484                   items = list.selectAll('.feature-list-item');
104485
104486               if (d3_event.keyCode === 13 && // ↩ Return
104487               q.length && items.size()) {
104488                 click(d3_event, items.datum());
104489               }
104490             }
104491
104492             function inputevent() {
104493               _geocodeResults = undefined;
104494               drawList();
104495             }
104496
104497             function clearSearch() {
104498               search.property('value', '');
104499               drawList();
104500             }
104501
104502             function mapDrawn(e) {
104503               if (e.full) {
104504                 drawList();
104505               }
104506             }
104507
104508             function features() {
104509               var result = [];
104510               var graph = context.graph();
104511               var visibleCenter = context.map().extent().center();
104512               var q = search.property('value').toLowerCase();
104513               if (!q) return result;
104514               var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
104515
104516               if (locationMatch) {
104517                 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
104518                 result.push({
104519                   id: -1,
104520                   geometry: 'point',
104521                   type: _t('inspector.location'),
104522                   name: dmsCoordinatePair([loc[1], loc[0]]),
104523                   location: loc
104524                 });
104525               } // A location search takes priority over an ID search
104526
104527
104528               var idMatch = !locationMatch && q.match(/(?:^|\W)(node|way|relation|[nwr])\W?0*([1-9]\d*)(?:\W|$)/i);
104529
104530               if (idMatch) {
104531                 var elemType = idMatch[1].charAt(0);
104532                 var elemId = idMatch[2];
104533                 result.push({
104534                   id: elemType + elemId,
104535                   geometry: elemType === 'n' ? 'point' : elemType === 'w' ? 'line' : 'relation',
104536                   type: elemType === 'n' ? _t('inspector.node') : elemType === 'w' ? _t('inspector.way') : _t('inspector.relation'),
104537                   name: elemId
104538                 });
104539               }
104540
104541               var allEntities = graph.entities;
104542               var localResults = [];
104543
104544               for (var id in allEntities) {
104545                 var entity = allEntities[id];
104546                 if (!entity) continue;
104547                 var name = utilDisplayName(entity) || '';
104548                 if (name.toLowerCase().indexOf(q) < 0) continue;
104549                 var matched = _mainPresetIndex.match(entity, graph);
104550                 var type = matched && matched.name() || utilDisplayType(entity.id);
104551                 var extent = entity.extent(graph);
104552                 var distance = extent ? geoSphericalDistance(visibleCenter, extent.center()) : 0;
104553                 localResults.push({
104554                   id: entity.id,
104555                   entity: entity,
104556                   geometry: entity.geometry(graph),
104557                   type: type,
104558                   name: name,
104559                   distance: distance
104560                 });
104561                 if (localResults.length > 100) break;
104562               }
104563
104564               localResults = localResults.sort(function byDistance(a, b) {
104565                 return a.distance - b.distance;
104566               });
104567               result = result.concat(localResults);
104568
104569               (_geocodeResults || []).forEach(function (d) {
104570                 if (d.osm_type && d.osm_id) {
104571                   // some results may be missing these - #1890
104572                   // Make a temporary osmEntity so we can preset match
104573                   // and better localize the search result - #4725
104574                   var id = osmEntity.id.fromOSM(d.osm_type, d.osm_id);
104575                   var tags = {};
104576                   tags[d["class"]] = d.type;
104577                   var attrs = {
104578                     id: id,
104579                     type: d.osm_type,
104580                     tags: tags
104581                   };
104582
104583                   if (d.osm_type === 'way') {
104584                     // for ways, add some fake closed nodes
104585                     attrs.nodes = ['a', 'a']; // so that geometry area is possible
104586                   }
104587
104588                   var tempEntity = osmEntity(attrs);
104589                   var tempGraph = coreGraph([tempEntity]);
104590                   var matched = _mainPresetIndex.match(tempEntity, tempGraph);
104591                   var type = matched && matched.name() || utilDisplayType(id);
104592                   result.push({
104593                     id: tempEntity.id,
104594                     geometry: tempEntity.geometry(tempGraph),
104595                     type: type,
104596                     name: d.display_name,
104597                     extent: new geoExtent([parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])], [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
104598                   });
104599                 }
104600               });
104601
104602               if (q.match(/^[0-9]+$/)) {
104603                 // if query is just a number, possibly an OSM ID without a prefix
104604                 result.push({
104605                   id: 'n' + q,
104606                   geometry: 'point',
104607                   type: _t('inspector.node'),
104608                   name: q
104609                 });
104610                 result.push({
104611                   id: 'w' + q,
104612                   geometry: 'line',
104613                   type: _t('inspector.way'),
104614                   name: q
104615                 });
104616                 result.push({
104617                   id: 'r' + q,
104618                   geometry: 'relation',
104619                   type: _t('inspector.relation'),
104620                   name: q
104621                 });
104622               }
104623
104624               return result;
104625             }
104626
104627             function drawList() {
104628               var value = search.property('value');
104629               var results = features();
104630               list.classed('filtered', value.length);
104631               var resultsIndicator = list.selectAll('.no-results-item').data([0]).enter().append('button').property('disabled', true).attr('class', 'no-results-item').call(svgIcon('#iD-icon-alert', 'pre-text'));
104632               resultsIndicator.append('span').attr('class', 'entity-name');
104633               list.selectAll('.no-results-item .entity-name').html('').call(_t.append('geocoder.no_results_worldwide'));
104634
104635               if (services.geocoder) {
104636                 list.selectAll('.geocode-item').data([0]).enter().append('button').attr('class', 'geocode-item secondary-action').on('click', geocoderSearch).append('div').attr('class', 'label').append('span').attr('class', 'entity-name').call(_t.append('geocoder.search'));
104637               }
104638
104639               list.selectAll('.no-results-item').style('display', value.length && !results.length ? 'block' : 'none');
104640               list.selectAll('.geocode-item').style('display', value && _geocodeResults === undefined ? 'block' : 'none');
104641               list.selectAll('.feature-list-item').data([-1]).remove();
104642               var items = list.selectAll('.feature-list-item').data(results, function (d) {
104643                 return d.id;
104644               });
104645               var enter = items.enter().insert('button', '.geocode-item').attr('class', 'feature-list-item').on('mouseover', mouseover).on('mouseout', mouseout).on('click', click);
104646               var label = enter.append('div').attr('class', 'label');
104647               label.each(function (d) {
104648                 select(this).call(svgIcon('#iD-icon-' + d.geometry, 'pre-text'));
104649               });
104650               label.append('span').attr('class', 'entity-type').text(function (d) {
104651                 return d.type;
104652               });
104653               label.append('span').attr('class', 'entity-name').text(function (d) {
104654                 return d.name;
104655               });
104656               enter.style('opacity', 0).transition().style('opacity', 1);
104657               items.order();
104658               items.exit().remove();
104659             }
104660
104661             function mouseover(d3_event, d) {
104662               if (d.id === -1) return;
104663               utilHighlightEntities([d.id], true, context);
104664             }
104665
104666             function mouseout(d3_event, d) {
104667               if (d.id === -1) return;
104668               utilHighlightEntities([d.id], false, context);
104669             }
104670
104671             function click(d3_event, d) {
104672               d3_event.preventDefault();
104673
104674               if (d.location) {
104675                 context.map().centerZoomEase([d.location[1], d.location[0]], 19);
104676               } else if (d.entity) {
104677                 utilHighlightEntities([d.id], false, context);
104678                 context.enter(modeSelect(context, [d.entity.id]));
104679                 context.map().zoomToEase(d.entity);
104680               } else {
104681                 // download, zoom to, and select the entity with the given ID
104682                 context.zoomToEntity(d.id);
104683               }
104684             }
104685
104686             function geocoderSearch() {
104687               services.geocoder.search(search.property('value'), function (err, resp) {
104688                 _geocodeResults = resp || [];
104689                 drawList();
104690               });
104691             }
104692           }
104693
104694           return featureList;
104695         }
104696
104697         function uiImproveOsmComments() {
104698           var _qaItem;
104699
104700           function issueComments(selection) {
104701             // make the div immediately so it appears above the buttons
104702             var comments = selection.selectAll('.comments-container').data([0]);
104703             comments = comments.enter().append('div').attr('class', 'comments-container').merge(comments); // must retrieve comments from API before they can be displayed
104704
104705             services.improveOSM.getComments(_qaItem).then(function (d) {
104706               if (!d.comments) return; // nothing to do here
104707
104708               var commentEnter = comments.selectAll('.comment').data(d.comments).enter().append('div').attr('class', 'comment');
104709               commentEnter.append('div').attr('class', 'comment-avatar').call(svgIcon('#iD-icon-avatar', 'comment-avatar-icon'));
104710               var mainEnter = commentEnter.append('div').attr('class', 'comment-main');
104711               var metadataEnter = mainEnter.append('div').attr('class', 'comment-metadata');
104712               metadataEnter.append('div').attr('class', 'comment-author').each(function (d) {
104713                 var osm = services.osm;
104714                 var selection = select(this);
104715
104716                 if (osm && d.username) {
104717                   selection = selection.append('a').attr('class', 'comment-author-link').attr('href', osm.userURL(d.username)).attr('target', '_blank');
104718                 }
104719
104720                 selection.text(function (d) {
104721                   return d.username;
104722                 });
104723               });
104724               metadataEnter.append('div').attr('class', 'comment-date').html(function (d) {
104725                 return _t.html('note.status.commented', {
104726                   when: localeDateString(d.timestamp)
104727                 });
104728               });
104729               mainEnter.append('div').attr('class', 'comment-text').append('p').text(function (d) {
104730                 return d.text;
104731               });
104732             })["catch"](function (err) {
104733               console.log(err); // eslint-disable-line no-console
104734             });
104735           }
104736
104737           function localeDateString(s) {
104738             if (!s) return null;
104739             var options = {
104740               day: 'numeric',
104741               month: 'short',
104742               year: 'numeric'
104743             };
104744             var d = new Date(s * 1000); // timestamp is served in seconds, date takes ms
104745
104746             if (isNaN(d.getTime())) return null;
104747             return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
104748           }
104749
104750           issueComments.issue = function (val) {
104751             if (!arguments.length) return _qaItem;
104752             _qaItem = val;
104753             return issueComments;
104754           };
104755
104756           return issueComments;
104757         }
104758
104759         function uiImproveOsmDetails(context) {
104760           var _qaItem;
104761
104762           function issueDetail(d) {
104763             if (d.desc) return d.desc;
104764             var issueKey = d.issueKey;
104765             d.replacements = d.replacements || {};
104766             d.replacements["default"] = {
104767               html: _t.html('inspector.unknown')
104768             }; // special key `default` works as a fallback string
104769
104770             return _t.html("QA.improveOSM.error_types.".concat(issueKey, ".description"), d.replacements);
104771           }
104772
104773           function improveOsmDetails(selection) {
104774             var details = selection.selectAll('.error-details').data(_qaItem ? [_qaItem] : [], function (d) {
104775               return "".concat(d.id, "-").concat(d.status || 0);
104776             });
104777             details.exit().remove();
104778             var detailsEnter = details.enter().append('div').attr('class', 'error-details qa-details-container'); // description
104779
104780             var descriptionEnter = detailsEnter.append('div').attr('class', 'qa-details-subsection');
104781             descriptionEnter.append('h4').call(_t.append('QA.keepRight.detail_description'));
104782             descriptionEnter.append('div').attr('class', 'qa-details-description-text').html(issueDetail); // If there are entity links in the error message..
104783
104784             var relatedEntities = [];
104785             descriptionEnter.selectAll('.error_entity_link, .error_object_link').attr('href', '#').each(function () {
104786               var link = select(this);
104787               var isObjectLink = link.classed('error_object_link');
104788               var entityID = isObjectLink ? utilEntityRoot(_qaItem.objectType) + _qaItem.objectId : this.textContent;
104789               var entity = context.hasEntity(entityID);
104790               relatedEntities.push(entityID); // Add click handler
104791
104792               link.on('mouseenter', function () {
104793                 utilHighlightEntities([entityID], true, context);
104794               }).on('mouseleave', function () {
104795                 utilHighlightEntities([entityID], false, context);
104796               }).on('click', function (d3_event) {
104797                 d3_event.preventDefault();
104798                 utilHighlightEntities([entityID], false, context);
104799                 var osmlayer = context.layers().layer('osm');
104800
104801                 if (!osmlayer.enabled()) {
104802                   osmlayer.enabled(true);
104803                 }
104804
104805                 context.map().centerZoom(_qaItem.loc, 20);
104806
104807                 if (entity) {
104808                   context.enter(modeSelect(context, [entityID]));
104809                 } else {
104810                   context.loadEntity(entityID, function (err, result) {
104811                     if (err) return;
104812                     var entity = result.data.find(function (e) {
104813                       return e.id === entityID;
104814                     });
104815                     if (entity) context.enter(modeSelect(context, [entityID]));
104816                   });
104817                 }
104818               }); // Replace with friendly name if possible
104819               // (The entity may not yet be loaded into the graph)
104820
104821               if (entity) {
104822                 var name = utilDisplayName(entity); // try to use common name
104823
104824                 if (!name && !isObjectLink) {
104825                   var preset = _mainPresetIndex.match(entity, context.graph());
104826                   name = preset && !preset.isFallback() && preset.name(); // fallback to preset name
104827                 }
104828
104829                 if (name) {
104830                   this.innerText = name;
104831                 }
104832               }
104833             }); // Don't hide entities related to this error - #5880
104834
104835             context.features().forceVisible(relatedEntities);
104836             context.map().pan([0, 0]); // trigger a redraw
104837           }
104838
104839           improveOsmDetails.issue = function (val) {
104840             if (!arguments.length) return _qaItem;
104841             _qaItem = val;
104842             return improveOsmDetails;
104843           };
104844
104845           return improveOsmDetails;
104846         }
104847
104848         function uiImproveOsmHeader() {
104849           var _qaItem;
104850
104851           function issueTitle(d) {
104852             var issueKey = d.issueKey;
104853             d.replacements = d.replacements || {};
104854             d.replacements["default"] = {
104855               html: _t.html('inspector.unknown')
104856             }; // special key `default` works as a fallback string
104857
104858             return _t.html("QA.improveOSM.error_types.".concat(issueKey, ".title"), d.replacements);
104859           }
104860
104861           function improveOsmHeader(selection) {
104862             var header = selection.selectAll('.qa-header').data(_qaItem ? [_qaItem] : [], function (d) {
104863               return "".concat(d.id, "-").concat(d.status || 0);
104864             });
104865             header.exit().remove();
104866             var headerEnter = header.enter().append('div').attr('class', 'qa-header');
104867             var svgEnter = headerEnter.append('div').attr('class', 'qa-header-icon').classed('new', function (d) {
104868               return d.id < 0;
104869             }).append('svg').attr('width', '20px').attr('height', '30px').attr('viewbox', '0 0 20 30').attr('class', function (d) {
104870               return "preset-icon-28 qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
104871             });
104872             svgEnter.append('polygon').attr('fill', 'currentColor').attr('class', 'qaItem-fill').attr('points', '16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6');
104873             svgEnter.append('use').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('transform', 'translate(3.5, 5)').attr('xlink:href', function (d) {
104874               var picon = d.icon;
104875
104876               if (!picon) {
104877                 return '';
104878               } else {
104879                 var isMaki = /^maki-/.test(picon);
104880                 return "#".concat(picon).concat(isMaki ? '-11' : '');
104881               }
104882             });
104883             headerEnter.append('div').attr('class', 'qa-header-label').html(issueTitle);
104884           }
104885
104886           improveOsmHeader.issue = function (val) {
104887             if (!arguments.length) return _qaItem;
104888             _qaItem = val;
104889             return improveOsmHeader;
104890           };
104891
104892           return improveOsmHeader;
104893         }
104894
104895         function uiImproveOsmEditor(context) {
104896           var dispatch = dispatch$8('change');
104897           var qaDetails = uiImproveOsmDetails(context);
104898           var qaComments = uiImproveOsmComments();
104899           var qaHeader = uiImproveOsmHeader();
104900
104901           var _qaItem;
104902
104903           function improveOsmEditor(selection) {
104904             var headerEnter = selection.selectAll('.header').data([0]).enter().append('div').attr('class', 'header fillL');
104905             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
104906               return context.enter(modeBrowse(context));
104907             }).call(svgIcon('#iD-icon-close'));
104908             headerEnter.append('h2').call(_t.append('QA.improveOSM.title'));
104909             var body = selection.selectAll('.body').data([0]);
104910             body = body.enter().append('div').attr('class', 'body').merge(body);
104911             var editor = body.selectAll('.qa-editor').data([0]);
104912             editor.enter().append('div').attr('class', 'modal-section qa-editor').merge(editor).call(qaHeader.issue(_qaItem)).call(qaDetails.issue(_qaItem)).call(qaComments.issue(_qaItem)).call(improveOsmSaveSection);
104913           }
104914
104915           function improveOsmSaveSection(selection) {
104916             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
104917
104918             var isShown = _qaItem && (isSelected || _qaItem.newComment || _qaItem.comment);
104919             var saveSection = selection.selectAll('.qa-save').data(isShown ? [_qaItem] : [], function (d) {
104920               return "".concat(d.id, "-").concat(d.status || 0);
104921             }); // exit
104922
104923             saveSection.exit().remove(); // enter
104924
104925             var saveSectionEnter = saveSection.enter().append('div').attr('class', 'qa-save save-section cf');
104926             saveSectionEnter.append('h4').attr('class', '.qa-save-header').call(_t.append('note.newComment'));
104927             saveSectionEnter.append('textarea').attr('class', 'new-comment-input').attr('placeholder', _t('QA.keepRight.comment_placeholder')).attr('maxlength', 1000).property('value', function (d) {
104928               return d.newComment;
104929             }).call(utilNoAuto).on('input', changeInput).on('blur', changeInput); // update
104930
104931             saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
104932
104933             function changeInput() {
104934               var input = select(this);
104935               var val = input.property('value').trim();
104936
104937               if (val === '') {
104938                 val = undefined;
104939               } // store the unsaved comment with the issue itself
104940
104941
104942               _qaItem = _qaItem.update({
104943                 newComment: val
104944               });
104945               var qaService = services.improveOSM;
104946
104947               if (qaService) {
104948                 qaService.replaceItem(_qaItem);
104949               }
104950
104951               saveSection.call(qaSaveButtons);
104952             }
104953           }
104954
104955           function qaSaveButtons(selection) {
104956             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
104957
104958             var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_qaItem] : [], function (d) {
104959               return d.status + d.id;
104960             }); // exit
104961
104962             buttonSection.exit().remove(); // enter
104963
104964             var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
104965             buttonEnter.append('button').attr('class', 'button comment-button action').call(_t.append('QA.keepRight.save_comment'));
104966             buttonEnter.append('button').attr('class', 'button close-button action');
104967             buttonEnter.append('button').attr('class', 'button ignore-button action'); // update
104968
104969             buttonSection = buttonSection.merge(buttonEnter);
104970             buttonSection.select('.comment-button').attr('disabled', function (d) {
104971               return d.newComment ? null : true;
104972             }).on('click.comment', function (d3_event, d) {
104973               this.blur(); // avoid keeping focus on the button - #4641
104974
104975               var qaService = services.improveOSM;
104976
104977               if (qaService) {
104978                 qaService.postUpdate(d, function (err, item) {
104979                   return dispatch.call('change', item);
104980                 });
104981               }
104982             });
104983             buttonSection.select('.close-button').html(function (d) {
104984               var andComment = d.newComment ? '_comment' : '';
104985               return _t.html("QA.keepRight.close".concat(andComment));
104986             }).on('click.close', function (d3_event, d) {
104987               this.blur(); // avoid keeping focus on the button - #4641
104988
104989               var qaService = services.improveOSM;
104990
104991               if (qaService) {
104992                 d.newStatus = 'SOLVED';
104993                 qaService.postUpdate(d, function (err, item) {
104994                   return dispatch.call('change', item);
104995                 });
104996               }
104997             });
104998             buttonSection.select('.ignore-button').html(function (d) {
104999               var andComment = d.newComment ? '_comment' : '';
105000               return _t.html("QA.keepRight.ignore".concat(andComment));
105001             }).on('click.ignore', function (d3_event, d) {
105002               this.blur(); // avoid keeping focus on the button - #4641
105003
105004               var qaService = services.improveOSM;
105005
105006               if (qaService) {
105007                 d.newStatus = 'INVALID';
105008                 qaService.postUpdate(d, function (err, item) {
105009                   return dispatch.call('change', item);
105010                 });
105011               }
105012             });
105013           } // NOTE: Don't change method name until UI v3 is merged
105014
105015
105016           improveOsmEditor.error = function (val) {
105017             if (!arguments.length) return _qaItem;
105018             _qaItem = val;
105019             return improveOsmEditor;
105020           };
105021
105022           return utilRebind(improveOsmEditor, dispatch, 'on');
105023         }
105024
105025         function uiPresetList(context) {
105026           var dispatch = dispatch$8('cancel', 'choose');
105027
105028           var _entityIDs;
105029
105030           var _currLoc;
105031
105032           var _currentPresets;
105033
105034           var _autofocus = false;
105035
105036           function presetList(selection) {
105037             if (!_entityIDs) return;
105038             var presets = _mainPresetIndex.matchAllGeometry(entityGeometries());
105039             selection.html('');
105040             var messagewrap = selection.append('div').attr('class', 'header fillL');
105041             var message = messagewrap.append('h2').call(_t.append('inspector.choose'));
105042             var direction = _mainLocalizer.textDirection() === 'rtl' ? 'backward' : 'forward';
105043             messagewrap.append('button').attr('class', 'preset-choose').attr('title', direction).on('click', function () {
105044               dispatch.call('cancel', this);
105045             }).call(svgIcon("#iD-icon-".concat(direction)));
105046
105047             function initialKeydown(d3_event) {
105048               // hack to let delete shortcut work when search is autofocused
105049               if (search.property('value').length === 0 && (d3_event.keyCode === utilKeybinding.keyCodes['⌫'] || d3_event.keyCode === utilKeybinding.keyCodes['⌦'])) {
105050                 d3_event.preventDefault();
105051                 d3_event.stopPropagation();
105052                 operationDelete(context, _entityIDs)(); // hack to let undo work when search is autofocused
105053               } else if (search.property('value').length === 0 && (d3_event.ctrlKey || d3_event.metaKey) && d3_event.keyCode === utilKeybinding.keyCodes.z) {
105054                 d3_event.preventDefault();
105055                 d3_event.stopPropagation();
105056                 context.undo();
105057               } else if (!d3_event.ctrlKey && !d3_event.metaKey) {
105058                 // don't check for delete/undo hack on future keydown events
105059                 select(this).on('keydown', keydown);
105060                 keydown.call(this, d3_event);
105061               }
105062             }
105063
105064             function keydown(d3_event) {
105065               // down arrow
105066               if (d3_event.keyCode === utilKeybinding.keyCodes['↓'] && // if insertion point is at the end of the string
105067               search.node().selectionStart === search.property('value').length) {
105068                 d3_event.preventDefault();
105069                 d3_event.stopPropagation(); // move focus to the first item in the preset list
105070
105071                 var buttons = list.selectAll('.preset-list-button');
105072                 if (!buttons.empty()) buttons.nodes()[0].focus();
105073               }
105074             }
105075
105076             function keypress(d3_event) {
105077               // enter
105078               var value = search.property('value');
105079
105080               if (d3_event.keyCode === 13 && // ↩ Return
105081               value.length) {
105082                 list.selectAll('.preset-list-item:first-child').each(function (d) {
105083                   d.choose.call(this);
105084                 });
105085               }
105086             }
105087
105088             function inputevent() {
105089               var value = search.property('value');
105090               list.classed('filtered', value.length);
105091               var results, messageText;
105092
105093               if (value.length) {
105094                 results = presets.search(value, entityGeometries()[0], _currLoc);
105095                 messageText = _t.html('inspector.results', {
105096                   n: results.collection.length,
105097                   search: value
105098                 });
105099               } else {
105100                 results = _mainPresetIndex.defaults(entityGeometries()[0], 36, !context.inIntro(), _currLoc);
105101                 messageText = _t.html('inspector.choose');
105102               }
105103
105104               list.call(drawList, results);
105105               message.html(messageText);
105106             }
105107
105108             var searchWrap = selection.append('div').attr('class', 'search-header');
105109             searchWrap.call(svgIcon('#iD-icon-search', 'pre-text'));
105110             var search = searchWrap.append('input').attr('class', 'preset-search-input').attr('placeholder', _t('inspector.search')).attr('type', 'search').call(utilNoAuto).on('keydown', initialKeydown).on('keypress', keypress).on('input', debounce(inputevent));
105111
105112             if (_autofocus) {
105113               search.node().focus(); // Safari 14 doesn't always like to focus immediately,
105114               // so try again on the next pass
105115
105116               setTimeout(function () {
105117                 search.node().focus();
105118               }, 0);
105119             }
105120
105121             var listWrap = selection.append('div').attr('class', 'inspector-body');
105122             var list = listWrap.append('div').attr('class', 'preset-list').call(drawList, _mainPresetIndex.defaults(entityGeometries()[0], 36, !context.inIntro(), _currLoc));
105123             context.features().on('change.preset-list', updateForFeatureHiddenState);
105124           }
105125
105126           function drawList(list, presets) {
105127             presets = presets.matchAllGeometry(entityGeometries());
105128             var collection = presets.collection.reduce(function (collection, preset) {
105129               if (!preset) return collection;
105130
105131               if (preset.members) {
105132                 if (preset.members.collection.filter(function (preset) {
105133                   return preset.addable();
105134                 }).length > 1) {
105135                   collection.push(CategoryItem(preset));
105136                 }
105137               } else if (preset.addable()) {
105138                 collection.push(PresetItem(preset));
105139               }
105140
105141               return collection;
105142             }, []);
105143             var items = list.selectAll('.preset-list-item').data(collection, function (d) {
105144               return d.preset.id;
105145             });
105146             items.order();
105147             items.exit().remove();
105148             items.enter().append('div').attr('class', function (item) {
105149               return 'preset-list-item preset-' + item.preset.id.replace('/', '-');
105150             }).classed('current', function (item) {
105151               return _currentPresets.indexOf(item.preset) !== -1;
105152             }).each(function (item) {
105153               select(this).call(item);
105154             }).style('opacity', 0).transition().style('opacity', 1);
105155             updateForFeatureHiddenState();
105156           }
105157
105158           function itemKeydown(d3_event) {
105159             // the actively focused item
105160             var item = select(this.closest('.preset-list-item'));
105161             var parentItem = select(item.node().parentNode.closest('.preset-list-item')); // arrow down, move focus to the next, lower item
105162
105163             if (d3_event.keyCode === utilKeybinding.keyCodes['↓']) {
105164               d3_event.preventDefault();
105165               d3_event.stopPropagation(); // the next item in the list at the same level
105166
105167               var nextItem = select(item.node().nextElementSibling); // if there is no next item in this list
105168
105169               if (nextItem.empty()) {
105170                 // if there is a parent item
105171                 if (!parentItem.empty()) {
105172                   // the item is the last item of a sublist,
105173                   // select the next item at the parent level
105174                   nextItem = select(parentItem.node().nextElementSibling);
105175                 } // if the focused item is expanded
105176
105177               } else if (select(this).classed('expanded')) {
105178                 // select the first subitem instead
105179                 nextItem = item.select('.subgrid .preset-list-item:first-child');
105180               }
105181
105182               if (!nextItem.empty()) {
105183                 // focus on the next item
105184                 nextItem.select('.preset-list-button').node().focus();
105185               } // arrow up, move focus to the previous, higher item
105186
105187             } else if (d3_event.keyCode === utilKeybinding.keyCodes['↑']) {
105188               d3_event.preventDefault();
105189               d3_event.stopPropagation(); // the previous item in the list at the same level
105190
105191               var previousItem = select(item.node().previousElementSibling); // if there is no previous item in this list
105192
105193               if (previousItem.empty()) {
105194                 // if there is a parent item
105195                 if (!parentItem.empty()) {
105196                   // the item is the first subitem of a sublist select the parent item
105197                   previousItem = parentItem;
105198                 } // if the previous item is expanded
105199
105200               } else if (previousItem.select('.preset-list-button').classed('expanded')) {
105201                 // select the last subitem of the sublist of the previous item
105202                 previousItem = previousItem.select('.subgrid .preset-list-item:last-child');
105203               }
105204
105205               if (!previousItem.empty()) {
105206                 // focus on the previous item
105207                 previousItem.select('.preset-list-button').node().focus();
105208               } else {
105209                 // the focus is at the top of the list, move focus back to the search field
105210                 var search = select(this.closest('.preset-list-pane')).select('.preset-search-input');
105211                 search.node().focus();
105212               } // arrow left, move focus to the parent item if there is one
105213
105214             } else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '→' : '←']) {
105215               d3_event.preventDefault();
105216               d3_event.stopPropagation(); // if there is a parent item, focus on the parent item
105217
105218               if (!parentItem.empty()) {
105219                 parentItem.select('.preset-list-button').node().focus();
105220               } // arrow right, choose this item
105221
105222             } else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '←' : '→']) {
105223               d3_event.preventDefault();
105224               d3_event.stopPropagation();
105225               item.datum().choose.call(select(this).node());
105226             }
105227           }
105228
105229           function CategoryItem(preset) {
105230             var box,
105231                 sublist,
105232                 shown = false;
105233
105234             function item(selection) {
105235               var wrap = selection.append('div').attr('class', 'preset-list-button-wrap category');
105236
105237               function click() {
105238                 var isExpanded = select(this).classed('expanded');
105239                 var iconName = isExpanded ? _mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward' : '#iD-icon-down';
105240                 select(this).classed('expanded', !isExpanded).attr('title', !isExpanded ? _t('icons.collapse') : _t('icons.expand'));
105241                 select(this).selectAll('div.label-inner svg.icon use').attr('href', iconName);
105242                 item.choose();
105243               }
105244
105245               var geometries = entityGeometries();
105246               var button = wrap.append('button').attr('class', 'preset-list-button').attr('title', _t('icons.expand')).classed('expanded', false).call(uiPresetIcon().geometry(geometries.length === 1 && geometries[0]).preset(preset)).on('click', click).on('keydown', function (d3_event) {
105247                 // right arrow, expand the focused item
105248                 if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '←' : '→']) {
105249                   d3_event.preventDefault();
105250                   d3_event.stopPropagation(); // if the item isn't expanded
105251
105252                   if (!select(this).classed('expanded')) {
105253                     // toggle expansion (expand the item)
105254                     click.call(this, d3_event);
105255                   } // left arrow, collapse the focused item
105256
105257                 } else if (d3_event.keyCode === utilKeybinding.keyCodes[_mainLocalizer.textDirection() === 'rtl' ? '→' : '←']) {
105258                   d3_event.preventDefault();
105259                   d3_event.stopPropagation(); // if the item is expanded
105260
105261                   if (select(this).classed('expanded')) {
105262                     // toggle expansion (collapse the item)
105263                     click.call(this, d3_event);
105264                   }
105265                 } else {
105266                   itemKeydown.call(this, d3_event);
105267                 }
105268               });
105269               var label = button.append('div').attr('class', 'label').append('div').attr('class', 'label-inner');
105270               label.append('div').attr('class', 'namepart').call(svgIcon(_mainLocalizer.textDirection() === 'rtl' ? '#iD-icon-backward' : '#iD-icon-forward', 'inline')).append('span').html(function () {
105271                 return preset.nameLabel() + '&hellip;';
105272               });
105273               box = selection.append('div').attr('class', 'subgrid').style('max-height', '0px').style('opacity', 0);
105274               box.append('div').attr('class', 'arrow');
105275               sublist = box.append('div').attr('class', 'preset-list fillL3');
105276             }
105277
105278             item.choose = function () {
105279               if (!box || !sublist) return;
105280
105281               if (shown) {
105282                 shown = false;
105283                 box.transition().duration(200).style('opacity', '0').style('max-height', '0px').style('padding-bottom', '0px');
105284               } else {
105285                 shown = true;
105286                 var members = preset.members.matchAllGeometry(entityGeometries());
105287                 sublist.call(drawList, members);
105288                 box.transition().duration(200).style('opacity', '1').style('max-height', 200 + members.collection.length * 190 + 'px').style('padding-bottom', '10px');
105289               }
105290             };
105291
105292             item.preset = preset;
105293             return item;
105294           }
105295
105296           function PresetItem(preset) {
105297             function item(selection) {
105298               var wrap = selection.append('div').attr('class', 'preset-list-button-wrap');
105299               var geometries = entityGeometries();
105300               var button = wrap.append('button').attr('class', 'preset-list-button').call(uiPresetIcon().geometry(geometries.length === 1 && geometries[0]).preset(preset)).on('click', item.choose).on('keydown', itemKeydown);
105301               var label = button.append('div').attr('class', 'label').append('div').attr('class', 'label-inner');
105302               var nameparts = [preset.nameLabel(), preset.subtitleLabel()].filter(Boolean);
105303               label.selectAll('.namepart').data(nameparts).enter().append('div').attr('class', 'namepart').html(function (d) {
105304                 return d;
105305               });
105306               wrap.call(item.reference.button);
105307               selection.call(item.reference.body);
105308             }
105309
105310             item.choose = function () {
105311               if (select(this).classed('disabled')) return;
105312
105313               if (!context.inIntro()) {
105314                 _mainPresetIndex.setMostRecent(preset, entityGeometries()[0]);
105315               }
105316
105317               context.perform(function (graph) {
105318                 for (var i in _entityIDs) {
105319                   var entityID = _entityIDs[i];
105320                   var oldPreset = _mainPresetIndex.match(graph.entity(entityID), graph);
105321                   graph = actionChangePreset(entityID, oldPreset, preset)(graph);
105322                 }
105323
105324                 return graph;
105325               }, _t('operations.change_tags.annotation'));
105326               context.validator().validate(); // rerun validation
105327
105328               dispatch.call('choose', this, preset);
105329             };
105330
105331             item.help = function (d3_event) {
105332               d3_event.stopPropagation();
105333               item.reference.toggle();
105334             };
105335
105336             item.preset = preset;
105337             item.reference = uiTagReference(preset.reference());
105338             return item;
105339           }
105340
105341           function updateForFeatureHiddenState() {
105342             if (!_entityIDs.every(context.hasEntity)) return;
105343             var geometries = entityGeometries();
105344             var button = context.container().selectAll('.preset-list .preset-list-button'); // remove existing tooltips
105345
105346             button.call(uiTooltip().destroyAny);
105347             button.each(function (item, index) {
105348               var hiddenPresetFeaturesId;
105349
105350               for (var i in geometries) {
105351                 hiddenPresetFeaturesId = context.features().isHiddenPreset(item.preset, geometries[i]);
105352                 if (hiddenPresetFeaturesId) break;
105353               }
105354
105355               var isHiddenPreset = !context.inIntro() && !!hiddenPresetFeaturesId && (_currentPresets.length !== 1 || item.preset !== _currentPresets[0]);
105356               select(this).classed('disabled', isHiddenPreset);
105357
105358               if (isHiddenPreset) {
105359                 var isAutoHidden = context.features().autoHidden(hiddenPresetFeaturesId);
105360                 select(this).call(uiTooltip().title(_t.html('inspector.hidden_preset.' + (isAutoHidden ? 'zoom' : 'manual'), {
105361                   features: {
105362                     html: _t.html('feature.' + hiddenPresetFeaturesId + '.description')
105363                   }
105364                 })).placement(index < 2 ? 'bottom' : 'top'));
105365               }
105366             });
105367           }
105368
105369           presetList.autofocus = function (val) {
105370             if (!arguments.length) return _autofocus;
105371             _autofocus = val;
105372             return presetList;
105373           };
105374
105375           presetList.entityIDs = function (val) {
105376             if (!arguments.length) return _entityIDs;
105377             _entityIDs = val;
105378             _currLoc = null;
105379
105380             if (_entityIDs && _entityIDs.length) {
105381               // calculate current location
105382               var extent = _entityIDs.reduce(function (extent, entityID) {
105383                 var entity = context.graph().entity(entityID);
105384                 return extent.extend(entity.extent(context.graph()));
105385               }, geoExtent());
105386
105387               _currLoc = extent.center(); // match presets
105388
105389               var presets = _entityIDs.map(function (entityID) {
105390                 return _mainPresetIndex.match(context.entity(entityID), context.graph());
105391               });
105392
105393               presetList.presets(presets);
105394             }
105395
105396             return presetList;
105397           };
105398
105399           presetList.presets = function (val) {
105400             if (!arguments.length) return _currentPresets;
105401             _currentPresets = val;
105402             return presetList;
105403           };
105404
105405           function entityGeometries() {
105406             var counts = {};
105407
105408             for (var i in _entityIDs) {
105409               var entityID = _entityIDs[i];
105410               var entity = context.entity(entityID);
105411               var geometry = entity.geometry(context.graph()); // Treat entities on addr:interpolation lines as points, not vertices (#3241)
105412
105413               if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
105414                 geometry = 'point';
105415               }
105416
105417               if (!counts[geometry]) counts[geometry] = 0;
105418               counts[geometry] += 1;
105419             }
105420
105421             return Object.keys(counts).sort(function (geom1, geom2) {
105422               return counts[geom2] - counts[geom1];
105423             });
105424           }
105425
105426           return utilRebind(presetList, dispatch, 'on');
105427         }
105428
105429         function uiViewOnOSM(context) {
105430           var _what; // an osmEntity or osmNote
105431
105432
105433           function viewOnOSM(selection) {
105434             var url;
105435
105436             if (_what instanceof osmEntity) {
105437               url = context.connection().entityURL(_what);
105438             } else if (_what instanceof osmNote) {
105439               url = context.connection().noteURL(_what);
105440             }
105441
105442             var data = !_what || _what.isNew() ? [] : [_what];
105443             var link = selection.selectAll('.view-on-osm').data(data, function (d) {
105444               return d.id;
105445             }); // exit
105446
105447             link.exit().remove(); // enter
105448
105449             var linkEnter = link.enter().append('a').attr('class', 'view-on-osm').attr('target', '_blank').attr('href', url).call(svgIcon('#iD-icon-out-link', 'inline'));
105450             linkEnter.append('span').call(_t.append('inspector.view_on_osm'));
105451           }
105452
105453           viewOnOSM.what = function (_) {
105454             if (!arguments.length) return _what;
105455             _what = _;
105456             return viewOnOSM;
105457           };
105458
105459           return viewOnOSM;
105460         }
105461
105462         function uiInspector(context) {
105463           var presetList = uiPresetList(context);
105464           var entityEditor = uiEntityEditor(context);
105465           var wrap = select(null),
105466               presetPane = select(null),
105467               editorPane = select(null);
105468           var _state = 'select';
105469
105470           var _entityIDs;
105471
105472           var _newFeature = false;
105473
105474           function inspector(selection) {
105475             presetList.entityIDs(_entityIDs).autofocus(_newFeature).on('choose', inspector.setPreset).on('cancel', function () {
105476               inspector.setPreset();
105477             });
105478             entityEditor.state(_state).entityIDs(_entityIDs).on('choose', inspector.showList);
105479             wrap = selection.selectAll('.panewrap').data([0]);
105480             var enter = wrap.enter().append('div').attr('class', 'panewrap');
105481             enter.append('div').attr('class', 'preset-list-pane pane');
105482             enter.append('div').attr('class', 'entity-editor-pane pane');
105483             wrap = wrap.merge(enter);
105484             presetPane = wrap.selectAll('.preset-list-pane');
105485             editorPane = wrap.selectAll('.entity-editor-pane');
105486
105487             function shouldDefaultToPresetList() {
105488               // always show the inspector on hover
105489               if (_state !== 'select') return false; // can only change preset on single selection
105490
105491               if (_entityIDs.length !== 1) return false;
105492               var entityID = _entityIDs[0];
105493               var entity = context.hasEntity(entityID);
105494               if (!entity) return false; // default to inspector if there are already tags
105495
105496               if (entity.hasNonGeometryTags()) return false; // prompt to select preset if feature is new and untagged
105497
105498               if (_newFeature) return true; // all existing features except vertices should default to inspector
105499
105500               if (entity.geometry(context.graph()) !== 'vertex') return false; // show vertex relations if any
105501
105502               if (context.graph().parentRelations(entity).length) return false; // show vertex issues if there are any
105503
105504               if (context.validator().getEntityIssues(entityID).length) return false; // show turn retriction editor for junction vertices
105505
105506               if (entity.isHighwayIntersection(context.graph())) return false; // otherwise show preset list for uninteresting vertices
105507
105508               return true;
105509             }
105510
105511             if (shouldDefaultToPresetList()) {
105512               wrap.style('right', '-100%');
105513               editorPane.classed('hide', true);
105514               presetPane.classed('hide', false).call(presetList);
105515             } else {
105516               wrap.style('right', '0%');
105517               presetPane.classed('hide', true);
105518               editorPane.classed('hide', false).call(entityEditor);
105519             }
105520
105521             var footer = selection.selectAll('.footer').data([0]);
105522             footer = footer.enter().append('div').attr('class', 'footer').merge(footer);
105523             footer.call(uiViewOnOSM(context).what(context.hasEntity(_entityIDs.length === 1 && _entityIDs[0])));
105524           }
105525
105526           inspector.showList = function (presets) {
105527             presetPane.classed('hide', false);
105528             wrap.transition().styleTween('right', function () {
105529               return interpolate$1('0%', '-100%');
105530             }).on('end', function () {
105531               editorPane.classed('hide', true);
105532             });
105533
105534             if (presets) {
105535               presetList.presets(presets);
105536             }
105537
105538             presetPane.call(presetList.autofocus(true));
105539           };
105540
105541           inspector.setPreset = function (preset) {
105542             // upon setting multipolygon, go to the area preset list instead of the editor
105543             if (preset && preset.id === 'type/multipolygon') {
105544               presetPane.call(presetList.autofocus(true));
105545             } else {
105546               editorPane.classed('hide', false);
105547               wrap.transition().styleTween('right', function () {
105548                 return interpolate$1('-100%', '0%');
105549               }).on('end', function () {
105550                 presetPane.classed('hide', true);
105551               });
105552
105553               if (preset) {
105554                 entityEditor.presets([preset]);
105555               }
105556
105557               editorPane.call(entityEditor);
105558             }
105559           };
105560
105561           inspector.state = function (val) {
105562             if (!arguments.length) return _state;
105563             _state = val;
105564             entityEditor.state(_state); // remove any old field help overlay that might have gotten attached to the inspector
105565
105566             context.container().selectAll('.field-help-body').remove();
105567             return inspector;
105568           };
105569
105570           inspector.entityIDs = function (val) {
105571             if (!arguments.length) return _entityIDs;
105572             _entityIDs = val;
105573             return inspector;
105574           };
105575
105576           inspector.newFeature = function (val) {
105577             if (!arguments.length) return _newFeature;
105578             _newFeature = val;
105579             return inspector;
105580           };
105581
105582           return inspector;
105583         }
105584
105585         function uiKeepRightDetails(context) {
105586           var _qaItem;
105587
105588           function issueDetail(d) {
105589             var itemType = d.itemType,
105590                 parentIssueType = d.parentIssueType;
105591             var unknown = {
105592               html: _t.html('inspector.unknown')
105593             };
105594             var replacements = d.replacements || {};
105595             replacements["default"] = unknown; // special key `default` works as a fallback string
105596
105597             var detail = _t.html("QA.keepRight.errorTypes.".concat(itemType, ".description"), replacements);
105598
105599             if (detail === unknown.html) {
105600               detail = _t.html("QA.keepRight.errorTypes.".concat(parentIssueType, ".description"), replacements);
105601             }
105602
105603             return detail;
105604           }
105605
105606           function keepRightDetails(selection) {
105607             var details = selection.selectAll('.error-details').data(_qaItem ? [_qaItem] : [], function (d) {
105608               return "".concat(d.id, "-").concat(d.status || 0);
105609             });
105610             details.exit().remove();
105611             var detailsEnter = details.enter().append('div').attr('class', 'error-details qa-details-container'); // description
105612
105613             var descriptionEnter = detailsEnter.append('div').attr('class', 'qa-details-subsection');
105614             descriptionEnter.append('h4').call(_t.append('QA.keepRight.detail_description'));
105615             descriptionEnter.append('div').attr('class', 'qa-details-description-text').html(issueDetail); // If there are entity links in the error message..
105616
105617             var relatedEntities = [];
105618             descriptionEnter.selectAll('.error_entity_link, .error_object_link').attr('href', '#').each(function () {
105619               var link = select(this);
105620               var isObjectLink = link.classed('error_object_link');
105621               var entityID = isObjectLink ? utilEntityRoot(_qaItem.objectType) + _qaItem.objectId : this.textContent;
105622               var entity = context.hasEntity(entityID);
105623               relatedEntities.push(entityID); // Add click handler
105624
105625               link.on('mouseenter', function () {
105626                 utilHighlightEntities([entityID], true, context);
105627               }).on('mouseleave', function () {
105628                 utilHighlightEntities([entityID], false, context);
105629               }).on('click', function (d3_event) {
105630                 d3_event.preventDefault();
105631                 utilHighlightEntities([entityID], false, context);
105632                 var osmlayer = context.layers().layer('osm');
105633
105634                 if (!osmlayer.enabled()) {
105635                   osmlayer.enabled(true);
105636                 }
105637
105638                 context.map().centerZoomEase(_qaItem.loc, 20);
105639
105640                 if (entity) {
105641                   context.enter(modeSelect(context, [entityID]));
105642                 } else {
105643                   context.loadEntity(entityID, function (err, result) {
105644                     if (err) return;
105645                     var entity = result.data.find(function (e) {
105646                       return e.id === entityID;
105647                     });
105648                     if (entity) context.enter(modeSelect(context, [entityID]));
105649                   });
105650                 }
105651               }); // Replace with friendly name if possible
105652               // (The entity may not yet be loaded into the graph)
105653
105654               if (entity) {
105655                 var name = utilDisplayName(entity); // try to use common name
105656
105657                 if (!name && !isObjectLink) {
105658                   var preset = _mainPresetIndex.match(entity, context.graph());
105659                   name = preset && !preset.isFallback() && preset.name(); // fallback to preset name
105660                 }
105661
105662                 if (name) {
105663                   this.innerText = name;
105664                 }
105665               }
105666             }); // Don't hide entities related to this issue - #5880
105667
105668             context.features().forceVisible(relatedEntities);
105669             context.map().pan([0, 0]); // trigger a redraw
105670           }
105671
105672           keepRightDetails.issue = function (val) {
105673             if (!arguments.length) return _qaItem;
105674             _qaItem = val;
105675             return keepRightDetails;
105676           };
105677
105678           return keepRightDetails;
105679         }
105680
105681         function uiKeepRightHeader() {
105682           var _qaItem;
105683
105684           function issueTitle(d) {
105685             var itemType = d.itemType,
105686                 parentIssueType = d.parentIssueType;
105687             var unknown = _t.html('inspector.unknown');
105688             var replacements = d.replacements || {};
105689             replacements["default"] = {
105690               html: unknown
105691             }; // special key `default` works as a fallback string
105692
105693             var title = _t.html("QA.keepRight.errorTypes.".concat(itemType, ".title"), replacements);
105694
105695             if (title !== unknown) {
105696               return _t.apply("QA.keepRight.errorTypes.".concat(itemType, ".title"), replacements);
105697             } else {
105698               return _t.apply("QA.keepRight.errorTypes.".concat(parentIssueType, ".title"), replacements);
105699             }
105700           }
105701
105702           function keepRightHeader(selection) {
105703             var header = selection.selectAll('.qa-header').data(_qaItem ? [_qaItem] : [], function (d) {
105704               return "".concat(d.id, "-").concat(d.status || 0);
105705             });
105706             header.exit().remove();
105707             var headerEnter = header.enter().append('div').attr('class', 'qa-header');
105708             var iconEnter = headerEnter.append('div').attr('class', 'qa-header-icon').classed('new', function (d) {
105709               return d.id < 0;
105710             });
105711             iconEnter.append('div').attr('class', function (d) {
105712               return "preset-icon-28 qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.parentIssueType);
105713             }).call(svgIcon('#iD-icon-bolt', 'qaItem-fill'));
105714             headerEnter.append('div').attr('class', 'qa-header-label').html(issueTitle);
105715           }
105716
105717           keepRightHeader.issue = function (val) {
105718             if (!arguments.length) return _qaItem;
105719             _qaItem = val;
105720             return keepRightHeader;
105721           };
105722
105723           return keepRightHeader;
105724         }
105725
105726         function uiViewOnKeepRight() {
105727           var _qaItem;
105728
105729           function viewOnKeepRight(selection) {
105730             var url;
105731
105732             if (services.keepRight && _qaItem instanceof QAItem) {
105733               url = services.keepRight.issueURL(_qaItem);
105734             }
105735
105736             var link = selection.selectAll('.view-on-keepRight').data(url ? [url] : []); // exit
105737
105738             link.exit().remove(); // enter
105739
105740             var linkEnter = link.enter().append('a').attr('class', 'view-on-keepRight').attr('target', '_blank').attr('rel', 'noopener') // security measure
105741             .attr('href', function (d) {
105742               return d;
105743             }).call(svgIcon('#iD-icon-out-link', 'inline'));
105744             linkEnter.append('span').call(_t.append('inspector.view_on_keepRight'));
105745           }
105746
105747           viewOnKeepRight.what = function (val) {
105748             if (!arguments.length) return _qaItem;
105749             _qaItem = val;
105750             return viewOnKeepRight;
105751           };
105752
105753           return viewOnKeepRight;
105754         }
105755
105756         function uiKeepRightEditor(context) {
105757           var dispatch = dispatch$8('change');
105758           var qaDetails = uiKeepRightDetails(context);
105759           var qaHeader = uiKeepRightHeader();
105760
105761           var _qaItem;
105762
105763           function keepRightEditor(selection) {
105764             var headerEnter = selection.selectAll('.header').data([0]).enter().append('div').attr('class', 'header fillL');
105765             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
105766               return context.enter(modeBrowse(context));
105767             }).call(svgIcon('#iD-icon-close'));
105768             headerEnter.append('h2').call(_t.append('QA.keepRight.title'));
105769             var body = selection.selectAll('.body').data([0]);
105770             body = body.enter().append('div').attr('class', 'body').merge(body);
105771             var editor = body.selectAll('.qa-editor').data([0]);
105772             editor.enter().append('div').attr('class', 'modal-section qa-editor').merge(editor).call(qaHeader.issue(_qaItem)).call(qaDetails.issue(_qaItem)).call(keepRightSaveSection);
105773             var footer = selection.selectAll('.footer').data([0]);
105774             footer.enter().append('div').attr('class', 'footer').merge(footer).call(uiViewOnKeepRight().what(_qaItem));
105775           }
105776
105777           function keepRightSaveSection(selection) {
105778             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
105779
105780             var isShown = _qaItem && (isSelected || _qaItem.newComment || _qaItem.comment);
105781             var saveSection = selection.selectAll('.qa-save').data(isShown ? [_qaItem] : [], function (d) {
105782               return "".concat(d.id, "-").concat(d.status || 0);
105783             }); // exit
105784
105785             saveSection.exit().remove(); // enter
105786
105787             var saveSectionEnter = saveSection.enter().append('div').attr('class', 'qa-save save-section cf');
105788             saveSectionEnter.append('h4').attr('class', '.qa-save-header').call(_t.append('QA.keepRight.comment'));
105789             saveSectionEnter.append('textarea').attr('class', 'new-comment-input').attr('placeholder', _t('QA.keepRight.comment_placeholder')).attr('maxlength', 1000).property('value', function (d) {
105790               return d.newComment || d.comment;
105791             }).call(utilNoAuto).on('input', changeInput).on('blur', changeInput); // update
105792
105793             saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
105794
105795             function changeInput() {
105796               var input = select(this);
105797               var val = input.property('value').trim();
105798
105799               if (val === _qaItem.comment) {
105800                 val = undefined;
105801               } // store the unsaved comment with the issue itself
105802
105803
105804               _qaItem = _qaItem.update({
105805                 newComment: val
105806               });
105807               var qaService = services.keepRight;
105808
105809               if (qaService) {
105810                 qaService.replaceItem(_qaItem); // update keepright cache
105811               }
105812
105813               saveSection.call(qaSaveButtons);
105814             }
105815           }
105816
105817           function qaSaveButtons(selection) {
105818             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
105819
105820             var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_qaItem] : [], function (d) {
105821               return d.status + d.id;
105822             }); // exit
105823
105824             buttonSection.exit().remove(); // enter
105825
105826             var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
105827             buttonEnter.append('button').attr('class', 'button comment-button action').call(_t.append('QA.keepRight.save_comment'));
105828             buttonEnter.append('button').attr('class', 'button close-button action');
105829             buttonEnter.append('button').attr('class', 'button ignore-button action'); // update
105830
105831             buttonSection = buttonSection.merge(buttonEnter);
105832             buttonSection.select('.comment-button') // select and propagate data
105833             .attr('disabled', function (d) {
105834               return d.newComment ? null : true;
105835             }).on('click.comment', function (d3_event, d) {
105836               this.blur(); // avoid keeping focus on the button - #4641
105837
105838               var qaService = services.keepRight;
105839
105840               if (qaService) {
105841                 qaService.postUpdate(d, function (err, item) {
105842                   return dispatch.call('change', item);
105843                 });
105844               }
105845             });
105846             buttonSection.select('.close-button') // select and propagate data
105847             .html(function (d) {
105848               var andComment = d.newComment ? '_comment' : '';
105849               return _t.html("QA.keepRight.close".concat(andComment));
105850             }).on('click.close', function (d3_event, d) {
105851               this.blur(); // avoid keeping focus on the button - #4641
105852
105853               var qaService = services.keepRight;
105854
105855               if (qaService) {
105856                 d.newStatus = 'ignore_t'; // ignore temporarily (item fixed)
105857
105858                 qaService.postUpdate(d, function (err, item) {
105859                   return dispatch.call('change', item);
105860                 });
105861               }
105862             });
105863             buttonSection.select('.ignore-button') // select and propagate data
105864             .html(function (d) {
105865               var andComment = d.newComment ? '_comment' : '';
105866               return _t.html("QA.keepRight.ignore".concat(andComment));
105867             }).on('click.ignore', function (d3_event, d) {
105868               this.blur(); // avoid keeping focus on the button - #4641
105869
105870               var qaService = services.keepRight;
105871
105872               if (qaService) {
105873                 d.newStatus = 'ignore'; // ignore permanently (false positive)
105874
105875                 qaService.postUpdate(d, function (err, item) {
105876                   return dispatch.call('change', item);
105877                 });
105878               }
105879             });
105880           } // NOTE: Don't change method name until UI v3 is merged
105881
105882
105883           keepRightEditor.error = function (val) {
105884             if (!arguments.length) return _qaItem;
105885             _qaItem = val;
105886             return keepRightEditor;
105887           };
105888
105889           return utilRebind(keepRightEditor, dispatch, 'on');
105890         }
105891
105892         function uiLasso(context) {
105893           var group, polygon;
105894           lasso.coordinates = [];
105895
105896           function lasso(selection) {
105897             context.container().classed('lasso', true);
105898             group = selection.append('g').attr('class', 'lasso hide');
105899             polygon = group.append('path').attr('class', 'lasso-path');
105900             group.call(uiToggle(true));
105901           }
105902
105903           function draw() {
105904             if (polygon) {
105905               polygon.data([lasso.coordinates]).attr('d', function (d) {
105906                 return 'M' + d.join(' L') + ' Z';
105907               });
105908             }
105909           }
105910
105911           lasso.extent = function () {
105912             return lasso.coordinates.reduce(function (extent, point) {
105913               return extent.extend(geoExtent(point));
105914             }, geoExtent());
105915           };
105916
105917           lasso.p = function (_) {
105918             if (!arguments.length) return lasso;
105919             lasso.coordinates.push(_);
105920             draw();
105921             return lasso;
105922           };
105923
105924           lasso.close = function () {
105925             if (group) {
105926               group.call(uiToggle(false, function () {
105927                 select(this).remove();
105928               }));
105929             }
105930
105931             context.container().classed('lasso', false);
105932           };
105933
105934           return lasso;
105935         }
105936
105937         function uiNoteComments() {
105938           var _note;
105939
105940           function noteComments(selection) {
105941             if (_note.isNew()) return; // don't draw .comments-container
105942
105943             var comments = selection.selectAll('.comments-container').data([0]);
105944             comments = comments.enter().append('div').attr('class', 'comments-container').merge(comments);
105945             var commentEnter = comments.selectAll('.comment').data(_note.comments).enter().append('div').attr('class', 'comment');
105946             commentEnter.append('div').attr('class', function (d) {
105947               return 'comment-avatar user-' + d.uid;
105948             }).call(svgIcon('#iD-icon-avatar', 'comment-avatar-icon'));
105949             var mainEnter = commentEnter.append('div').attr('class', 'comment-main');
105950             var metadataEnter = mainEnter.append('div').attr('class', 'comment-metadata');
105951             metadataEnter.append('div').attr('class', 'comment-author').each(function (d) {
105952               var selection = select(this);
105953               var osm = services.osm;
105954
105955               if (osm && d.user) {
105956                 selection = selection.append('a').attr('class', 'comment-author-link').attr('href', osm.userURL(d.user)).attr('target', '_blank');
105957               }
105958
105959               if (d.user) {
105960                 selection.text(d.user);
105961               } else {
105962                 selection.call(_t.append('note.anonymous'));
105963               }
105964             });
105965             metadataEnter.append('div').attr('class', 'comment-date').html(function (d) {
105966               return _t.html('note.status.' + d.action, {
105967                 when: localeDateString(d.date)
105968               });
105969             });
105970             mainEnter.append('div').attr('class', 'comment-text').html(function (d) {
105971               return d.html;
105972             }).selectAll('a').attr('rel', 'noopener nofollow').attr('target', '_blank');
105973             comments.call(replaceAvatars);
105974           }
105975
105976           function replaceAvatars(selection) {
105977             var showThirdPartyIcons = corePreferences('preferences.privacy.thirdpartyicons') || 'true';
105978             var osm = services.osm;
105979             if (showThirdPartyIcons !== 'true' || !osm) return;
105980             var uids = {}; // gather uids in the comment thread
105981
105982             _note.comments.forEach(function (d) {
105983               if (d.uid) uids[d.uid] = true;
105984             });
105985
105986             Object.keys(uids).forEach(function (uid) {
105987               osm.loadUser(uid, function (err, user) {
105988                 if (!user || !user.image_url) return;
105989                 selection.selectAll('.comment-avatar.user-' + uid).html('').append('img').attr('class', 'icon comment-avatar-icon').attr('src', user.image_url).attr('alt', user.display_name);
105990               });
105991             });
105992           }
105993
105994           function localeDateString(s) {
105995             if (!s) return null;
105996             var options = {
105997               day: 'numeric',
105998               month: 'short',
105999               year: 'numeric'
106000             };
106001             s = s.replace(/-/g, '/'); // fix browser-specific Date() issues
106002
106003             var d = new Date(s);
106004             if (isNaN(d.getTime())) return null;
106005             return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
106006           }
106007
106008           noteComments.note = function (val) {
106009             if (!arguments.length) return _note;
106010             _note = val;
106011             return noteComments;
106012           };
106013
106014           return noteComments;
106015         }
106016
106017         function uiNoteHeader() {
106018           var _note;
106019
106020           function noteHeader(selection) {
106021             var header = selection.selectAll('.note-header').data(_note ? [_note] : [], function (d) {
106022               return d.status + d.id;
106023             });
106024             header.exit().remove();
106025             var headerEnter = header.enter().append('div').attr('class', 'note-header');
106026             var iconEnter = headerEnter.append('div').attr('class', function (d) {
106027               return 'note-header-icon ' + d.status;
106028             }).classed('new', function (d) {
106029               return d.id < 0;
106030             });
106031             iconEnter.append('div').attr('class', 'preset-icon-28').call(svgIcon('#iD-icon-note', 'note-fill'));
106032             iconEnter.each(function (d) {
106033               var statusIcon;
106034
106035               if (d.id < 0) {
106036                 statusIcon = '#iD-icon-plus';
106037               } else if (d.status === 'open') {
106038                 statusIcon = '#iD-icon-close';
106039               } else {
106040                 statusIcon = '#iD-icon-apply';
106041               }
106042
106043               iconEnter.append('div').attr('class', 'note-icon-annotation').attr('title', _t('icons.close')).call(svgIcon(statusIcon, 'icon-annotation'));
106044             });
106045             headerEnter.append('div').attr('class', 'note-header-label').html(function (d) {
106046               if (_note.isNew()) {
106047                 return _t.html('note.new');
106048               }
106049
106050               return _t.html('note.note') + ' ' + d.id + ' ' + (d.status === 'closed' ? _t.html('note.closed') : '');
106051             });
106052           }
106053
106054           noteHeader.note = function (val) {
106055             if (!arguments.length) return _note;
106056             _note = val;
106057             return noteHeader;
106058           };
106059
106060           return noteHeader;
106061         }
106062
106063         function uiNoteReport() {
106064           var _note;
106065
106066           function noteReport(selection) {
106067             var url;
106068
106069             if (services.osm && _note instanceof osmNote && !_note.isNew()) {
106070               url = services.osm.noteReportURL(_note);
106071             }
106072
106073             var link = selection.selectAll('.note-report').data(url ? [url] : []); // exit
106074
106075             link.exit().remove(); // enter
106076
106077             var linkEnter = link.enter().append('a').attr('class', 'note-report').attr('target', '_blank').attr('href', function (d) {
106078               return d;
106079             }).call(svgIcon('#iD-icon-out-link', 'inline'));
106080             linkEnter.append('span').call(_t.append('note.report'));
106081           }
106082
106083           noteReport.note = function (val) {
106084             if (!arguments.length) return _note;
106085             _note = val;
106086             return noteReport;
106087           };
106088
106089           return noteReport;
106090         }
106091
106092         function uiNoteEditor(context) {
106093           var dispatch = dispatch$8('change');
106094           var noteComments = uiNoteComments();
106095           var noteHeader = uiNoteHeader(); // var formFields = uiFormFields(context);
106096
106097           var _note;
106098
106099           var _newNote; // var _fieldsArr;
106100
106101
106102           function noteEditor(selection) {
106103             var header = selection.selectAll('.header').data([0]);
106104             var headerEnter = header.enter().append('div').attr('class', 'header fillL');
106105             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
106106               context.enter(modeBrowse(context));
106107             }).call(svgIcon('#iD-icon-close'));
106108             headerEnter.append('h2').call(_t.append('note.title'));
106109             var body = selection.selectAll('.body').data([0]);
106110             body = body.enter().append('div').attr('class', 'body').merge(body);
106111             var editor = body.selectAll('.note-editor').data([0]);
106112             editor.enter().append('div').attr('class', 'modal-section note-editor').merge(editor).call(noteHeader.note(_note)).call(noteComments.note(_note)).call(noteSaveSection);
106113             var footer = selection.selectAll('.footer').data([0]);
106114             footer.enter().append('div').attr('class', 'footer').merge(footer).call(uiViewOnOSM(context).what(_note)).call(uiNoteReport().note(_note)); // rerender the note editor on any auth change
106115
106116             var osm = services.osm;
106117
106118             if (osm) {
106119               osm.on('change.note-save', function () {
106120                 selection.call(noteEditor);
106121               });
106122             }
106123           }
106124
106125           function noteSaveSection(selection) {
106126             var isSelected = _note && _note.id === context.selectedNoteID();
106127
106128             var noteSave = selection.selectAll('.note-save').data(isSelected ? [_note] : [], function (d) {
106129               return d.status + d.id;
106130             }); // exit
106131
106132             noteSave.exit().remove(); // enter
106133
106134             var noteSaveEnter = noteSave.enter().append('div').attr('class', 'note-save save-section cf'); // // if new note, show categories to pick from
106135             // if (_note.isNew()) {
106136             //     var presets = presetManager;
106137             //     // NOTE: this key isn't a age and therefore there is no documentation (yet)
106138             //     _fieldsArr = [
106139             //         uiField(context, presets.field('category'), null, { show: true, revert: false }),
106140             //     ];
106141             //     _fieldsArr.forEach(function(field) {
106142             //         field
106143             //             .on('change', changeCategory);
106144             //     });
106145             //     noteSaveEnter
106146             //         .append('div')
106147             //         .attr('class', 'note-category')
106148             //         .call(formFields.fieldsArr(_fieldsArr));
106149             // }
106150             // function changeCategory() {
106151             //     // NOTE: perhaps there is a better way to get value
106152             //     var val = context.container().select('input[name=\'category\']:checked').property('__data__') || undefined;
106153             //     // store the unsaved category with the note itself
106154             //     _note = _note.update({ newCategory: val });
106155             //     var osm = services.osm;
106156             //     if (osm) {
106157             //         osm.replaceNote(_note);  // update note cache
106158             //     }
106159             //     noteSave
106160             //         .call(noteSaveButtons);
106161             // }
106162
106163             noteSaveEnter.append('h4').attr('class', '.note-save-header').html(function () {
106164               return _note.isNew() ? _t.html('note.newDescription') : _t.html('note.newComment');
106165             });
106166             var commentTextarea = noteSaveEnter.append('textarea').attr('class', 'new-comment-input').attr('placeholder', _t('note.inputPlaceholder')).attr('maxlength', 1000).property('value', function (d) {
106167               return d.newComment;
106168             }).call(utilNoAuto).on('keydown.note-input', keydown).on('input.note-input', changeInput).on('blur.note-input', changeInput);
106169
106170             if (!commentTextarea.empty() && _newNote) {
106171               // autofocus the comment field for new notes
106172               commentTextarea.node().focus();
106173             } // update
106174
106175
106176             noteSave = noteSaveEnter.merge(noteSave).call(userDetails).call(noteSaveButtons); // fast submit if user presses cmd+enter
106177
106178             function keydown(d3_event) {
106179               if (!(d3_event.keyCode === 13 && // ↩ Return
106180               d3_event.metaKey)) return;
106181               var osm = services.osm;
106182               if (!osm) return;
106183               var hasAuth = osm.authenticated();
106184               if (!hasAuth) return;
106185               if (!_note.newComment) return;
106186               d3_event.preventDefault();
106187               select(this).on('keydown.note-input', null); // focus on button and submit
106188
106189               window.setTimeout(function () {
106190                 if (_note.isNew()) {
106191                   noteSave.selectAll('.save-button').node().focus();
106192                   clickSave();
106193                 } else {
106194                   noteSave.selectAll('.comment-button').node().focus();
106195                   clickComment();
106196                 }
106197               }, 10);
106198             }
106199
106200             function changeInput() {
106201               var input = select(this);
106202               var val = input.property('value').trim() || undefined; // store the unsaved comment with the note itself
106203
106204               _note = _note.update({
106205                 newComment: val
106206               });
106207               var osm = services.osm;
106208
106209               if (osm) {
106210                 osm.replaceNote(_note); // update note cache
106211               }
106212
106213               noteSave.call(noteSaveButtons);
106214             }
106215           }
106216
106217           function userDetails(selection) {
106218             var detailSection = selection.selectAll('.detail-section').data([0]);
106219             detailSection = detailSection.enter().append('div').attr('class', 'detail-section').merge(detailSection);
106220             var osm = services.osm;
106221             if (!osm) return; // Add warning if user is not logged in
106222
106223             var hasAuth = osm.authenticated();
106224             var authWarning = detailSection.selectAll('.auth-warning').data(hasAuth ? [] : [0]);
106225             authWarning.exit().transition().duration(200).style('opacity', 0).remove();
106226             var authEnter = authWarning.enter().insert('div', '.tag-reference-body').attr('class', 'field-warning auth-warning').style('opacity', 0);
106227             authEnter.call(svgIcon('#iD-icon-alert', 'inline'));
106228             authEnter.append('span').call(_t.append('note.login'));
106229             authEnter.append('a').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).append('span').call(_t.append('login')).on('click.note-login', function (d3_event) {
106230               d3_event.preventDefault();
106231               osm.authenticate();
106232             });
106233             authEnter.transition().duration(200).style('opacity', 1);
106234             var prose = detailSection.selectAll('.note-save-prose').data(hasAuth ? [0] : []);
106235             prose.exit().remove();
106236             prose = prose.enter().append('p').attr('class', 'note-save-prose').call(_t.append('note.upload_explanation')).merge(prose);
106237             osm.userDetails(function (err, user) {
106238               if (err) return;
106239               var userLink = select(document.createElement('div'));
106240
106241               if (user.image_url) {
106242                 userLink.append('img').attr('src', user.image_url).attr('class', 'icon pre-text user-icon');
106243               }
106244
106245               userLink.append('a').attr('class', 'user-info').text(user.display_name).attr('href', osm.userURL(user.display_name)).attr('target', '_blank');
106246               prose.html(_t.html('note.upload_explanation_with_user', {
106247                 user: {
106248                   html: userLink.html()
106249                 }
106250               }));
106251             });
106252           }
106253
106254           function noteSaveButtons(selection) {
106255             var osm = services.osm;
106256             var hasAuth = osm && osm.authenticated();
106257
106258             var isSelected = _note && _note.id === context.selectedNoteID();
106259
106260             var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_note] : [], function (d) {
106261               return d.status + d.id;
106262             }); // exit
106263
106264             buttonSection.exit().remove(); // enter
106265
106266             var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
106267
106268             if (_note.isNew()) {
106269               buttonEnter.append('button').attr('class', 'button cancel-button secondary-action').call(_t.append('confirm.cancel'));
106270               buttonEnter.append('button').attr('class', 'button save-button action').call(_t.append('note.save'));
106271             } else {
106272               buttonEnter.append('button').attr('class', 'button status-button action');
106273               buttonEnter.append('button').attr('class', 'button comment-button action').call(_t.append('note.comment'));
106274             } // update
106275
106276
106277             buttonSection = buttonSection.merge(buttonEnter);
106278             buttonSection.select('.cancel-button') // select and propagate data
106279             .on('click.cancel', clickCancel);
106280             buttonSection.select('.save-button') // select and propagate data
106281             .attr('disabled', isSaveDisabled).on('click.save', clickSave);
106282             buttonSection.select('.status-button') // select and propagate data
106283             .attr('disabled', hasAuth ? null : true).html(function (d) {
106284               var action = d.status === 'open' ? 'close' : 'open';
106285               var andComment = d.newComment ? '_comment' : '';
106286               return _t.html('note.' + action + andComment);
106287             }).on('click.status', clickStatus);
106288             buttonSection.select('.comment-button') // select and propagate data
106289             .attr('disabled', isSaveDisabled).on('click.comment', clickComment);
106290
106291             function isSaveDisabled(d) {
106292               return hasAuth && d.status === 'open' && d.newComment ? null : true;
106293             }
106294           }
106295
106296           function clickCancel(d3_event, d) {
106297             this.blur(); // avoid keeping focus on the button - #4641
106298
106299             var osm = services.osm;
106300
106301             if (osm) {
106302               osm.removeNote(d);
106303             }
106304
106305             context.enter(modeBrowse(context));
106306             dispatch.call('change');
106307           }
106308
106309           function clickSave(d3_event, d) {
106310             this.blur(); // avoid keeping focus on the button - #4641
106311
106312             var osm = services.osm;
106313
106314             if (osm) {
106315               osm.postNoteCreate(d, function (err, note) {
106316                 dispatch.call('change', note);
106317               });
106318             }
106319           }
106320
106321           function clickStatus(d3_event, d) {
106322             this.blur(); // avoid keeping focus on the button - #4641
106323
106324             var osm = services.osm;
106325
106326             if (osm) {
106327               var setStatus = d.status === 'open' ? 'closed' : 'open';
106328               osm.postNoteUpdate(d, setStatus, function (err, note) {
106329                 dispatch.call('change', note);
106330               });
106331             }
106332           }
106333
106334           function clickComment(d3_event, d) {
106335             this.blur(); // avoid keeping focus on the button - #4641
106336
106337             var osm = services.osm;
106338
106339             if (osm) {
106340               osm.postNoteUpdate(d, d.status, function (err, note) {
106341                 dispatch.call('change', note);
106342               });
106343             }
106344           }
106345
106346           noteEditor.note = function (val) {
106347             if (!arguments.length) return _note;
106348             _note = val;
106349             return noteEditor;
106350           };
106351
106352           noteEditor.newNote = function (val) {
106353             if (!arguments.length) return _newNote;
106354             _newNote = val;
106355             return noteEditor;
106356           };
106357
106358           return utilRebind(noteEditor, dispatch, 'on');
106359         }
106360
106361         function uiSourceSwitch(context) {
106362           var keys;
106363
106364           function click(d3_event) {
106365             d3_event.preventDefault();
106366             var osm = context.connection();
106367             if (!osm) return;
106368             if (context.inIntro()) return;
106369             if (context.history().hasChanges() && !window.confirm(_t('source_switch.lose_changes'))) return;
106370             var isLive = select(this).classed('live');
106371             isLive = !isLive;
106372             context.enter(modeBrowse(context));
106373             context.history().clearSaved(); // remove saved history
106374
106375             context.flush(); // remove stored data
106376
106377             select(this).html(isLive ? _t.html('source_switch.live') : _t.html('source_switch.dev')).classed('live', isLive).classed('chip', isLive);
106378             osm["switch"](isLive ? keys[0] : keys[1]); // switch connection (warning: dispatches 'change' event)
106379           }
106380
106381           var sourceSwitch = function sourceSwitch(selection) {
106382             selection.append('a').attr('href', '#').call(_t.append('source_switch.live')).attr('class', 'live chip').on('click', click);
106383           };
106384
106385           sourceSwitch.keys = function (_) {
106386             if (!arguments.length) return keys;
106387             keys = _;
106388             return sourceSwitch;
106389           };
106390
106391           return sourceSwitch;
106392         }
106393
106394         function uiSpinner(context) {
106395           var osm = context.connection();
106396           return function (selection) {
106397             var img = selection.append('img').attr('src', context.imagePath('loader-black.gif')).style('opacity', 0);
106398
106399             if (osm) {
106400               osm.on('loading.spinner', function () {
106401                 img.transition().style('opacity', 1);
106402               }).on('loaded.spinner', function () {
106403                 img.transition().style('opacity', 0);
106404               });
106405             }
106406           };
106407         }
106408
106409         function uiSectionPrivacy(context) {
106410           var section = uiSection('preferences-third-party', context).label(_t.html('preferences.privacy.title')).disclosureContent(renderDisclosureContent);
106411
106412           function renderDisclosureContent(selection) {
106413             // enter
106414             selection.selectAll('.privacy-options-list').data([0]).enter().append('ul').attr('class', 'layer-list privacy-options-list');
106415             var thirdPartyIconsEnter = selection.select('.privacy-options-list').selectAll('.privacy-third-party-icons-item').data([corePreferences('preferences.privacy.thirdpartyicons') || 'true']).enter().append('li').attr('class', 'privacy-third-party-icons-item').append('label').call(uiTooltip().title(_t.html('preferences.privacy.third_party_icons.tooltip')).placement('bottom'));
106416             thirdPartyIconsEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
106417               d3_event.preventDefault();
106418               corePreferences('preferences.privacy.thirdpartyicons', d === 'true' ? 'false' : 'true');
106419             });
106420             thirdPartyIconsEnter.append('span').call(_t.append('preferences.privacy.third_party_icons.description')); // update
106421
106422             selection.selectAll('.privacy-third-party-icons-item').classed('active', function (d) {
106423               return d === 'true';
106424             }).select('input').property('checked', function (d) {
106425               return d === 'true';
106426             }); // Privacy Policy link
106427
106428             selection.selectAll('.privacy-link').data([0]).enter().append('div').attr('class', 'privacy-link').append('a').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).attr('href', 'https://github.com/openstreetmap/iD/blob/release/PRIVACY.md').append('span').call(_t.append('preferences.privacy.privacy_link'));
106429           }
106430
106431           corePreferences.onChange('preferences.privacy.thirdpartyicons', section.reRender);
106432           return section;
106433         }
106434
106435         function uiSplash(context) {
106436           return function (selection) {
106437             // Exception - if there are restorable changes, skip this splash screen.
106438             // This is because we currently only support one `uiModal` at a time
106439             //  and we need to show them `uiRestore`` instead of this one.
106440             if (context.history().hasRestorableChanges()) return; // If user has not seen this version of the privacy policy, show the splash again.
106441
106442             var updateMessage = '';
106443             var sawPrivacyVersion = corePreferences('sawPrivacyVersion');
106444             var showSplash = !corePreferences('sawSplash');
106445
106446             if (sawPrivacyVersion !== context.privacyVersion) {
106447               updateMessage = _t('splash.privacy_update');
106448               showSplash = true;
106449             }
106450
106451             if (!showSplash) return;
106452             corePreferences('sawSplash', true);
106453             corePreferences('sawPrivacyVersion', context.privacyVersion); // fetch intro graph data now, while user is looking at the splash screen
106454
106455             _mainFileFetcher.get('intro_graph');
106456             var modalSelection = uiModal(selection);
106457             modalSelection.select('.modal').attr('class', 'modal-splash modal');
106458             var introModal = modalSelection.select('.content').append('div').attr('class', 'fillL');
106459             introModal.append('div').attr('class', 'modal-section').append('h3').call(_t.append('splash.welcome'));
106460             var modalSection = introModal.append('div').attr('class', 'modal-section');
106461             modalSection.append('p').html(_t.html('splash.text', {
106462               version: context.version,
106463               website: {
106464                 html: '<a target="_blank" href="https://github.com/openstreetmap/iD/blob/develop/CHANGELOG.md#whats-new">changelog</a>'
106465               },
106466               github: {
106467                 html: '<a target="_blank" href="https://github.com/openstreetmap/iD/issues">github.com</a>'
106468               }
106469             }));
106470             modalSection.append('p').html(_t.html('splash.privacy', {
106471               updateMessage: updateMessage,
106472               privacyLink: {
106473                 html: '<a target="_blank" href="https://github.com/openstreetmap/iD/blob/release/PRIVACY.md">' + _t('splash.privacy_policy') + '</a>'
106474               }
106475             }));
106476             uiSectionPrivacy(context).label(_t.html('splash.privacy_settings')).render(modalSection);
106477             var buttonWrap = introModal.append('div').attr('class', 'modal-actions');
106478             var walkthrough = buttonWrap.append('button').attr('class', 'walkthrough').on('click', function () {
106479               context.container().call(uiIntro(context));
106480               modalSelection.close();
106481             });
106482             walkthrough.append('svg').attr('class', 'logo logo-walkthrough').append('use').attr('xlink:href', '#iD-logo-walkthrough');
106483             walkthrough.append('div').call(_t.append('splash.walkthrough'));
106484             var startEditing = buttonWrap.append('button').attr('class', 'start-editing').on('click', modalSelection.close);
106485             startEditing.append('svg').attr('class', 'logo logo-features').append('use').attr('xlink:href', '#iD-logo-features');
106486             startEditing.append('div').call(_t.append('splash.start'));
106487             modalSelection.select('button.close').attr('class', 'hide');
106488           };
106489         }
106490
106491         function uiStatus(context) {
106492           var osm = context.connection();
106493           return function (selection) {
106494             if (!osm) return;
106495
106496             function update(err, apiStatus) {
106497               selection.html('');
106498
106499               if (err) {
106500                 if (apiStatus === 'connectionSwitched') {
106501                   // if the connection was just switched, we can't rely on
106502                   // the status (we're getting the status of the previous api)
106503                   return;
106504                 } else if (apiStatus === 'rateLimited') {
106505                   selection.call(_t.append('osm_api_status.message.rateLimit')).append('a').attr('href', '#').attr('class', 'api-status-login').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).append('span').call(_t.append('login')).on('click.login', function (d3_event) {
106506                     d3_event.preventDefault();
106507                     osm.authenticate();
106508                   });
106509                 } else {
106510                   // don't allow retrying too rapidly
106511                   var throttledRetry = throttle(function () {
106512                     // try loading the visible tiles
106513                     context.loadTiles(context.projection); // manually reload the status too in case all visible tiles were already loaded
106514
106515                     osm.reloadApiStatus();
106516                   }, 2000); // eslint-disable-next-line no-warning-comments
106517                   // TODO: nice messages for different error types
106518
106519
106520                   selection.call(_t.append('osm_api_status.message.error', {
106521                     suffix: ' '
106522                   })).append('a').attr('href', '#') // let the user manually retry their connection directly
106523                   .call(_t.append('osm_api_status.retry')).on('click.retry', function (d3_event) {
106524                     d3_event.preventDefault();
106525                     throttledRetry();
106526                   });
106527                 }
106528               } else if (apiStatus === 'readonly') {
106529                 selection.call(_t.append('osm_api_status.message.readonly'));
106530               } else if (apiStatus === 'offline') {
106531                 selection.call(_t.append('osm_api_status.message.offline'));
106532               }
106533
106534               selection.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
106535             }
106536
106537             osm.on('apiStatusChange.uiStatus', update);
106538             context.history().on('storage_error', function () {
106539               selection.selectAll('span.local-storage-full').remove();
106540               selection.append('span').attr('class', 'local-storage-full').call(_t.append('osm_api_status.message.local_storage_full'));
106541               selection.classed('error', true);
106542             }); // reload the status periodically regardless of other factors
106543
106544             window.setInterval(function () {
106545               osm.reloadApiStatus();
106546             }, 90000); // load the initial status in case no OSM data was loaded yet
106547
106548             osm.reloadApiStatus();
106549           };
106550         }
106551
106552         // for punction see https://stackoverflow.com/a/21224179
106553
106554         function simplify(str) {
106555           if (typeof str !== 'string') return '';
106556           return diacritics.remove(str.replace(/&/g, 'and').replace(/İ/ig, 'i').replace(/[\s\-=_!"#%'*{},.\/:;?\(\)\[\]@\\$\^*+<>«»~`’\u00a1\u00a7\u00b6\u00b7\u00bf\u037e\u0387\u055a-\u055f\u0589\u05c0\u05c3\u05c6\u05f3\u05f4\u0609\u060a\u060c\u060d\u061b\u061e\u061f\u066a-\u066d\u06d4\u0700-\u070d\u07f7-\u07f9\u0830-\u083e\u085e\u0964\u0965\u0970\u0af0\u0df4\u0e4f\u0e5a\u0e5b\u0f04-\u0f12\u0f14\u0f85\u0fd0-\u0fd4\u0fd9\u0fda\u104a-\u104f\u10fb\u1360-\u1368\u166d\u166e\u16eb-\u16ed\u1735\u1736\u17d4-\u17d6\u17d8-\u17da\u1800-\u1805\u1807-\u180a\u1944\u1945\u1a1e\u1a1f\u1aa0-\u1aa6\u1aa8-\u1aad\u1b5a-\u1b60\u1bfc-\u1bff\u1c3b-\u1c3f\u1c7e\u1c7f\u1cc0-\u1cc7\u1cd3\u200b-\u200f\u2016\u2017\u2020-\u2027\u2030-\u2038\u203b-\u203e\u2041-\u2043\u2047-\u2051\u2053\u2055-\u205e\u2cf9-\u2cfc\u2cfe\u2cff\u2d70\u2e00\u2e01\u2e06-\u2e08\u2e0b\u2e0e-\u2e16\u2e18\u2e19\u2e1b\u2e1e\u2e1f\u2e2a-\u2e2e\u2e30-\u2e39\u3001-\u3003\u303d\u30fb\ua4fe\ua4ff\ua60d-\ua60f\ua673\ua67e\ua6f2-\ua6f7\ua874-\ua877\ua8ce\ua8cf\ua8f8-\ua8fa\ua92e\ua92f\ua95f\ua9c1-\ua9cd\ua9de\ua9df\uaa5c-\uaa5f\uaade\uaadf\uaaf0\uaaf1\uabeb\ufe10-\ufe16\ufe19\ufe30\ufe45\ufe46\ufe49-\ufe4c\ufe50-\ufe52\ufe54-\ufe57\ufe5f-\ufe61\ufe68\ufe6a\ufe6b\ufeff\uff01-\uff03\uff05-\uff07\uff0a\uff0c\uff0e\uff0f\uff1a\uff1b\uff1f\uff20\uff3c\uff61\uff64\uff65]+/g, '').toLowerCase());
106557         }
106558
106559         // `resolveStrings`
106560         // Resolves the text strings for a given community index item
106561         //
106562         // Arguments
106563         //   `item`:  Object containing the community index item
106564         //   `defaults`: Object containing the community index default strings
106565         //   `localizerFn?`: optional function we will call to do the localization.
106566         //      This function should be like the iD `t()` function that
106567         //      accepts a `stringID` and returns a localized string
106568         //
106569         // Returns
106570         //   An Object containing all the resolved strings:
106571         //   {
106572         //     name:                     'talk-ru Mailing List',
106573         //     url:                      'https://lists.openstreetmap.org/listinfo/talk-ru',
106574         //     signupUrl:                'https://example.url/signup',
106575         //     description:              'A one line description',
106576         //     extendedDescription:      'Extended description',
106577         //     nameHTML:                 '<a href="the url">the name</a>',
106578         //     urlHTML:                  '<a href="the url">the url</a>',
106579         //     signupUrlHTML:            '<a href="the signupUrl">the signupUrl</a>',
106580         //     descriptionHTML:          the description, with urls and signupUrls linkified,
106581         //     extendedDescriptionHTML:  the extendedDescription with urls and signupUrls linkified
106582         //   }
106583         //
106584
106585         function resolveStrings(item, defaults, localizerFn) {
106586           var itemStrings = Object.assign({}, item.strings); // shallow clone
106587
106588           var defaultStrings = Object.assign({}, defaults[item.type]); // shallow clone
106589
106590           var anyToken = new RegExp(/(\{\w+\})/, 'gi'); // Pre-localize the item and default strings
106591
106592           if (localizerFn) {
106593             if (itemStrings.community) {
106594               var communityID = simplify(itemStrings.community);
106595               itemStrings.community = localizerFn("_communities.".concat(communityID));
106596             }
106597
106598             ['name', 'description', 'extendedDescription'].forEach(function (prop) {
106599               if (defaultStrings[prop]) defaultStrings[prop] = localizerFn("_defaults.".concat(item.type, ".").concat(prop));
106600               if (itemStrings[prop]) itemStrings[prop] = localizerFn("".concat(item.id, ".").concat(prop));
106601             });
106602           }
106603
106604           var replacements = {
106605             account: item.account,
106606             community: itemStrings.community,
106607             signupUrl: itemStrings.signupUrl,
106608             url: itemStrings.url
106609           }; // Resolve URLs first (which may refer to {account})
106610
106611           if (!replacements.signupUrl) {
106612             replacements.signupUrl = resolve(itemStrings.signupUrl || defaultStrings.signupUrl);
106613           }
106614
106615           if (!replacements.url) {
106616             replacements.url = resolve(itemStrings.url || defaultStrings.url);
106617           }
106618
106619           var resolved = {
106620             name: resolve(itemStrings.name || defaultStrings.name),
106621             url: resolve(itemStrings.url || defaultStrings.url),
106622             signupUrl: resolve(itemStrings.signupUrl || defaultStrings.signupUrl),
106623             description: resolve(itemStrings.description || defaultStrings.description),
106624             extendedDescription: resolve(itemStrings.extendedDescription || defaultStrings.extendedDescription)
106625           }; // Generate linkified strings
106626
106627           resolved.nameHTML = linkify(resolved.url, resolved.name);
106628           resolved.urlHTML = linkify(resolved.url);
106629           resolved.signupUrlHTML = linkify(resolved.signupUrl);
106630           resolved.descriptionHTML = resolve(itemStrings.description || defaultStrings.description, true);
106631           resolved.extendedDescriptionHTML = resolve(itemStrings.extendedDescription || defaultStrings.extendedDescription, true);
106632           return resolved;
106633
106634           function resolve(s, addLinks) {
106635             if (!s) return undefined;
106636             var result = s;
106637
106638             for (var key in replacements) {
106639               var token = "{".concat(key, "}");
106640               var regex = new RegExp(token, 'g');
106641
106642               if (regex.test(result)) {
106643                 var replacement = replacements[key];
106644
106645                 if (!replacement) {
106646                   throw new Error("Cannot resolve token: ".concat(token));
106647                 } else {
106648                   if (addLinks && (key === 'signupUrl' || key === 'url')) {
106649                     replacement = linkify(replacement);
106650                   }
106651
106652                   result = result.replace(regex, replacement);
106653                 }
106654               }
106655             } // There shouldn't be any leftover tokens in a resolved string
106656
106657
106658             var leftovers = result.match(anyToken);
106659
106660             if (leftovers) {
106661               throw new Error("Cannot resolve tokens: ".concat(leftovers));
106662             } // Linkify subreddits like `/r/openstreetmap`
106663             // https://github.com/osmlab/osm-community-index/issues/82
106664             // https://github.com/openstreetmap/iD/issues/4997
106665
106666
106667             if (addLinks && item.type === 'reddit') {
106668               result = result.replace(/(\/r\/\w+\/*)/i, function (match) {
106669                 return linkify(resolved.url, match);
106670               });
106671             }
106672
106673             return result;
106674           }
106675
106676           function linkify(url, text) {
106677             if (!url) return undefined;
106678             text = text || url;
106679             return "<a target=\"_blank\" href=\"".concat(url, "\">").concat(text, "</a>");
106680           }
106681         }
106682
106683         var _oci = null;
106684         function uiSuccess(context) {
106685           var MAXEVENTS = 2;
106686           var dispatch = dispatch$8('cancel');
106687
106688           var _changeset;
106689
106690           var _location;
106691
106692           ensureOSMCommunityIndex(); // start fetching the data
106693
106694           function ensureOSMCommunityIndex() {
106695             var data = _mainFileFetcher;
106696             return Promise.all([data.get('oci_features'), data.get('oci_resources'), data.get('oci_defaults')]).then(function (vals) {
106697               if (_oci) return _oci; // Merge Custom Features
106698
106699               if (vals[0] && Array.isArray(vals[0].features)) {
106700                 _mainLocations.mergeCustomGeoJSON(vals[0]);
106701               }
106702
106703               var ociResources = Object.values(vals[1].resources);
106704
106705               if (ociResources.length) {
106706                 // Resolve all locationSet features.
106707                 return _mainLocations.mergeLocationSets(ociResources).then(function () {
106708                   _oci = {
106709                     resources: ociResources,
106710                     defaults: vals[2].defaults
106711                   };
106712                   return _oci;
106713                 });
106714               } else {
106715                 _oci = {
106716                   resources: [],
106717                   // no resources?
106718                   defaults: vals[2].defaults
106719                 };
106720                 return _oci;
106721               }
106722             });
106723           } // string-to-date parsing in JavaScript is weird
106724
106725
106726           function parseEventDate(when) {
106727             if (!when) return;
106728             var raw = when.trim();
106729             if (!raw) return;
106730
106731             if (!/Z$/.test(raw)) {
106732               // if no trailing 'Z', add one
106733               raw += 'Z'; // this forces date to be parsed as a UTC date
106734             }
106735
106736             var parsed = new Date(raw);
106737             return new Date(parsed.toUTCString().substr(0, 25)); // convert to local timezone
106738           }
106739
106740           function success(selection) {
106741             var header = selection.append('div').attr('class', 'header fillL');
106742             header.append('h2').call(_t.append('success.just_edited'));
106743             header.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
106744               return dispatch.call('cancel');
106745             }).call(svgIcon('#iD-icon-close'));
106746             var body = selection.append('div').attr('class', 'body save-success fillL');
106747             var summary = body.append('div').attr('class', 'save-summary');
106748             summary.append('h3').call(_t.append('success.thank_you' + (_location ? '_location' : ''), {
106749               where: _location
106750             }));
106751             summary.append('p').call(_t.append('success.help_html')).append('a').attr('class', 'link-out').attr('target', '_blank').attr('href', _t('success.help_link_url')).call(svgIcon('#iD-icon-out-link', 'inline')).append('span').call(_t.append('success.help_link_text'));
106752             var osm = context.connection();
106753             if (!osm) return;
106754             var changesetURL = osm.changesetURL(_changeset.id);
106755             var table = summary.append('table').attr('class', 'summary-table');
106756             var row = table.append('tr').attr('class', 'summary-row');
106757             row.append('td').attr('class', 'cell-icon summary-icon').append('a').attr('target', '_blank').attr('href', changesetURL).append('svg').attr('class', 'logo-small').append('use').attr('xlink:href', '#iD-logo-osm');
106758             var summaryDetail = row.append('td').attr('class', 'cell-detail summary-detail');
106759             summaryDetail.append('a').attr('class', 'cell-detail summary-view-on-osm').attr('target', '_blank').attr('href', changesetURL).call(_t.append('success.view_on_osm'));
106760             summaryDetail.append('div').html(_t.html('success.changeset_id', {
106761               changeset_id: {
106762                 html: "<a href=\"".concat(changesetURL, "\" target=\"_blank\">").concat(_changeset.id, "</a>")
106763               }
106764             })); // Get OSM community index features intersecting the map..
106765
106766             ensureOSMCommunityIndex().then(function (oci) {
106767               var loc = context.map().center();
106768               var validLocations = _mainLocations.locationsAt(loc); // Gather the communities
106769
106770               var communities = [];
106771               oci.resources.forEach(function (resource) {
106772                 var area = validLocations[resource.locationSetID];
106773                 if (!area) return; // Resolve strings
106774
106775                 var localizer = function localizer(stringID) {
106776                   return _t.html("community.".concat(stringID));
106777                 };
106778
106779                 resource.resolved = resolveStrings(resource, oci.defaults, localizer);
106780                 communities.push({
106781                   area: area,
106782                   order: resource.order || 0,
106783                   resource: resource
106784                 });
106785               }); // sort communities by feature area ascending, community order descending
106786
106787               communities.sort(function (a, b) {
106788                 return a.area - b.area || b.order - a.order;
106789               });
106790               body.call(showCommunityLinks, communities.map(function (c) {
106791                 return c.resource;
106792               }));
106793             });
106794           }
106795
106796           function showCommunityLinks(selection, resources) {
106797             var communityLinks = selection.append('div').attr('class', 'save-communityLinks');
106798             communityLinks.append('h3').call(_t.append('success.like_osm'));
106799             var table = communityLinks.append('table').attr('class', 'community-table');
106800             var row = table.selectAll('.community-row').data(resources);
106801             var rowEnter = row.enter().append('tr').attr('class', 'community-row');
106802             rowEnter.append('td').attr('class', 'cell-icon community-icon').append('a').attr('target', '_blank').attr('href', function (d) {
106803               return d.resolved.url;
106804             }).append('svg').attr('class', 'logo-small').append('use').attr('xlink:href', function (d) {
106805               return "#community-".concat(d.type);
106806             });
106807             var communityDetail = rowEnter.append('td').attr('class', 'cell-detail community-detail');
106808             communityDetail.each(showCommunityDetails);
106809             communityLinks.append('div').attr('class', 'community-missing').call(_t.append('success.missing')).append('a').attr('class', 'link-out').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).attr('href', 'https://github.com/osmlab/osm-community-index/issues').append('span').call(_t.append('success.tell_us'));
106810           }
106811
106812           function showCommunityDetails(d) {
106813             var selection = select(this);
106814             var communityID = d.id;
106815             selection.append('div').attr('class', 'community-name').html(d.resolved.nameHTML);
106816             selection.append('div').attr('class', 'community-description').html(d.resolved.descriptionHTML); // Create an expanding section if any of these are present..
106817
106818             if (d.resolved.extendedDescriptionHTML || d.languageCodes && d.languageCodes.length) {
106819               selection.append('div').call(uiDisclosure(context, "community-more-".concat(d.id), false).expanded(false).updatePreference(false).label(_t.html('success.more')).content(showMore));
106820             }
106821
106822             var nextEvents = (d.events || []).map(function (event) {
106823               event.date = parseEventDate(event.when);
106824               return event;
106825             }).filter(function (event) {
106826               // date is valid and future (or today)
106827               var t = event.date.getTime();
106828               var now = new Date().setHours(0, 0, 0, 0);
106829               return !isNaN(t) && t >= now;
106830             }).sort(function (a, b) {
106831               // sort by date ascending
106832               return a.date < b.date ? -1 : a.date > b.date ? 1 : 0;
106833             }).slice(0, MAXEVENTS); // limit number of events shown
106834
106835             if (nextEvents.length) {
106836               selection.append('div').call(uiDisclosure(context, "community-events-".concat(d.id), false).expanded(false).updatePreference(false).label(_t.html('success.events')).content(showNextEvents)).select('.hide-toggle').append('span').attr('class', 'badge-text').text(nextEvents.length);
106837             }
106838
106839             function showMore(selection) {
106840               var more = selection.selectAll('.community-more').data([0]);
106841               var moreEnter = more.enter().append('div').attr('class', 'community-more');
106842
106843               if (d.resolved.extendedDescriptionHTML) {
106844                 moreEnter.append('div').attr('class', 'community-extended-description').html(d.resolved.extendedDescriptionHTML);
106845               }
106846
106847               if (d.languageCodes && d.languageCodes.length) {
106848                 var languageList = d.languageCodes.map(function (code) {
106849                   return _mainLocalizer.languageName(code);
106850                 }).join(', ');
106851                 moreEnter.append('div').attr('class', 'community-languages').call(_t.append('success.languages', {
106852                   languages: languageList
106853                 }));
106854               }
106855             }
106856
106857             function showNextEvents(selection) {
106858               var events = selection.append('div').attr('class', 'community-events');
106859               var item = events.selectAll('.community-event').data(nextEvents);
106860               var itemEnter = item.enter().append('div').attr('class', 'community-event');
106861               itemEnter.append('div').attr('class', 'community-event-name').append('a').attr('target', '_blank').attr('href', function (d) {
106862                 return d.url;
106863               }).text(function (d) {
106864                 var name = d.name;
106865
106866                 if (d.i18n && d.id) {
106867                   name = _t("community.".concat(communityID, ".events.").concat(d.id, ".name"), {
106868                     "default": name
106869                   });
106870                 }
106871
106872                 return name;
106873               });
106874               itemEnter.append('div').attr('class', 'community-event-when').text(function (d) {
106875                 var options = {
106876                   weekday: 'short',
106877                   day: 'numeric',
106878                   month: 'short',
106879                   year: 'numeric'
106880                 };
106881
106882                 if (d.date.getHours() || d.date.getMinutes()) {
106883                   // include time if it has one
106884                   options.hour = 'numeric';
106885                   options.minute = 'numeric';
106886                 }
106887
106888                 return d.date.toLocaleString(_mainLocalizer.localeCode(), options);
106889               });
106890               itemEnter.append('div').attr('class', 'community-event-where').text(function (d) {
106891                 var where = d.where;
106892
106893                 if (d.i18n && d.id) {
106894                   where = _t("community.".concat(communityID, ".events.").concat(d.id, ".where"), {
106895                     "default": where
106896                   });
106897                 }
106898
106899                 return where;
106900               });
106901               itemEnter.append('div').attr('class', 'community-event-description').text(function (d) {
106902                 var description = d.description;
106903
106904                 if (d.i18n && d.id) {
106905                   description = _t("community.".concat(communityID, ".events.").concat(d.id, ".description"), {
106906                     "default": description
106907                   });
106908                 }
106909
106910                 return description;
106911               });
106912             }
106913           }
106914
106915           success.changeset = function (val) {
106916             if (!arguments.length) return _changeset;
106917             _changeset = val;
106918             return success;
106919           };
106920
106921           success.location = function (val) {
106922             if (!arguments.length) return _location;
106923             _location = val;
106924             return success;
106925           };
106926
106927           return utilRebind(success, dispatch, 'on');
106928         }
106929
106930         var sawVersion = null;
106931         var isNewVersion = false;
106932         var isNewUser = false;
106933         function uiVersion(context) {
106934           var currVersion = context.version;
106935           var matchedVersion = currVersion.match(/\d+\.\d+\.\d+.*/);
106936
106937           if (sawVersion === null && matchedVersion !== null) {
106938             if (corePreferences('sawVersion')) {
106939               isNewUser = false;
106940               isNewVersion = corePreferences('sawVersion') !== currVersion && currVersion.indexOf('-') === -1;
106941             } else {
106942               isNewUser = true;
106943               isNewVersion = true;
106944             }
106945
106946             corePreferences('sawVersion', currVersion);
106947             sawVersion = currVersion;
106948           }
106949
106950           return function (selection) {
106951             selection.append('a').attr('target', '_blank').attr('href', 'https://github.com/openstreetmap/iD').text(currVersion); // only show new version indicator to users that have used iD before
106952
106953             if (isNewVersion && !isNewUser) {
106954               selection.append('a').attr('class', 'badge').attr('target', '_blank').attr('href', 'https://github.com/openstreetmap/iD/blob/release/CHANGELOG.md#whats-new').call(svgIcon('#maki-gift-11')).call(uiTooltip().title(_t.html('version.whats_new', {
106955                 version: currVersion
106956               })).placement('top').scrollContainer(context.container().select('.main-footer-wrap')));
106957             }
106958           };
106959         }
106960
106961         function uiZoom(context) {
106962           var zooms = [{
106963             id: 'zoom-in',
106964             icon: 'iD-icon-plus',
106965             title: _t.html('zoom.in'),
106966             action: zoomIn,
106967             disabled: function disabled() {
106968               return !context.map().canZoomIn();
106969             },
106970             disabledTitle: _t.html('zoom.disabled.in'),
106971             key: '+'
106972           }, {
106973             id: 'zoom-out',
106974             icon: 'iD-icon-minus',
106975             title: _t.html('zoom.out'),
106976             action: zoomOut,
106977             disabled: function disabled() {
106978               return !context.map().canZoomOut();
106979             },
106980             disabledTitle: _t.html('zoom.disabled.out'),
106981             key: '-'
106982           }];
106983
106984           function zoomIn(d3_event) {
106985             if (d3_event.shiftKey) return;
106986             d3_event.preventDefault();
106987             context.map().zoomIn();
106988           }
106989
106990           function zoomOut(d3_event) {
106991             if (d3_event.shiftKey) return;
106992             d3_event.preventDefault();
106993             context.map().zoomOut();
106994           }
106995
106996           function zoomInFurther(d3_event) {
106997             if (d3_event.shiftKey) return;
106998             d3_event.preventDefault();
106999             context.map().zoomInFurther();
107000           }
107001
107002           function zoomOutFurther(d3_event) {
107003             if (d3_event.shiftKey) return;
107004             d3_event.preventDefault();
107005             context.map().zoomOutFurther();
107006           }
107007
107008           return function (selection) {
107009             var tooltipBehavior = uiTooltip().placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left').title(function (d) {
107010               if (d.disabled()) {
107011                 return d.disabledTitle;
107012               }
107013
107014               return d.title;
107015             }).keys(function (d) {
107016               return [d.key];
107017             });
107018             var lastPointerUpType;
107019             var buttons = selection.selectAll('button').data(zooms).enter().append('button').attr('class', function (d) {
107020               return d.id;
107021             }).on('pointerup.editor', function (d3_event) {
107022               lastPointerUpType = d3_event.pointerType;
107023             }).on('click.editor', function (d3_event, d) {
107024               if (!d.disabled()) {
107025                 d.action(d3_event);
107026               } else if (lastPointerUpType === 'touch' || lastPointerUpType === 'pen') {
107027                 context.ui().flash.duration(2000).iconName('#' + d.icon).iconClass('disabled').label(d.disabledTitle)();
107028               }
107029
107030               lastPointerUpType = null;
107031             }).call(tooltipBehavior);
107032             buttons.each(function (d) {
107033               select(this).call(svgIcon('#' + d.icon, 'light'));
107034             });
107035             utilKeybinding.plusKeys.forEach(function (key) {
107036               context.keybinding().on([key], zoomIn);
107037               context.keybinding().on([uiCmd('⌥' + key)], zoomInFurther);
107038             });
107039             utilKeybinding.minusKeys.forEach(function (key) {
107040               context.keybinding().on([key], zoomOut);
107041               context.keybinding().on([uiCmd('⌥' + key)], zoomOutFurther);
107042             });
107043
107044             function updateButtonStates() {
107045               buttons.classed('disabled', function (d) {
107046                 return d.disabled();
107047               }).each(function () {
107048                 var selection = select(this);
107049
107050                 if (!selection.select('.tooltip.in').empty()) {
107051                   selection.call(tooltipBehavior.updateContent);
107052                 }
107053               });
107054             }
107055
107056             updateButtonStates();
107057             context.map().on('move.uiZoom', updateButtonStates);
107058           };
107059         }
107060
107061         function uiSectionRawTagEditor(id, context) {
107062           var section = uiSection(id, context).classes('raw-tag-editor').label(function () {
107063             var count = Object.keys(_tags).filter(function (d) {
107064               return d;
107065             }).length;
107066             return _t.html('inspector.title_count', {
107067               title: {
107068                 html: _t.html('inspector.tags')
107069               },
107070               count: count
107071             });
107072           }).expandedByDefault(false).disclosureContent(renderDisclosureContent);
107073           var taginfo = services.taginfo;
107074           var dispatch = dispatch$8('change');
107075           var availableViews = [{
107076             id: 'list',
107077             icon: '#fas-th-list'
107078           }, {
107079             id: 'text',
107080             icon: '#fas-i-cursor'
107081           }];
107082
107083           var _tagView = corePreferences('raw-tag-editor-view') || 'list'; // 'list, 'text'
107084
107085
107086           var _readOnlyTags = []; // the keys in the order we want them to display
107087
107088           var _orderedKeys = [];
107089           var _showBlank = false;
107090           var _pendingChange = null;
107091
107092           var _state;
107093
107094           var _presets;
107095
107096           var _tags;
107097
107098           var _entityIDs;
107099
107100           var _didInteract = false;
107101
107102           function interacted() {
107103             _didInteract = true;
107104           }
107105
107106           function renderDisclosureContent(wrap) {
107107             // remove deleted keys
107108             _orderedKeys = _orderedKeys.filter(function (key) {
107109               return _tags[key] !== undefined;
107110             }); // When switching to a different entity or changing the state (hover/select)
107111             // reorder the keys alphabetically.
107112             // We trigger this by emptying the `_orderedKeys` array, then it will be rebuilt here.
107113             // Otherwise leave their order alone - #5857, #5927
107114
107115             var all = Object.keys(_tags).sort();
107116             var missingKeys = utilArrayDifference(all, _orderedKeys);
107117
107118             for (var i in missingKeys) {
107119               _orderedKeys.push(missingKeys[i]);
107120             } // assemble row data
107121
107122
107123             var rowData = _orderedKeys.map(function (key, i) {
107124               return {
107125                 index: i,
107126                 key: key,
107127                 value: _tags[key]
107128               };
107129             }); // append blank row last, if necessary
107130
107131
107132             if (!rowData.length || _showBlank) {
107133               _showBlank = false;
107134               rowData.push({
107135                 index: rowData.length,
107136                 key: '',
107137                 value: ''
107138               });
107139             } // View Options
107140
107141
107142             var options = wrap.selectAll('.raw-tag-options').data([0]);
107143             options.exit().remove();
107144             var optionsEnter = options.enter().insert('div', ':first-child').attr('class', 'raw-tag-options').attr('role', 'tablist');
107145             var optionEnter = optionsEnter.selectAll('.raw-tag-option').data(availableViews, function (d) {
107146               return d.id;
107147             }).enter();
107148             optionEnter.append('button').attr('class', function (d) {
107149               return 'raw-tag-option raw-tag-option-' + d.id + (_tagView === d.id ? ' selected' : '');
107150             }).attr('aria-selected', function (d) {
107151               return _tagView === d.id;
107152             }).attr('role', 'tab').attr('title', function (d) {
107153               return _t('icons.' + d.id);
107154             }).on('click', function (d3_event, d) {
107155               _tagView = d.id;
107156               corePreferences('raw-tag-editor-view', d.id);
107157               wrap.selectAll('.raw-tag-option').classed('selected', function (datum) {
107158                 return datum === d;
107159               }).attr('aria-selected', function (datum) {
107160                 return datum === d;
107161               });
107162               wrap.selectAll('.tag-text').classed('hide', d.id !== 'text').each(setTextareaHeight);
107163               wrap.selectAll('.tag-list, .add-row').classed('hide', d.id !== 'list');
107164             }).each(function (d) {
107165               select(this).call(svgIcon(d.icon));
107166             }); // View as Text
107167
107168             var textData = rowsToText(rowData);
107169             var textarea = wrap.selectAll('.tag-text').data([0]);
107170             textarea = textarea.enter().append('textarea').attr('class', 'tag-text' + (_tagView !== 'text' ? ' hide' : '')).call(utilNoAuto).attr('placeholder', _t('inspector.key_value')).attr('spellcheck', 'false').merge(textarea);
107171             textarea.call(utilGetSetValue, textData).each(setTextareaHeight).on('input', setTextareaHeight).on('focus', interacted).on('blur', textChanged).on('change', textChanged); // View as List
107172
107173             var list = wrap.selectAll('.tag-list').data([0]);
107174             list = list.enter().append('ul').attr('class', 'tag-list' + (_tagView !== 'list' ? ' hide' : '')).merge(list); // Container for the Add button
107175
107176             var addRowEnter = wrap.selectAll('.add-row').data([0]).enter().append('div').attr('class', 'add-row' + (_tagView !== 'list' ? ' hide' : ''));
107177             addRowEnter.append('button').attr('class', 'add-tag').attr('aria-label', _t('inspector.add_to_tag')).call(svgIcon('#iD-icon-plus', 'light')).call(uiTooltip().title(_t.html('inspector.add_to_tag')).placement(_mainLocalizer.textDirection() === 'ltr' ? 'right' : 'left')).on('click', addTag);
107178             addRowEnter.append('div').attr('class', 'space-value'); // preserve space
107179
107180             addRowEnter.append('div').attr('class', 'space-buttons'); // preserve space
107181             // Tag list items
107182
107183             var items = list.selectAll('.tag-row').data(rowData, function (d) {
107184               return d.key;
107185             });
107186             items.exit().each(unbind).remove(); // Enter
107187
107188             var itemsEnter = items.enter().append('li').attr('class', 'tag-row').classed('readonly', isReadOnly);
107189             var innerWrap = itemsEnter.append('div').attr('class', 'inner-wrap');
107190             innerWrap.append('div').attr('class', 'key-wrap').append('input').property('type', 'text').attr('class', 'key').call(utilNoAuto).on('focus', interacted).on('blur', keyChange).on('change', keyChange);
107191             innerWrap.append('div').attr('class', 'value-wrap').append('input').property('type', 'text').attr('class', 'value').call(utilNoAuto).on('focus', interacted).on('blur', valueChange).on('change', valueChange).on('keydown.push-more', pushMore);
107192             innerWrap.append('button').attr('class', 'form-field-button remove').attr('title', _t('icons.remove')).call(svgIcon('#iD-operation-delete')); // Update
107193
107194             items = items.merge(itemsEnter).sort(function (a, b) {
107195               return a.index - b.index;
107196             });
107197             items.each(function (d) {
107198               var row = select(this);
107199               var key = row.select('input.key'); // propagate bound data
107200
107201               var value = row.select('input.value'); // propagate bound data
107202
107203               if (_entityIDs && taginfo && _state !== 'hover') {
107204                 bindTypeahead(key, value);
107205               }
107206
107207               var referenceOptions = {
107208                 key: d.key
107209               };
107210
107211               if (typeof d.value === 'string') {
107212                 referenceOptions.value = d.value;
107213               }
107214
107215               var reference = uiTagReference(referenceOptions);
107216
107217               if (_state === 'hover') {
107218                 reference.showing(false);
107219               }
107220
107221               row.select('.inner-wrap') // propagate bound data
107222               .call(reference.button);
107223               row.call(reference.body);
107224               row.select('button.remove'); // propagate bound data
107225             });
107226             items.selectAll('input.key').attr('title', function (d) {
107227               return d.key;
107228             }).call(utilGetSetValue, function (d) {
107229               return d.key;
107230             }).attr('readonly', function (d) {
107231               return isReadOnly(d) || null;
107232             });
107233             items.selectAll('input.value').attr('title', function (d) {
107234               return Array.isArray(d.value) ? d.value.filter(Boolean).join('\n') : d.value;
107235             }).classed('mixed', function (d) {
107236               return Array.isArray(d.value);
107237             }).attr('placeholder', function (d) {
107238               return typeof d.value === 'string' ? null : _t('inspector.multiple_values');
107239             }).call(utilGetSetValue, function (d) {
107240               return typeof d.value === 'string' ? d.value : '';
107241             }).attr('readonly', function (d) {
107242               return isReadOnly(d) || null;
107243             });
107244             items.selectAll('button.remove').on(('PointerEvent' in window ? 'pointer' : 'mouse') + 'down', removeTag); // 'click' fires too late - #5878
107245           }
107246
107247           function isReadOnly(d) {
107248             for (var i = 0; i < _readOnlyTags.length; i++) {
107249               if (d.key.match(_readOnlyTags[i]) !== null) {
107250                 return true;
107251               }
107252             }
107253
107254             return false;
107255           }
107256
107257           function setTextareaHeight() {
107258             if (_tagView !== 'text') return;
107259             var selection = select(this);
107260             var matches = selection.node().value.match(/\n/g);
107261             var lineCount = 2 + Number(matches && matches.length);
107262             var lineHeight = 20;
107263             selection.style('height', lineCount * lineHeight + 'px');
107264           }
107265
107266           function stringify(s) {
107267             return JSON.stringify(s).slice(1, -1); // without leading/trailing "
107268           }
107269
107270           function unstringify(s) {
107271             var leading = '';
107272             var trailing = '';
107273
107274             if (s.length < 1 || s.charAt(0) !== '"') {
107275               leading = '"';
107276             }
107277
107278             if (s.length < 2 || s.charAt(s.length - 1) !== '"' || s.charAt(s.length - 1) === '"' && s.charAt(s.length - 2) === '\\') {
107279               trailing = '"';
107280             }
107281
107282             return JSON.parse(leading + s + trailing);
107283           }
107284
107285           function rowsToText(rows) {
107286             var str = rows.filter(function (row) {
107287               return row.key && row.key.trim() !== '';
107288             }).map(function (row) {
107289               var rawVal = row.value;
107290               if (typeof rawVal !== 'string') rawVal = '*';
107291               var val = rawVal ? stringify(rawVal) : '';
107292               return stringify(row.key) + '=' + val;
107293             }).join('\n');
107294
107295             if (_state !== 'hover' && str.length) {
107296               return str + '\n';
107297             }
107298
107299             return str;
107300           }
107301
107302           function textChanged() {
107303             var newText = this.value.trim();
107304             var newTags = {};
107305             newText.split('\n').forEach(function (row) {
107306               var m = row.match(/^\s*([^=]+)=(.*)$/);
107307
107308               if (m !== null) {
107309                 var k = context.cleanTagKey(unstringify(m[1].trim()));
107310                 var v = context.cleanTagValue(unstringify(m[2].trim()));
107311                 newTags[k] = v;
107312               }
107313             });
107314             var tagDiff = utilTagDiff(_tags, newTags);
107315             if (!tagDiff.length) return;
107316             _pendingChange = _pendingChange || {};
107317             tagDiff.forEach(function (change) {
107318               if (isReadOnly({
107319                 key: change.key
107320               })) return; // skip unchanged multiselection placeholders
107321
107322               if (change.newVal === '*' && typeof change.oldVal !== 'string') return;
107323
107324               if (change.type === '-') {
107325                 _pendingChange[change.key] = undefined;
107326               } else if (change.type === '+') {
107327                 _pendingChange[change.key] = change.newVal || '';
107328               }
107329             });
107330
107331             if (Object.keys(_pendingChange).length === 0) {
107332               _pendingChange = null;
107333               return;
107334             }
107335
107336             scheduleChange();
107337           }
107338
107339           function pushMore(d3_event) {
107340             // if pressing Tab on the last value field with content, add a blank row
107341             if (d3_event.keyCode === 9 && !d3_event.shiftKey && section.selection().selectAll('.tag-list li:last-child input.value').node() === this && utilGetSetValue(select(this))) {
107342               addTag();
107343             }
107344           }
107345
107346           function bindTypeahead(key, value) {
107347             if (isReadOnly(key.datum())) return;
107348
107349             if (Array.isArray(value.datum().value)) {
107350               value.call(uiCombobox(context, 'tag-value').minItems(1).fetcher(function (value, callback) {
107351                 var keyString = utilGetSetValue(key);
107352                 if (!_tags[keyString]) return;
107353
107354                 var data = _tags[keyString].filter(Boolean).map(function (tagValue) {
107355                   return {
107356                     value: tagValue,
107357                     title: tagValue
107358                   };
107359                 });
107360
107361                 callback(data);
107362               }));
107363               return;
107364             }
107365
107366             var geometry = context.graph().geometry(_entityIDs[0]);
107367             key.call(uiCombobox(context, 'tag-key').fetcher(function (value, callback) {
107368               taginfo.keys({
107369                 debounce: true,
107370                 geometry: geometry,
107371                 query: value
107372               }, function (err, data) {
107373                 if (!err) {
107374                   var filtered = data.filter(function (d) {
107375                     return _tags[d.value] === undefined;
107376                   });
107377                   callback(sort(value, filtered));
107378                 }
107379               });
107380             }));
107381             value.call(uiCombobox(context, 'tag-value').fetcher(function (value, callback) {
107382               taginfo.values({
107383                 debounce: true,
107384                 key: utilGetSetValue(key),
107385                 geometry: geometry,
107386                 query: value
107387               }, function (err, data) {
107388                 if (!err) callback(sort(value, data));
107389               });
107390             }));
107391
107392             function sort(value, data) {
107393               var sameletter = [];
107394               var other = [];
107395
107396               for (var i = 0; i < data.length; i++) {
107397                 if (data[i].value.substring(0, value.length) === value) {
107398                   sameletter.push(data[i]);
107399                 } else {
107400                   other.push(data[i]);
107401                 }
107402               }
107403
107404               return sameletter.concat(other);
107405             }
107406           }
107407
107408           function unbind() {
107409             var row = select(this);
107410             row.selectAll('input.key').call(uiCombobox.off, context);
107411             row.selectAll('input.value').call(uiCombobox.off, context);
107412           }
107413
107414           function keyChange(d3_event, d) {
107415             if (select(this).attr('readonly')) return;
107416             var kOld = d.key; // exit if we are currently about to delete this row anyway - #6366
107417
107418             if (_pendingChange && _pendingChange.hasOwnProperty(kOld) && _pendingChange[kOld] === undefined) return;
107419             var kNew = context.cleanTagKey(this.value.trim()); // allow no change if the key should be readonly
107420
107421             if (isReadOnly({
107422               key: kNew
107423             })) {
107424               this.value = kOld;
107425               return;
107426             }
107427
107428             if (kNew && kNew !== kOld && _tags[kNew] !== undefined) {
107429               // new key is already in use, switch focus to the existing row
107430               this.value = kOld; // reset the key
107431
107432               section.selection().selectAll('.tag-list input.value').each(function (d) {
107433                 if (d.key === kNew) {
107434                   // send focus to that other value combo instead
107435                   var input = select(this).node();
107436                   input.focus();
107437                   input.select();
107438                 }
107439               });
107440               return;
107441             }
107442
107443             _pendingChange = _pendingChange || {};
107444
107445             if (kOld) {
107446               if (kOld === kNew) return; // a tag key was renamed
107447
107448               _pendingChange[kNew] = _pendingChange[kOld] || {
107449                 oldKey: kOld
107450               };
107451               _pendingChange[kOld] = undefined;
107452             } else {
107453               // a new tag was added
107454               var row = this.parentNode.parentNode;
107455               var inputVal = select(row).selectAll('input.value');
107456               var vNew = context.cleanTagValue(utilGetSetValue(inputVal));
107457               _pendingChange[kNew] = vNew;
107458               utilGetSetValue(inputVal, vNew);
107459             } // update the ordered key index so this row doesn't change position
107460
107461
107462             var existingKeyIndex = _orderedKeys.indexOf(kOld);
107463
107464             if (existingKeyIndex !== -1) _orderedKeys[existingKeyIndex] = kNew;
107465             d.key = kNew; // update datum to avoid exit/enter on tag update
107466
107467             this.value = kNew;
107468             scheduleChange();
107469           }
107470
107471           function valueChange(d3_event, d) {
107472             if (isReadOnly(d)) return; // exit if this is a multiselection and no value was entered
107473
107474             if (typeof d.value !== 'string' && !this.value) return; // exit if we are currently about to delete this row anyway - #6366
107475
107476             if (_pendingChange && _pendingChange.hasOwnProperty(d.key) && _pendingChange[d.key] === undefined) return;
107477             _pendingChange = _pendingChange || {};
107478             _pendingChange[d.key] = context.cleanTagValue(this.value);
107479             scheduleChange();
107480           }
107481
107482           function removeTag(d3_event, d) {
107483             if (isReadOnly(d)) return;
107484
107485             if (d.key === '') {
107486               // removing the blank row
107487               _showBlank = false;
107488               section.reRender();
107489             } else {
107490               // remove the key from the ordered key index
107491               _orderedKeys = _orderedKeys.filter(function (key) {
107492                 return key !== d.key;
107493               });
107494               _pendingChange = _pendingChange || {};
107495               _pendingChange[d.key] = undefined;
107496               scheduleChange();
107497             }
107498           }
107499
107500           function addTag() {
107501             // Delay render in case this click is blurring an edited combo.
107502             // Without the setTimeout, the `content` render would wipe out the pending tag change.
107503             window.setTimeout(function () {
107504               _showBlank = true;
107505               section.reRender();
107506               section.selection().selectAll('.tag-list li:last-child input.key').node().focus();
107507             }, 20);
107508           }
107509
107510           function scheduleChange() {
107511             // Cache IDs in case the editor is reloaded before the change event is called. - #6028
107512             var entityIDs = _entityIDs; // Delay change in case this change is blurring an edited combo. - #5878
107513
107514             window.setTimeout(function () {
107515               if (!_pendingChange) return;
107516               dispatch.call('change', this, entityIDs, _pendingChange);
107517               _pendingChange = null;
107518             }, 10);
107519           }
107520
107521           section.state = function (val) {
107522             if (!arguments.length) return _state;
107523
107524             if (_state !== val) {
107525               _orderedKeys = [];
107526               _state = val;
107527             }
107528
107529             return section;
107530           };
107531
107532           section.presets = function (val) {
107533             if (!arguments.length) return _presets;
107534             _presets = val;
107535
107536             if (_presets && _presets.length && _presets[0].isFallback()) {
107537               section.disclosureExpanded(true); // don't collapse the disclosure if the mapper used the raw tag editor - #1881
107538             } else if (!_didInteract) {
107539               section.disclosureExpanded(null);
107540             }
107541
107542             return section;
107543           };
107544
107545           section.tags = function (val) {
107546             if (!arguments.length) return _tags;
107547             _tags = val;
107548             return section;
107549           };
107550
107551           section.entityIDs = function (val) {
107552             if (!arguments.length) return _entityIDs;
107553
107554             if (!_entityIDs || !val || !utilArrayIdentical(_entityIDs, val)) {
107555               _entityIDs = val;
107556               _orderedKeys = [];
107557             }
107558
107559             return section;
107560           }; // pass an array of regular expressions to test against the tag key
107561
107562
107563           section.readOnlyTags = function (val) {
107564             if (!arguments.length) return _readOnlyTags;
107565             _readOnlyTags = val;
107566             return section;
107567           };
107568
107569           return utilRebind(section, dispatch, 'on');
107570         }
107571
107572         function uiDataEditor(context) {
107573           var dataHeader = uiDataHeader();
107574           var rawTagEditor = uiSectionRawTagEditor('custom-data-tag-editor', context).expandedByDefault(true).readOnlyTags([/./]);
107575
107576           var _datum;
107577
107578           function dataEditor(selection) {
107579             var header = selection.selectAll('.header').data([0]);
107580             var headerEnter = header.enter().append('div').attr('class', 'header fillL');
107581             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
107582               context.enter(modeBrowse(context));
107583             }).call(svgIcon('#iD-icon-close'));
107584             headerEnter.append('h2').call(_t.append('map_data.title'));
107585             var body = selection.selectAll('.body').data([0]);
107586             body = body.enter().append('div').attr('class', 'body').merge(body);
107587             var editor = body.selectAll('.data-editor').data([0]); // enter/update
107588
107589             editor.enter().append('div').attr('class', 'modal-section data-editor').merge(editor).call(dataHeader.datum(_datum));
107590             var rte = body.selectAll('.raw-tag-editor').data([0]); // enter/update
107591
107592             rte.enter().append('div').attr('class', 'raw-tag-editor data-editor').merge(rte).call(rawTagEditor.tags(_datum && _datum.properties || {}).state('hover').render).selectAll('textarea.tag-text').attr('readonly', true).classed('readonly', true);
107593           }
107594
107595           dataEditor.datum = function (val) {
107596             if (!arguments.length) return _datum;
107597             _datum = val;
107598             return this;
107599           };
107600
107601           return dataEditor;
107602         }
107603
107604         function uiOsmoseDetails(context) {
107605           var _qaItem;
107606
107607           function issueString(d, type) {
107608             if (!d) return ''; // Issue strings are cached from Osmose API
107609
107610             var s = services.osmose.getStrings(d.itemType);
107611             return type in s ? s[type] : '';
107612           }
107613
107614           function osmoseDetails(selection) {
107615             var details = selection.selectAll('.error-details').data(_qaItem ? [_qaItem] : [], function (d) {
107616               return "".concat(d.id, "-").concat(d.status || 0);
107617             });
107618             details.exit().remove();
107619             var detailsEnter = details.enter().append('div').attr('class', 'error-details qa-details-container'); // Description
107620
107621             if (issueString(_qaItem, 'detail')) {
107622               var div = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107623               div.append('h4').call(_t.append('QA.keepRight.detail_description'));
107624               div.append('p').attr('class', 'qa-details-description-text').html(function (d) {
107625                 return issueString(d, 'detail');
107626               }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107627             } // Elements (populated later as data is requested)
107628
107629
107630             var detailsDiv = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107631             var elemsDiv = detailsEnter.append('div').attr('class', 'qa-details-subsection'); // Suggested Fix (mustn't exist for every issue type)
107632
107633             if (issueString(_qaItem, 'fix')) {
107634               var _div = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107635
107636               _div.append('h4').call(_t.append('QA.osmose.fix_title'));
107637
107638               _div.append('p').html(function (d) {
107639                 return issueString(d, 'fix');
107640               }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107641             } // Common Pitfalls (mustn't exist for every issue type)
107642
107643
107644             if (issueString(_qaItem, 'trap')) {
107645               var _div2 = detailsEnter.append('div').attr('class', 'qa-details-subsection');
107646
107647               _div2.append('h4').call(_t.append('QA.osmose.trap_title'));
107648
107649               _div2.append('p').html(function (d) {
107650                 return issueString(d, 'trap');
107651               }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107652             } // Save current item to check if UI changed by time request resolves
107653
107654
107655             var thisItem = _qaItem;
107656             services.osmose.loadIssueDetail(_qaItem).then(function (d) {
107657               // No details to add if there are no associated issue elements
107658               if (!d.elems || d.elems.length === 0) return; // Do nothing if UI has moved on by the time this resolves
107659
107660               if (context.selectedErrorID() !== thisItem.id && context.container().selectAll(".qaItem.osmose.hover.itemId-".concat(thisItem.id)).empty()) return; // Things like keys and values are dynamically added to a subtitle string
107661
107662               if (d.detail) {
107663                 detailsDiv.append('h4').call(_t.append('QA.osmose.detail_title'));
107664                 detailsDiv.append('p').html(function (d) {
107665                   return d.detail;
107666                 }).selectAll('a').attr('rel', 'noopener').attr('target', '_blank');
107667               } // Create list of linked issue elements
107668
107669
107670               elemsDiv.append('h4').call(_t.append('QA.osmose.elems_title'));
107671               elemsDiv.append('ul').selectAll('li').data(d.elems).enter().append('li').append('a').attr('href', '#').attr('class', 'error_entity_link').text(function (d) {
107672                 return d;
107673               }).each(function () {
107674                 var link = select(this);
107675                 var entityID = this.textContent;
107676                 var entity = context.hasEntity(entityID); // Add click handler
107677
107678                 link.on('mouseenter', function () {
107679                   utilHighlightEntities([entityID], true, context);
107680                 }).on('mouseleave', function () {
107681                   utilHighlightEntities([entityID], false, context);
107682                 }).on('click', function (d3_event) {
107683                   d3_event.preventDefault();
107684                   utilHighlightEntities([entityID], false, context);
107685                   var osmlayer = context.layers().layer('osm');
107686
107687                   if (!osmlayer.enabled()) {
107688                     osmlayer.enabled(true);
107689                   }
107690
107691                   context.map().centerZoom(d.loc, 20);
107692
107693                   if (entity) {
107694                     context.enter(modeSelect(context, [entityID]));
107695                   } else {
107696                     context.loadEntity(entityID, function (err, result) {
107697                       if (err) return;
107698                       var entity = result.data.find(function (e) {
107699                         return e.id === entityID;
107700                       });
107701                       if (entity) context.enter(modeSelect(context, [entityID]));
107702                     });
107703                   }
107704                 }); // Replace with friendly name if possible
107705                 // (The entity may not yet be loaded into the graph)
107706
107707                 if (entity) {
107708                   var name = utilDisplayName(entity); // try to use common name
107709
107710                   if (!name) {
107711                     var preset = _mainPresetIndex.match(entity, context.graph());
107712                     name = preset && !preset.isFallback() && preset.name(); // fallback to preset name
107713                   }
107714
107715                   if (name) {
107716                     this.innerText = name;
107717                   }
107718                 }
107719               }); // Don't hide entities related to this issue - #5880
107720
107721               context.features().forceVisible(d.elems);
107722               context.map().pan([0, 0]); // trigger a redraw
107723             })["catch"](function (err) {
107724               console.log(err); // eslint-disable-line no-console
107725             });
107726           }
107727
107728           osmoseDetails.issue = function (val) {
107729             if (!arguments.length) return _qaItem;
107730             _qaItem = val;
107731             return osmoseDetails;
107732           };
107733
107734           return osmoseDetails;
107735         }
107736
107737         function uiOsmoseHeader() {
107738           var _qaItem;
107739
107740           function issueTitle(d) {
107741             var unknown = _t('inspector.unknown');
107742             if (!d) return unknown; // Issue titles supplied by Osmose
107743
107744             var s = services.osmose.getStrings(d.itemType);
107745             return 'title' in s ? s.title : unknown;
107746           }
107747
107748           function osmoseHeader(selection) {
107749             var header = selection.selectAll('.qa-header').data(_qaItem ? [_qaItem] : [], function (d) {
107750               return "".concat(d.id, "-").concat(d.status || 0);
107751             });
107752             header.exit().remove();
107753             var headerEnter = header.enter().append('div').attr('class', 'qa-header');
107754             var svgEnter = headerEnter.append('div').attr('class', 'qa-header-icon').classed('new', function (d) {
107755               return d.id < 0;
107756             }).append('svg').attr('width', '20px').attr('height', '30px').attr('viewbox', '0 0 20 30').attr('class', function (d) {
107757               return "preset-icon-28 qaItem ".concat(d.service, " itemId-").concat(d.id, " itemType-").concat(d.itemType);
107758             });
107759             svgEnter.append('polygon').attr('fill', function (d) {
107760               return services.osmose.getColor(d.item);
107761             }).attr('class', 'qaItem-fill').attr('points', '16,3 4,3 1,6 1,17 4,20 7,20 10,27 13,20 16,20 19,17.033 19,6');
107762             svgEnter.append('use').attr('class', 'icon-annotation').attr('width', '13px').attr('height', '13px').attr('transform', 'translate(3.5, 5)').attr('xlink:href', function (d) {
107763               var picon = d.icon;
107764
107765               if (!picon) {
107766                 return '';
107767               } else {
107768                 var isMaki = /^maki-/.test(picon);
107769                 return "#".concat(picon).concat(isMaki ? '-11' : '');
107770               }
107771             });
107772             headerEnter.append('div').attr('class', 'qa-header-label').text(issueTitle);
107773           }
107774
107775           osmoseHeader.issue = function (val) {
107776             if (!arguments.length) return _qaItem;
107777             _qaItem = val;
107778             return osmoseHeader;
107779           };
107780
107781           return osmoseHeader;
107782         }
107783
107784         function uiViewOnOsmose() {
107785           var _qaItem;
107786
107787           function viewOnOsmose(selection) {
107788             var url;
107789
107790             if (services.osmose && _qaItem instanceof QAItem) {
107791               url = services.osmose.itemURL(_qaItem);
107792             }
107793
107794             var link = selection.selectAll('.view-on-osmose').data(url ? [url] : []); // exit
107795
107796             link.exit().remove(); // enter
107797
107798             var linkEnter = link.enter().append('a').attr('class', 'view-on-osmose').attr('target', '_blank').attr('rel', 'noopener') // security measure
107799             .attr('href', function (d) {
107800               return d;
107801             }).call(svgIcon('#iD-icon-out-link', 'inline'));
107802             linkEnter.append('span').call(_t.append('inspector.view_on_osmose'));
107803           }
107804
107805           viewOnOsmose.what = function (val) {
107806             if (!arguments.length) return _qaItem;
107807             _qaItem = val;
107808             return viewOnOsmose;
107809           };
107810
107811           return viewOnOsmose;
107812         }
107813
107814         function uiOsmoseEditor(context) {
107815           var dispatch = dispatch$8('change');
107816           var qaDetails = uiOsmoseDetails(context);
107817           var qaHeader = uiOsmoseHeader();
107818
107819           var _qaItem;
107820
107821           function osmoseEditor(selection) {
107822             var header = selection.selectAll('.header').data([0]);
107823             var headerEnter = header.enter().append('div').attr('class', 'header fillL');
107824             headerEnter.append('button').attr('class', 'close').attr('title', _t('icons.close')).on('click', function () {
107825               return context.enter(modeBrowse(context));
107826             }).call(svgIcon('#iD-icon-close'));
107827             headerEnter.append('h2').call(_t.append('QA.osmose.title'));
107828             var body = selection.selectAll('.body').data([0]);
107829             body = body.enter().append('div').attr('class', 'body').merge(body);
107830             var editor = body.selectAll('.qa-editor').data([0]);
107831             editor.enter().append('div').attr('class', 'modal-section qa-editor').merge(editor).call(qaHeader.issue(_qaItem)).call(qaDetails.issue(_qaItem)).call(osmoseSaveSection);
107832             var footer = selection.selectAll('.footer').data([0]);
107833             footer.enter().append('div').attr('class', 'footer').merge(footer).call(uiViewOnOsmose().what(_qaItem));
107834           }
107835
107836           function osmoseSaveSection(selection) {
107837             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
107838
107839             var isShown = _qaItem && isSelected;
107840             var saveSection = selection.selectAll('.qa-save').data(isShown ? [_qaItem] : [], function (d) {
107841               return "".concat(d.id, "-").concat(d.status || 0);
107842             }); // exit
107843
107844             saveSection.exit().remove(); // enter
107845
107846             var saveSectionEnter = saveSection.enter().append('div').attr('class', 'qa-save save-section cf'); // update
107847
107848             saveSection = saveSectionEnter.merge(saveSection).call(qaSaveButtons);
107849           }
107850
107851           function qaSaveButtons(selection) {
107852             var isSelected = _qaItem && _qaItem.id === context.selectedErrorID();
107853
107854             var buttonSection = selection.selectAll('.buttons').data(isSelected ? [_qaItem] : [], function (d) {
107855               return d.status + d.id;
107856             }); // exit
107857
107858             buttonSection.exit().remove(); // enter
107859
107860             var buttonEnter = buttonSection.enter().append('div').attr('class', 'buttons');
107861             buttonEnter.append('button').attr('class', 'button close-button action');
107862             buttonEnter.append('button').attr('class', 'button ignore-button action'); // update
107863
107864             buttonSection = buttonSection.merge(buttonEnter);
107865             buttonSection.select('.close-button').call(_t.append('QA.keepRight.close')).on('click.close', function (d3_event, d) {
107866               this.blur(); // avoid keeping focus on the button - #4641
107867
107868               var qaService = services.osmose;
107869
107870               if (qaService) {
107871                 d.newStatus = 'done';
107872                 qaService.postUpdate(d, function (err, item) {
107873                   return dispatch.call('change', item);
107874                 });
107875               }
107876             });
107877             buttonSection.select('.ignore-button').call(_t.append('QA.keepRight.ignore')).on('click.ignore', function (d3_event, d) {
107878               this.blur(); // avoid keeping focus on the button - #4641
107879
107880               var qaService = services.osmose;
107881
107882               if (qaService) {
107883                 d.newStatus = 'false';
107884                 qaService.postUpdate(d, function (err, item) {
107885                   return dispatch.call('change', item);
107886                 });
107887               }
107888             });
107889           } // NOTE: Don't change method name until UI v3 is merged
107890
107891
107892           osmoseEditor.error = function (val) {
107893             if (!arguments.length) return _qaItem;
107894             _qaItem = val;
107895             return osmoseEditor;
107896           };
107897
107898           return utilRebind(osmoseEditor, dispatch, 'on');
107899         }
107900
107901         function uiSidebar(context) {
107902           var inspector = uiInspector(context);
107903           var dataEditor = uiDataEditor(context);
107904           var noteEditor = uiNoteEditor(context);
107905           var improveOsmEditor = uiImproveOsmEditor(context);
107906           var keepRightEditor = uiKeepRightEditor(context);
107907           var osmoseEditor = uiOsmoseEditor(context);
107908
107909           var _current;
107910
107911           var _wasData = false;
107912           var _wasNote = false;
107913           var _wasQaItem = false; // use pointer events on supported platforms; fallback to mouse events
107914
107915           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
107916
107917           function sidebar(selection) {
107918             var container = context.container();
107919             var minWidth = 240;
107920             var sidebarWidth;
107921             var containerWidth;
107922             var dragOffset; // Set the initial width constraints
107923
107924             selection.style('min-width', minWidth + 'px').style('max-width', '400px').style('width', '33.3333%');
107925             var resizer = selection.append('div').attr('class', 'sidebar-resizer').on(_pointerPrefix + 'down.sidebar-resizer', pointerdown);
107926             var downPointerId, lastClientX, containerLocGetter;
107927
107928             function pointerdown(d3_event) {
107929               if (downPointerId) return;
107930               if ('button' in d3_event && d3_event.button !== 0) return;
107931               downPointerId = d3_event.pointerId || 'mouse';
107932               lastClientX = d3_event.clientX;
107933               containerLocGetter = utilFastMouse(container.node()); // offset from edge of sidebar-resizer
107934
107935               dragOffset = utilFastMouse(resizer.node())(d3_event)[0] - 1;
107936               sidebarWidth = selection.node().getBoundingClientRect().width;
107937               containerWidth = container.node().getBoundingClientRect().width;
107938               var widthPct = sidebarWidth / containerWidth * 100;
107939               selection.style('width', widthPct + '%') // lock in current width
107940               .style('max-width', '85%'); // but allow larger widths
107941
107942               resizer.classed('dragging', true);
107943               select(window).on('touchmove.sidebar-resizer', function (d3_event) {
107944                 // disable page scrolling while resizing on touch input
107945                 d3_event.preventDefault();
107946               }, {
107947                 passive: false
107948               }).on(_pointerPrefix + 'move.sidebar-resizer', pointermove).on(_pointerPrefix + 'up.sidebar-resizer pointercancel.sidebar-resizer', pointerup);
107949             }
107950
107951             function pointermove(d3_event) {
107952               if (downPointerId !== (d3_event.pointerId || 'mouse')) return;
107953               d3_event.preventDefault();
107954               var dx = d3_event.clientX - lastClientX;
107955               lastClientX = d3_event.clientX;
107956               var isRTL = _mainLocalizer.textDirection() === 'rtl';
107957               var scaleX = isRTL ? 0 : 1;
107958               var xMarginProperty = isRTL ? 'margin-right' : 'margin-left';
107959               var x = containerLocGetter(d3_event)[0] - dragOffset;
107960               sidebarWidth = isRTL ? containerWidth - x : x;
107961               var isCollapsed = selection.classed('collapsed');
107962               var shouldCollapse = sidebarWidth < minWidth;
107963               selection.classed('collapsed', shouldCollapse);
107964
107965               if (shouldCollapse) {
107966                 if (!isCollapsed) {
107967                   selection.style(xMarginProperty, '-400px').style('width', '400px');
107968                   context.ui().onResize([(sidebarWidth - dx) * scaleX, 0]);
107969                 }
107970               } else {
107971                 var widthPct = sidebarWidth / containerWidth * 100;
107972                 selection.style(xMarginProperty, null).style('width', widthPct + '%');
107973
107974                 if (isCollapsed) {
107975                   context.ui().onResize([-sidebarWidth * scaleX, 0]);
107976                 } else {
107977                   context.ui().onResize([-dx * scaleX, 0]);
107978                 }
107979               }
107980             }
107981
107982             function pointerup(d3_event) {
107983               if (downPointerId !== (d3_event.pointerId || 'mouse')) return;
107984               downPointerId = null;
107985               resizer.classed('dragging', false);
107986               select(window).on('touchmove.sidebar-resizer', null).on(_pointerPrefix + 'move.sidebar-resizer', null).on(_pointerPrefix + 'up.sidebar-resizer pointercancel.sidebar-resizer', null);
107987             }
107988
107989             var featureListWrap = selection.append('div').attr('class', 'feature-list-pane').call(uiFeatureList(context));
107990             var inspectorWrap = selection.append('div').attr('class', 'inspector-hidden inspector-wrap');
107991
107992             var hoverModeSelect = function hoverModeSelect(targets) {
107993               context.container().selectAll('.feature-list-item button').classed('hover', false);
107994
107995               if (context.selectedIDs().length > 1 && targets && targets.length) {
107996                 var elements = context.container().selectAll('.feature-list-item button').filter(function (node) {
107997                   return targets.indexOf(node) !== -1;
107998                 });
107999
108000                 if (!elements.empty()) {
108001                   elements.classed('hover', true);
108002                 }
108003               }
108004             };
108005
108006             sidebar.hoverModeSelect = throttle(hoverModeSelect, 200);
108007
108008             function hover(targets) {
108009               var datum = targets && targets.length && targets[0];
108010
108011               if (datum && datum.__featurehash__) {
108012                 // hovering on data
108013                 _wasData = true;
108014                 sidebar.show(dataEditor.datum(datum));
108015                 selection.selectAll('.sidebar-component').classed('inspector-hover', true);
108016               } else if (datum instanceof osmNote) {
108017                 if (context.mode().id === 'drag-note') return;
108018                 _wasNote = true;
108019                 var osm = services.osm;
108020
108021                 if (osm) {
108022                   datum = osm.getNote(datum.id); // marker may contain stale data - get latest
108023                 }
108024
108025                 sidebar.show(noteEditor.note(datum));
108026                 selection.selectAll('.sidebar-component').classed('inspector-hover', true);
108027               } else if (datum instanceof QAItem) {
108028                 _wasQaItem = true;
108029                 var errService = services[datum.service];
108030
108031                 if (errService) {
108032                   // marker may contain stale data - get latest
108033                   datum = errService.getError(datum.id);
108034                 } // Currently only three possible services
108035
108036
108037                 var errEditor;
108038
108039                 if (datum.service === 'keepRight') {
108040                   errEditor = keepRightEditor;
108041                 } else if (datum.service === 'osmose') {
108042                   errEditor = osmoseEditor;
108043                 } else {
108044                   errEditor = improveOsmEditor;
108045                 }
108046
108047                 context.container().selectAll('.qaItem.' + datum.service).classed('hover', function (d) {
108048                   return d.id === datum.id;
108049                 });
108050                 sidebar.show(errEditor.error(datum));
108051                 selection.selectAll('.sidebar-component').classed('inspector-hover', true);
108052               } else if (!_current && datum instanceof osmEntity) {
108053                 featureListWrap.classed('inspector-hidden', true);
108054                 inspectorWrap.classed('inspector-hidden', false).classed('inspector-hover', true);
108055
108056                 if (!inspector.entityIDs() || !utilArrayIdentical(inspector.entityIDs(), [datum.id]) || inspector.state() !== 'hover') {
108057                   inspector.state('hover').entityIDs([datum.id]).newFeature(false);
108058                   inspectorWrap.call(inspector);
108059                 }
108060               } else if (!_current) {
108061                 featureListWrap.classed('inspector-hidden', false);
108062                 inspectorWrap.classed('inspector-hidden', true);
108063                 inspector.state('hide');
108064               } else if (_wasData || _wasNote || _wasQaItem) {
108065                 _wasNote = false;
108066                 _wasData = false;
108067                 _wasQaItem = false;
108068                 context.container().selectAll('.note').classed('hover', false);
108069                 context.container().selectAll('.qaItem').classed('hover', false);
108070                 sidebar.hide();
108071               }
108072             }
108073
108074             sidebar.hover = throttle(hover, 200);
108075
108076             sidebar.intersects = function (extent) {
108077               var rect = selection.node().getBoundingClientRect();
108078               return extent.intersects([context.projection.invert([0, rect.height]), context.projection.invert([rect.width, 0])]);
108079             };
108080
108081             sidebar.select = function (ids, newFeature) {
108082               sidebar.hide();
108083
108084               if (ids && ids.length) {
108085                 var entity = ids.length === 1 && context.entity(ids[0]);
108086
108087                 if (entity && newFeature && selection.classed('collapsed')) {
108088                   // uncollapse the sidebar
108089                   var extent = entity.extent(context.graph());
108090                   sidebar.expand(sidebar.intersects(extent));
108091                 }
108092
108093                 featureListWrap.classed('inspector-hidden', true);
108094                 inspectorWrap.classed('inspector-hidden', false).classed('inspector-hover', false); // reload the UI even if the ids are the same since the entities
108095                 // themselves may have changed
108096
108097                 inspector.state('select').entityIDs(ids).newFeature(newFeature);
108098                 inspectorWrap.call(inspector);
108099               } else {
108100                 inspector.state('hide');
108101               }
108102             };
108103
108104             sidebar.showPresetList = function () {
108105               inspector.showList();
108106             };
108107
108108             sidebar.show = function (component, element) {
108109               featureListWrap.classed('inspector-hidden', true);
108110               inspectorWrap.classed('inspector-hidden', true);
108111               if (_current) _current.remove();
108112               _current = selection.append('div').attr('class', 'sidebar-component').call(component, element);
108113             };
108114
108115             sidebar.hide = function () {
108116               featureListWrap.classed('inspector-hidden', false);
108117               inspectorWrap.classed('inspector-hidden', true);
108118               if (_current) _current.remove();
108119               _current = null;
108120             };
108121
108122             sidebar.expand = function (moveMap) {
108123               if (selection.classed('collapsed')) {
108124                 sidebar.toggle(moveMap);
108125               }
108126             };
108127
108128             sidebar.collapse = function (moveMap) {
108129               if (!selection.classed('collapsed')) {
108130                 sidebar.toggle(moveMap);
108131               }
108132             };
108133
108134             sidebar.toggle = function (moveMap) {
108135               // Don't allow sidebar to toggle when the user is in the walkthrough.
108136               if (context.inIntro()) return;
108137               var isCollapsed = selection.classed('collapsed');
108138               var isCollapsing = !isCollapsed;
108139               var isRTL = _mainLocalizer.textDirection() === 'rtl';
108140               var scaleX = isRTL ? 0 : 1;
108141               var xMarginProperty = isRTL ? 'margin-right' : 'margin-left';
108142               sidebarWidth = selection.node().getBoundingClientRect().width; // switch from % to px
108143
108144               selection.style('width', sidebarWidth + 'px');
108145               var startMargin, endMargin, lastMargin;
108146
108147               if (isCollapsing) {
108148                 startMargin = lastMargin = 0;
108149                 endMargin = -sidebarWidth;
108150               } else {
108151                 startMargin = lastMargin = -sidebarWidth;
108152                 endMargin = 0;
108153               }
108154
108155               if (!isCollapsing) {
108156                 // unhide the sidebar's content before it transitions onscreen
108157                 selection.classed('collapsed', isCollapsing);
108158               }
108159
108160               selection.transition().style(xMarginProperty, endMargin + 'px').tween('panner', function () {
108161                 var i = d3_interpolateNumber(startMargin, endMargin);
108162                 return function (t) {
108163                   var dx = lastMargin - Math.round(i(t));
108164                   lastMargin = lastMargin - dx;
108165                   context.ui().onResize(moveMap ? undefined : [dx * scaleX, 0]);
108166                 };
108167               }).on('end', function () {
108168                 if (isCollapsing) {
108169                   // hide the sidebar's content after it transitions offscreen
108170                   selection.classed('collapsed', isCollapsing);
108171                 } // switch back from px to %
108172
108173
108174                 if (!isCollapsing) {
108175                   var containerWidth = container.node().getBoundingClientRect().width;
108176                   var widthPct = sidebarWidth / containerWidth * 100;
108177                   selection.style(xMarginProperty, null).style('width', widthPct + '%');
108178                 }
108179               });
108180             }; // toggle the sidebar collapse when double-clicking the resizer
108181
108182
108183             resizer.on('dblclick', function (d3_event) {
108184               d3_event.preventDefault();
108185
108186               if (d3_event.sourceEvent) {
108187                 d3_event.sourceEvent.preventDefault();
108188               }
108189
108190               sidebar.toggle();
108191             }); // ensure hover sidebar is closed when zooming out beyond editable zoom
108192
108193             context.map().on('crossEditableZoom.sidebar', function (within) {
108194               if (!within && !selection.select('.inspector-hover').empty()) {
108195                 hover([]);
108196               }
108197             });
108198           }
108199
108200           sidebar.showPresetList = function () {};
108201
108202           sidebar.hover = function () {};
108203
108204           sidebar.hover.cancel = function () {};
108205
108206           sidebar.intersects = function () {};
108207
108208           sidebar.select = function () {};
108209
108210           sidebar.show = function () {};
108211
108212           sidebar.hide = function () {};
108213
108214           sidebar.expand = function () {};
108215
108216           sidebar.collapse = function () {};
108217
108218           sidebar.toggle = function () {};
108219
108220           return sidebar;
108221         }
108222
108223         function modeDrawArea(context, wayID, startGraph, button) {
108224           var mode = {
108225             button: button,
108226             id: 'draw-area'
108227           };
108228           var behavior = behaviorDrawWay(context, wayID, mode, startGraph).on('rejectedSelfIntersection.modeDrawArea', function () {
108229             context.ui().flash.iconName('#iD-icon-no').label(_t.html('self_intersection.error.areas'))();
108230           });
108231           mode.wayID = wayID;
108232
108233           mode.enter = function () {
108234             context.install(behavior);
108235           };
108236
108237           mode.exit = function () {
108238             context.uninstall(behavior);
108239           };
108240
108241           mode.selectedIDs = function () {
108242             return [wayID];
108243           };
108244
108245           mode.activeID = function () {
108246             return behavior && behavior.activeID() || [];
108247           };
108248
108249           return mode;
108250         }
108251
108252         function modeAddArea(context, mode) {
108253           mode.id = 'add-area';
108254           var behavior = behaviorAddWay(context).on('start', start).on('startFromWay', startFromWay).on('startFromNode', startFromNode);
108255           var defaultTags = {
108256             area: 'yes'
108257           };
108258           if (mode.preset) defaultTags = mode.preset.setTags(defaultTags, 'area');
108259
108260           function actionClose(wayId) {
108261             return function (graph) {
108262               return graph.replace(graph.entity(wayId).close());
108263             };
108264           }
108265
108266           function start(loc) {
108267             var startGraph = context.graph();
108268             var node = osmNode({
108269               loc: loc
108270             });
108271             var way = osmWay({
108272               tags: defaultTags
108273             });
108274             context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id));
108275             context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
108276           }
108277
108278           function startFromWay(loc, edge) {
108279             var startGraph = context.graph();
108280             var node = osmNode({
108281               loc: loc
108282             });
108283             var way = osmWay({
108284               tags: defaultTags
108285             });
108286             context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id), actionAddMidpoint({
108287               loc: loc,
108288               edge: edge
108289             }, node));
108290             context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
108291           }
108292
108293           function startFromNode(node) {
108294             var startGraph = context.graph();
108295             var way = osmWay({
108296               tags: defaultTags
108297             });
108298             context.perform(actionAddEntity(way), actionAddVertex(way.id, node.id), actionClose(way.id));
108299             context.enter(modeDrawArea(context, way.id, startGraph, mode.button));
108300           }
108301
108302           mode.enter = function () {
108303             context.install(behavior);
108304           };
108305
108306           mode.exit = function () {
108307             context.uninstall(behavior);
108308           };
108309
108310           return mode;
108311         }
108312
108313         function modeAddLine(context, mode) {
108314           mode.id = 'add-line';
108315           var behavior = behaviorAddWay(context).on('start', start).on('startFromWay', startFromWay).on('startFromNode', startFromNode);
108316           var defaultTags = {};
108317           if (mode.preset) defaultTags = mode.preset.setTags(defaultTags, 'line');
108318
108319           function start(loc) {
108320             var startGraph = context.graph();
108321             var node = osmNode({
108322               loc: loc
108323             });
108324             var way = osmWay({
108325               tags: defaultTags
108326             });
108327             context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id));
108328             context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
108329           }
108330
108331           function startFromWay(loc, edge) {
108332             var startGraph = context.graph();
108333             var node = osmNode({
108334               loc: loc
108335             });
108336             var way = osmWay({
108337               tags: defaultTags
108338             });
108339             context.perform(actionAddEntity(node), actionAddEntity(way), actionAddVertex(way.id, node.id), actionAddMidpoint({
108340               loc: loc,
108341               edge: edge
108342             }, node));
108343             context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
108344           }
108345
108346           function startFromNode(node) {
108347             var startGraph = context.graph();
108348             var way = osmWay({
108349               tags: defaultTags
108350             });
108351             context.perform(actionAddEntity(way), actionAddVertex(way.id, node.id));
108352             context.enter(modeDrawLine(context, way.id, startGraph, mode.button));
108353           }
108354
108355           mode.enter = function () {
108356             context.install(behavior);
108357           };
108358
108359           mode.exit = function () {
108360             context.uninstall(behavior);
108361           };
108362
108363           return mode;
108364         }
108365
108366         function modeAddPoint(context, mode) {
108367           mode.id = 'add-point';
108368           var behavior = behaviorDraw(context).on('click', add).on('clickWay', addWay).on('clickNode', addNode).on('cancel', cancel).on('finish', cancel);
108369           var defaultTags = {};
108370           if (mode.preset) defaultTags = mode.preset.setTags(defaultTags, 'point');
108371
108372           function add(loc) {
108373             var node = osmNode({
108374               loc: loc,
108375               tags: defaultTags
108376             });
108377             context.perform(actionAddEntity(node), _t('operations.add.annotation.point'));
108378             enterSelectMode(node);
108379           }
108380
108381           function addWay(loc, edge) {
108382             var node = osmNode({
108383               tags: defaultTags
108384             });
108385             context.perform(actionAddMidpoint({
108386               loc: loc,
108387               edge: edge
108388             }, node), _t('operations.add.annotation.vertex'));
108389             enterSelectMode(node);
108390           }
108391
108392           function enterSelectMode(node) {
108393             context.enter(modeSelect(context, [node.id]).newFeature(true));
108394           }
108395
108396           function addNode(node) {
108397             if (Object.keys(defaultTags).length === 0) {
108398               enterSelectMode(node);
108399               return;
108400             }
108401
108402             var tags = Object.assign({}, node.tags); // shallow copy
108403
108404             for (var key in defaultTags) {
108405               tags[key] = defaultTags[key];
108406             }
108407
108408             context.perform(actionChangeTags(node.id, tags), _t('operations.add.annotation.point'));
108409             enterSelectMode(node);
108410           }
108411
108412           function cancel() {
108413             context.enter(modeBrowse(context));
108414           }
108415
108416           mode.enter = function () {
108417             context.install(behavior);
108418           };
108419
108420           mode.exit = function () {
108421             context.uninstall(behavior);
108422           };
108423
108424           return mode;
108425         }
108426
108427         function modeSelectNote(context, selectedNoteID) {
108428           var mode = {
108429             id: 'select-note',
108430             button: 'browse'
108431           };
108432
108433           var _keybinding = utilKeybinding('select-note');
108434
108435           var _noteEditor = uiNoteEditor(context).on('change', function () {
108436             context.map().pan([0, 0]); // trigger a redraw
108437
108438             var note = checkSelectedID();
108439             if (!note) return;
108440             context.ui().sidebar.show(_noteEditor.note(note));
108441           });
108442
108443           var _behaviors = [behaviorBreathe(), behaviorHover(context), behaviorSelect(context), behaviorLasso(context), modeDragNode(context).behavior, modeDragNote(context).behavior];
108444           var _newFeature = false;
108445
108446           function checkSelectedID() {
108447             if (!services.osm) return;
108448             var note = services.osm.getNote(selectedNoteID);
108449
108450             if (!note) {
108451               context.enter(modeBrowse(context));
108452             }
108453
108454             return note;
108455           } // class the note as selected, or return to browse mode if the note is gone
108456
108457
108458           function selectNote(d3_event, drawn) {
108459             if (!checkSelectedID()) return;
108460             var selection = context.surface().selectAll('.layer-notes .note-' + selectedNoteID);
108461
108462             if (selection.empty()) {
108463               // Return to browse mode if selected DOM elements have
108464               // disappeared because the user moved them out of view..
108465               var source = d3_event && d3_event.type === 'zoom' && d3_event.sourceEvent;
108466
108467               if (drawn && source && (source.type === 'pointermove' || source.type === 'mousemove' || source.type === 'touchmove')) {
108468                 context.enter(modeBrowse(context));
108469               }
108470             } else {
108471               selection.classed('selected', true);
108472               context.selectedNoteID(selectedNoteID);
108473             }
108474           }
108475
108476           function esc() {
108477             if (context.container().select('.combobox').size()) return;
108478             context.enter(modeBrowse(context));
108479           }
108480
108481           mode.zoomToSelected = function () {
108482             if (!services.osm) return;
108483             var note = services.osm.getNote(selectedNoteID);
108484
108485             if (note) {
108486               context.map().centerZoomEase(note.loc, 20);
108487             }
108488           };
108489
108490           mode.newFeature = function (val) {
108491             if (!arguments.length) return _newFeature;
108492             _newFeature = val;
108493             return mode;
108494           };
108495
108496           mode.enter = function () {
108497             var note = checkSelectedID();
108498             if (!note) return;
108499
108500             _behaviors.forEach(context.install);
108501
108502             _keybinding.on(_t('inspector.zoom_to.key'), mode.zoomToSelected).on('⎋', esc, true);
108503
108504             select(document).call(_keybinding);
108505             selectNote();
108506             var sidebar = context.ui().sidebar;
108507             sidebar.show(_noteEditor.note(note).newNote(_newFeature)); // expand the sidebar, avoid obscuring the note if needed
108508
108509             sidebar.expand(sidebar.intersects(note.extent()));
108510             context.map().on('drawn.select', selectNote);
108511           };
108512
108513           mode.exit = function () {
108514             _behaviors.forEach(context.uninstall);
108515
108516             select(document).call(_keybinding.unbind);
108517             context.surface().selectAll('.layer-notes .selected').classed('selected hover', false);
108518             context.map().on('drawn.select', null);
108519             context.ui().sidebar.hide();
108520             context.selectedNoteID(null);
108521           };
108522
108523           return mode;
108524         }
108525
108526         function modeAddNote(context) {
108527           var mode = {
108528             id: 'add-note',
108529             button: 'note',
108530             description: _t.html('modes.add_note.description'),
108531             key: _t('modes.add_note.key')
108532           };
108533           var behavior = behaviorDraw(context).on('click', add).on('cancel', cancel).on('finish', cancel);
108534
108535           function add(loc) {
108536             var osm = services.osm;
108537             if (!osm) return;
108538             var note = osmNote({
108539               loc: loc,
108540               status: 'open',
108541               comments: []
108542             });
108543             osm.replaceNote(note); // force a reraw (there is no history change that would otherwise do this)
108544
108545             context.map().pan([0, 0]);
108546             context.selectedNoteID(note.id).enter(modeSelectNote(context, note.id).newFeature(true));
108547           }
108548
108549           function cancel() {
108550             context.enter(modeBrowse(context));
108551           }
108552
108553           mode.enter = function () {
108554             context.install(behavior);
108555           };
108556
108557           mode.exit = function () {
108558             context.uninstall(behavior);
108559           };
108560
108561           return mode;
108562         }
108563
108564         function modeSave(context) {
108565           var mode = {
108566             id: 'save'
108567           };
108568           var keybinding = utilKeybinding('modeSave');
108569           var commit = uiCommit(context).on('cancel', cancel);
108570
108571           var _conflictsUi; // uiConflicts
108572
108573
108574           var _location;
108575
108576           var _success;
108577
108578           var uploader = context.uploader().on('saveStarted.modeSave', function () {
108579             keybindingOff();
108580           }) // fire off some async work that we want to be ready later
108581           .on('willAttemptUpload.modeSave', prepareForSuccess).on('progressChanged.modeSave', showProgress).on('resultNoChanges.modeSave', function () {
108582             cancel();
108583           }).on('resultErrors.modeSave', showErrors).on('resultConflicts.modeSave', showConflicts).on('resultSuccess.modeSave', showSuccess);
108584
108585           function cancel() {
108586             context.enter(modeBrowse(context));
108587           }
108588
108589           function showProgress(num, total) {
108590             var modal = context.container().select('.loading-modal .modal-section');
108591             var progress = modal.selectAll('.progress').data([0]); // enter/update
108592
108593             progress.enter().append('div').attr('class', 'progress').merge(progress).text(_t('save.conflict_progress', {
108594               num: num,
108595               total: total
108596             }));
108597           }
108598
108599           function showConflicts(changeset, conflicts, origChanges) {
108600             var selection = context.container().select('.sidebar').append('div').attr('class', 'sidebar-component');
108601             context.container().selectAll('.main-content').classed('active', true).classed('inactive', false);
108602             _conflictsUi = uiConflicts(context).conflictList(conflicts).origChanges(origChanges).on('cancel', function () {
108603               context.container().selectAll('.main-content').classed('active', false).classed('inactive', true);
108604               selection.remove();
108605               keybindingOn();
108606               uploader.cancelConflictResolution();
108607             }).on('save', function () {
108608               context.container().selectAll('.main-content').classed('active', false).classed('inactive', true);
108609               selection.remove();
108610               uploader.processResolvedConflicts(changeset);
108611             });
108612             selection.call(_conflictsUi);
108613           }
108614
108615           function showErrors(errors) {
108616             keybindingOn();
108617             var selection = uiConfirm(context.container());
108618             selection.select('.modal-section.header').append('h3').text(_t('save.error'));
108619             addErrors(selection, errors);
108620             selection.okButton();
108621           }
108622
108623           function addErrors(selection, data) {
108624             var message = selection.select('.modal-section.message-text');
108625             var items = message.selectAll('.error-container').data(data);
108626             var enter = items.enter().append('div').attr('class', 'error-container');
108627             enter.append('a').attr('class', 'error-description').attr('href', '#').classed('hide-toggle', true).text(function (d) {
108628               return d.msg || _t('save.unknown_error_details');
108629             }).on('click', function (d3_event) {
108630               d3_event.preventDefault();
108631               var error = select(this);
108632               var detail = select(this.nextElementSibling);
108633               var exp = error.classed('expanded');
108634               detail.style('display', exp ? 'none' : 'block');
108635               error.classed('expanded', !exp);
108636             });
108637             var details = enter.append('div').attr('class', 'error-detail-container').style('display', 'none');
108638             details.append('ul').attr('class', 'error-detail-list').selectAll('li').data(function (d) {
108639               return d.details || [];
108640             }).enter().append('li').attr('class', 'error-detail-item').text(function (d) {
108641               return d;
108642             });
108643             items.exit().remove();
108644           }
108645
108646           function showSuccess(changeset) {
108647             commit.reset();
108648
108649             var ui = _success.changeset(changeset).location(_location).on('cancel', function () {
108650               context.ui().sidebar.hide();
108651             });
108652
108653             context.enter(modeBrowse(context).sidebar(ui));
108654           }
108655
108656           function keybindingOn() {
108657             select(document).call(keybinding.on('⎋', cancel, true));
108658           }
108659
108660           function keybindingOff() {
108661             select(document).call(keybinding.unbind);
108662           } // Reverse geocode current map location so we can display a message on
108663           // the success screen like "Thank you for editing around place, region."
108664
108665
108666           function prepareForSuccess() {
108667             _success = uiSuccess(context);
108668             _location = null;
108669             if (!services.geocoder) return;
108670             services.geocoder.reverse(context.map().center(), function (err, result) {
108671               if (err || !result || !result.address) return;
108672               var addr = result.address;
108673               var place = addr && (addr.town || addr.city || addr.county) || '';
108674               var region = addr && (addr.state || addr.country) || '';
108675               var separator = place && region ? _t('success.thank_you_where.separator') : '';
108676               _location = _t('success.thank_you_where.format', {
108677                 place: place,
108678                 separator: separator,
108679                 region: region
108680               });
108681             });
108682           }
108683
108684           mode.selectedIDs = function () {
108685             return _conflictsUi ? _conflictsUi.shownEntityIds() : [];
108686           };
108687
108688           mode.enter = function () {
108689             // Show sidebar
108690             context.ui().sidebar.expand();
108691
108692             function done() {
108693               context.ui().sidebar.show(commit);
108694             }
108695
108696             keybindingOn();
108697             context.container().selectAll('.main-content').classed('active', false).classed('inactive', true);
108698             var osm = context.connection();
108699
108700             if (!osm) {
108701               cancel();
108702               return;
108703             }
108704
108705             if (osm.authenticated()) {
108706               done();
108707             } else {
108708               osm.authenticate(function (err) {
108709                 if (err) {
108710                   cancel();
108711                 } else {
108712                   done();
108713                 }
108714               });
108715             }
108716           };
108717
108718           mode.exit = function () {
108719             keybindingOff();
108720             context.container().selectAll('.main-content').classed('active', true).classed('inactive', false);
108721             context.ui().sidebar.hide();
108722           };
108723
108724           return mode;
108725         }
108726
108727         function modeSelectError(context, selectedErrorID, selectedErrorService) {
108728           var mode = {
108729             id: 'select-error',
108730             button: 'browse'
108731           };
108732           var keybinding = utilKeybinding('select-error');
108733           var errorService = services[selectedErrorService];
108734           var errorEditor;
108735
108736           switch (selectedErrorService) {
108737             case 'improveOSM':
108738               errorEditor = uiImproveOsmEditor(context).on('change', function () {
108739                 context.map().pan([0, 0]); // trigger a redraw
108740
108741                 var error = checkSelectedID();
108742                 if (!error) return;
108743                 context.ui().sidebar.show(errorEditor.error(error));
108744               });
108745               break;
108746
108747             case 'keepRight':
108748               errorEditor = uiKeepRightEditor(context).on('change', function () {
108749                 context.map().pan([0, 0]); // trigger a redraw
108750
108751                 var error = checkSelectedID();
108752                 if (!error) return;
108753                 context.ui().sidebar.show(errorEditor.error(error));
108754               });
108755               break;
108756
108757             case 'osmose':
108758               errorEditor = uiOsmoseEditor(context).on('change', function () {
108759                 context.map().pan([0, 0]); // trigger a redraw
108760
108761                 var error = checkSelectedID();
108762                 if (!error) return;
108763                 context.ui().sidebar.show(errorEditor.error(error));
108764               });
108765               break;
108766           }
108767
108768           var behaviors = [behaviorBreathe(), behaviorHover(context), behaviorSelect(context), behaviorLasso(context), modeDragNode(context).behavior, modeDragNote(context).behavior];
108769
108770           function checkSelectedID() {
108771             if (!errorService) return;
108772             var error = errorService.getError(selectedErrorID);
108773
108774             if (!error) {
108775               context.enter(modeBrowse(context));
108776             }
108777
108778             return error;
108779           }
108780
108781           mode.zoomToSelected = function () {
108782             if (!errorService) return;
108783             var error = errorService.getError(selectedErrorID);
108784
108785             if (error) {
108786               context.map().centerZoomEase(error.loc, 20);
108787             }
108788           };
108789
108790           mode.enter = function () {
108791             var error = checkSelectedID();
108792             if (!error) return;
108793             behaviors.forEach(context.install);
108794             keybinding.on(_t('inspector.zoom_to.key'), mode.zoomToSelected).on('⎋', esc, true);
108795             select(document).call(keybinding);
108796             selectError();
108797             var sidebar = context.ui().sidebar;
108798             sidebar.show(errorEditor.error(error));
108799             context.map().on('drawn.select-error', selectError); // class the error as selected, or return to browse mode if the error is gone
108800
108801             function selectError(d3_event, drawn) {
108802               if (!checkSelectedID()) return;
108803               var selection = context.surface().selectAll('.itemId-' + selectedErrorID + '.' + selectedErrorService);
108804
108805               if (selection.empty()) {
108806                 // Return to browse mode if selected DOM elements have
108807                 // disappeared because the user moved them out of view..
108808                 var source = d3_event && d3_event.type === 'zoom' && d3_event.sourceEvent;
108809
108810                 if (drawn && source && (source.type === 'pointermove' || source.type === 'mousemove' || source.type === 'touchmove')) {
108811                   context.enter(modeBrowse(context));
108812                 }
108813               } else {
108814                 selection.classed('selected', true);
108815                 context.selectedErrorID(selectedErrorID);
108816               }
108817             }
108818
108819             function esc() {
108820               if (context.container().select('.combobox').size()) return;
108821               context.enter(modeBrowse(context));
108822             }
108823           };
108824
108825           mode.exit = function () {
108826             behaviors.forEach(context.uninstall);
108827             select(document).call(keybinding.unbind);
108828             context.surface().selectAll('.qaItem.selected').classed('selected hover', false);
108829             context.map().on('drawn.select-error', null);
108830             context.ui().sidebar.hide();
108831             context.selectedErrorID(null);
108832             context.features().forceVisible([]);
108833           };
108834
108835           return mode;
108836         }
108837
108838         function uiToolOldDrawModes(context) {
108839           var tool = {
108840             id: 'old_modes',
108841             label: _t.html('toolbar.add_feature')
108842           };
108843           var modes = [modeAddPoint(context, {
108844             title: _t.html('modes.add_point.title'),
108845             button: 'point',
108846             description: _t.html('modes.add_point.description'),
108847             preset: _mainPresetIndex.item('point'),
108848             key: '1'
108849           }), modeAddLine(context, {
108850             title: _t.html('modes.add_line.title'),
108851             button: 'line',
108852             description: _t.html('modes.add_line.description'),
108853             preset: _mainPresetIndex.item('line'),
108854             key: '2'
108855           }), modeAddArea(context, {
108856             title: _t.html('modes.add_area.title'),
108857             button: 'area',
108858             description: _t.html('modes.add_area.description'),
108859             preset: _mainPresetIndex.item('area'),
108860             key: '3'
108861           })];
108862
108863           function enabled() {
108864             return osmEditable();
108865           }
108866
108867           function osmEditable() {
108868             return context.editable();
108869           }
108870
108871           modes.forEach(function (mode) {
108872             context.keybinding().on(mode.key, function () {
108873               if (!enabled()) return;
108874
108875               if (mode.id === context.mode().id) {
108876                 context.enter(modeBrowse(context));
108877               } else {
108878                 context.enter(mode);
108879               }
108880             });
108881           });
108882
108883           tool.render = function (selection) {
108884             var wrap = selection.append('div').attr('class', 'joined').style('display', 'flex');
108885
108886             var debouncedUpdate = debounce(update, 500, {
108887               leading: true,
108888               trailing: true
108889             });
108890
108891             context.map().on('move.modes', debouncedUpdate).on('drawn.modes', debouncedUpdate);
108892             context.on('enter.modes', update);
108893             update();
108894
108895             function update() {
108896               var buttons = wrap.selectAll('button.add-button').data(modes, function (d) {
108897                 return d.id;
108898               }); // exit
108899
108900               buttons.exit().remove(); // enter
108901
108902               var buttonsEnter = buttons.enter().append('button').attr('class', function (d) {
108903                 return d.id + ' add-button bar-button';
108904               }).on('click.mode-buttons', function (d3_event, d) {
108905                 if (!enabled()) return; // When drawing, ignore accidental clicks on mode buttons - #4042
108906
108907                 var currMode = context.mode().id;
108908                 if (/^draw/.test(currMode)) return;
108909
108910                 if (d.id === currMode) {
108911                   context.enter(modeBrowse(context));
108912                 } else {
108913                   context.enter(d);
108914                 }
108915               }).call(uiTooltip().placement('bottom').title(function (d) {
108916                 return d.description;
108917               }).keys(function (d) {
108918                 return [d.key];
108919               }).scrollContainer(context.container().select('.top-toolbar')));
108920               buttonsEnter.each(function (d) {
108921                 select(this).call(svgIcon('#iD-icon-' + d.button));
108922               });
108923               buttonsEnter.append('span').attr('class', 'label').html(function (mode) {
108924                 return mode.title;
108925               }); // if we are adding/removing the buttons, check if toolbar has overflowed
108926
108927               if (buttons.enter().size() || buttons.exit().size()) {
108928                 context.ui().checkOverflow('.top-toolbar', true);
108929               } // update
108930
108931
108932               buttons = buttons.merge(buttonsEnter).attr('aria-disabled', function (d) {
108933                 return !enabled();
108934               }).classed('disabled', function (d) {
108935                 return !enabled();
108936               }).attr('aria-pressed', function (d) {
108937                 return context.mode() && context.mode().button === d.button;
108938               }).classed('active', function (d) {
108939                 return context.mode() && context.mode().button === d.button;
108940               });
108941             }
108942           };
108943
108944           return tool;
108945         }
108946
108947         function uiToolNotes(context) {
108948           var tool = {
108949             id: 'notes',
108950             label: _t.html('modes.add_note.label')
108951           };
108952           var mode = modeAddNote(context);
108953
108954           function enabled() {
108955             return notesEnabled() && notesEditable();
108956           }
108957
108958           function notesEnabled() {
108959             var noteLayer = context.layers().layer('notes');
108960             return noteLayer && noteLayer.enabled();
108961           }
108962
108963           function notesEditable() {
108964             var mode = context.mode();
108965             return context.map().notesEditable() && mode && mode.id !== 'save';
108966           }
108967
108968           context.keybinding().on(mode.key, function () {
108969             if (!enabled()) return;
108970
108971             if (mode.id === context.mode().id) {
108972               context.enter(modeBrowse(context));
108973             } else {
108974               context.enter(mode);
108975             }
108976           });
108977
108978           tool.render = function (selection) {
108979             var debouncedUpdate = debounce(update, 500, {
108980               leading: true,
108981               trailing: true
108982             });
108983
108984             context.map().on('move.notes', debouncedUpdate).on('drawn.notes', debouncedUpdate);
108985             context.on('enter.notes', update);
108986             update();
108987
108988             function update() {
108989               var showNotes = notesEnabled();
108990               var data = showNotes ? [mode] : [];
108991               var buttons = selection.selectAll('button.add-button').data(data, function (d) {
108992                 return d.id;
108993               }); // exit
108994
108995               buttons.exit().remove(); // enter
108996
108997               var buttonsEnter = buttons.enter().append('button').attr('class', function (d) {
108998                 return d.id + ' add-button bar-button';
108999               }).on('click.notes', function (d3_event, d) {
109000                 if (!enabled()) return; // When drawing, ignore accidental clicks on mode buttons - #4042
109001
109002                 var currMode = context.mode().id;
109003                 if (/^draw/.test(currMode)) return;
109004
109005                 if (d.id === currMode) {
109006                   context.enter(modeBrowse(context));
109007                 } else {
109008                   context.enter(d);
109009                 }
109010               }).call(uiTooltip().placement('bottom').title(function (d) {
109011                 return d.description;
109012               }).keys(function (d) {
109013                 return [d.key];
109014               }).scrollContainer(context.container().select('.top-toolbar')));
109015               buttonsEnter.each(function (d) {
109016                 select(this).call(svgIcon(d.icon || '#iD-icon-' + d.button));
109017               }); // if we are adding/removing the buttons, check if toolbar has overflowed
109018
109019               if (buttons.enter().size() || buttons.exit().size()) {
109020                 context.ui().checkOverflow('.top-toolbar', true);
109021               } // update
109022
109023
109024               buttons = buttons.merge(buttonsEnter).classed('disabled', function (d) {
109025                 return !enabled();
109026               }).attr('aria-disabled', function (d) {
109027                 return !enabled();
109028               }).classed('active', function (d) {
109029                 return context.mode() && context.mode().button === d.button;
109030               }).attr('aria-pressed', function (d) {
109031                 return context.mode() && context.mode().button === d.button;
109032               });
109033             }
109034           };
109035
109036           tool.uninstall = function () {
109037             context.on('enter.editor.notes', null).on('exit.editor.notes', null).on('enter.notes', null);
109038             context.map().on('move.notes', null).on('drawn.notes', null);
109039           };
109040
109041           return tool;
109042         }
109043
109044         function uiToolSave(context) {
109045           var tool = {
109046             id: 'save',
109047             label: _t.html('save.title')
109048           };
109049           var button = null;
109050           var tooltipBehavior = null;
109051           var history = context.history();
109052           var key = uiCmd('⌘S');
109053           var _numChanges = 0;
109054
109055           function isSaving() {
109056             var mode = context.mode();
109057             return mode && mode.id === 'save';
109058           }
109059
109060           function isDisabled() {
109061             return _numChanges === 0 || isSaving();
109062           }
109063
109064           function save(d3_event) {
109065             d3_event.preventDefault();
109066
109067             if (!context.inIntro() && !isSaving() && history.hasChanges()) {
109068               context.enter(modeSave(context));
109069             }
109070           }
109071
109072           function bgColor() {
109073             var step;
109074
109075             if (_numChanges === 0) {
109076               return null;
109077             } else if (_numChanges <= 50) {
109078               step = _numChanges / 50;
109079               return d3_interpolateRgb('#fff', '#ff8')(step); // white -> yellow
109080             } else {
109081               step = Math.min((_numChanges - 50) / 50, 1.0);
109082               return d3_interpolateRgb('#ff8', '#f88')(step); // yellow -> red
109083             }
109084           }
109085
109086           function updateCount() {
109087             var val = history.difference().summary().length;
109088             if (val === _numChanges) return;
109089             _numChanges = val;
109090
109091             if (tooltipBehavior) {
109092               tooltipBehavior.title(_t.html(_numChanges > 0 ? 'save.help' : 'save.no_changes')).keys([key]);
109093             }
109094
109095             if (button) {
109096               button.classed('disabled', isDisabled()).style('background', bgColor());
109097               button.select('span.count').text(_numChanges);
109098             }
109099           }
109100
109101           tool.render = function (selection) {
109102             tooltipBehavior = uiTooltip().placement('bottom').title(_t.html('save.no_changes')).keys([key]).scrollContainer(context.container().select('.top-toolbar'));
109103             var lastPointerUpType;
109104             button = selection.append('button').attr('class', 'save disabled bar-button').on('pointerup', function (d3_event) {
109105               lastPointerUpType = d3_event.pointerType;
109106             }).on('click', function (d3_event) {
109107               save(d3_event);
109108
109109               if (_numChanges === 0 && (lastPointerUpType === 'touch' || lastPointerUpType === 'pen')) {
109110                 // there are no tooltips for touch interactions so flash feedback instead
109111                 context.ui().flash.duration(2000).iconName('#iD-icon-save').iconClass('disabled').label(_t.html('save.no_changes'))();
109112               }
109113
109114               lastPointerUpType = null;
109115             }).call(tooltipBehavior);
109116             button.call(svgIcon('#iD-icon-save'));
109117             button.append('span').attr('class', 'count').attr('aria-hidden', 'true').text('0');
109118             updateCount();
109119             context.keybinding().on(key, save, true);
109120             context.history().on('change.save', updateCount);
109121             context.on('enter.save', function () {
109122               if (button) {
109123                 button.classed('disabled', isDisabled());
109124
109125                 if (isSaving()) {
109126                   button.call(tooltipBehavior.hide);
109127                 }
109128               }
109129             });
109130           };
109131
109132           tool.uninstall = function () {
109133             context.keybinding().off(key, true);
109134             context.history().on('change.save', null);
109135             context.on('enter.save', null);
109136             button = null;
109137             tooltipBehavior = null;
109138           };
109139
109140           return tool;
109141         }
109142
109143         function uiToolSidebarToggle(context) {
109144           var tool = {
109145             id: 'sidebar_toggle',
109146             label: _t.html('toolbar.inspect')
109147           };
109148
109149           tool.render = function (selection) {
109150             selection.append('button').attr('class', 'bar-button').attr('aria-label', _t('sidebar.tooltip')).on('click', function () {
109151               context.ui().sidebar.toggle();
109152             }).call(uiTooltip().placement('bottom').title(_t.html('sidebar.tooltip')).keys([_t('sidebar.key')]).scrollContainer(context.container().select('.top-toolbar'))).call(svgIcon('#iD-icon-sidebar-' + (_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left')));
109153           };
109154
109155           return tool;
109156         }
109157
109158         function uiToolUndoRedo(context) {
109159           var tool = {
109160             id: 'undo_redo',
109161             label: _t.html('toolbar.undo_redo')
109162           };
109163           var commands = [{
109164             id: 'undo',
109165             cmd: uiCmd('⌘Z'),
109166             action: function action() {
109167               context.undo();
109168             },
109169             annotation: function annotation() {
109170               return context.history().undoAnnotation();
109171             },
109172             icon: 'iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'redo' : 'undo')
109173           }, {
109174             id: 'redo',
109175             cmd: uiCmd('⌘⇧Z'),
109176             action: function action() {
109177               context.redo();
109178             },
109179             annotation: function annotation() {
109180               return context.history().redoAnnotation();
109181             },
109182             icon: 'iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'undo' : 'redo')
109183           }];
109184
109185           function editable() {
109186             return context.mode() && context.mode().id !== 'save' && context.map().editableDataEnabled(true
109187             /* ignore min zoom */
109188             );
109189           }
109190
109191           tool.render = function (selection) {
109192             var tooltipBehavior = uiTooltip().placement('bottom').title(function (d) {
109193               return d.annotation() ? _t.html(d.id + '.tooltip', {
109194                 action: d.annotation()
109195               }) : _t.html(d.id + '.nothing');
109196             }).keys(function (d) {
109197               return [d.cmd];
109198             }).scrollContainer(context.container().select('.top-toolbar'));
109199             var lastPointerUpType;
109200             var buttons = selection.selectAll('button').data(commands).enter().append('button').attr('class', function (d) {
109201               return 'disabled ' + d.id + '-button bar-button';
109202             }).on('pointerup', function (d3_event) {
109203               // `pointerup` is always called before `click`
109204               lastPointerUpType = d3_event.pointerType;
109205             }).on('click', function (d3_event, d) {
109206               d3_event.preventDefault();
109207               var annotation = d.annotation();
109208
109209               if (editable() && annotation) {
109210                 d.action();
109211               }
109212
109213               if (editable() && (lastPointerUpType === 'touch' || lastPointerUpType === 'pen')) {
109214                 // there are no tooltips for touch interactions so flash feedback instead
109215                 var text = annotation ? _t.html(d.id + '.tooltip', {
109216                   action: annotation
109217                 }) : _t.html(d.id + '.nothing');
109218                 context.ui().flash.duration(2000).iconName('#' + d.icon).iconClass(annotation ? '' : 'disabled').label(text)();
109219               }
109220
109221               lastPointerUpType = null;
109222             }).call(tooltipBehavior);
109223             buttons.each(function (d) {
109224               select(this).call(svgIcon('#' + d.icon));
109225             });
109226             context.keybinding().on(commands[0].cmd, function (d3_event) {
109227               d3_event.preventDefault();
109228               if (editable()) commands[0].action();
109229             }).on(commands[1].cmd, function (d3_event) {
109230               d3_event.preventDefault();
109231               if (editable()) commands[1].action();
109232             });
109233
109234             var debouncedUpdate = debounce(update, 500, {
109235               leading: true,
109236               trailing: true
109237             });
109238
109239             context.map().on('move.undo_redo', debouncedUpdate).on('drawn.undo_redo', debouncedUpdate);
109240             context.history().on('change.undo_redo', function (difference) {
109241               if (difference) update();
109242             });
109243             context.on('enter.undo_redo', update);
109244
109245             function update() {
109246               buttons.classed('disabled', function (d) {
109247                 return !editable() || !d.annotation();
109248               }).each(function () {
109249                 var selection = select(this);
109250
109251                 if (!selection.select('.tooltip.in').empty()) {
109252                   selection.call(tooltipBehavior.updateContent);
109253                 }
109254               });
109255             }
109256           };
109257
109258           tool.uninstall = function () {
109259             context.keybinding().off(commands[0].cmd).off(commands[1].cmd);
109260             context.map().on('move.undo_redo', null).on('drawn.undo_redo', null);
109261             context.history().on('change.undo_redo', null);
109262             context.on('enter.undo_redo', null);
109263           };
109264
109265           return tool;
109266         }
109267
109268         function uiTopToolbar(context) {
109269           var sidebarToggle = uiToolSidebarToggle(context),
109270               modes = uiToolOldDrawModes(context),
109271               notes = uiToolNotes(context),
109272               undoRedo = uiToolUndoRedo(context),
109273               save = uiToolSave(context);
109274
109275           function notesEnabled() {
109276             var noteLayer = context.layers().layer('notes');
109277             return noteLayer && noteLayer.enabled();
109278           }
109279
109280           function topToolbar(bar) {
109281             bar.on('wheel.topToolbar', function (d3_event) {
109282               if (!d3_event.deltaX) {
109283                 // translate vertical scrolling into horizontal scrolling in case
109284                 // the user doesn't have an input device that can scroll horizontally
109285                 bar.node().scrollLeft += d3_event.deltaY;
109286               }
109287             });
109288
109289             var debouncedUpdate = debounce(update, 500, {
109290               leading: true,
109291               trailing: true
109292             });
109293
109294             context.layers().on('change.topToolbar', debouncedUpdate);
109295             update();
109296
109297             function update() {
109298               var tools = [sidebarToggle, 'spacer', modes];
109299               tools.push('spacer');
109300
109301               if (notesEnabled()) {
109302                 tools = tools.concat([notes, 'spacer']);
109303               }
109304
109305               tools = tools.concat([undoRedo, save]);
109306               var toolbarItems = bar.selectAll('.toolbar-item').data(tools, function (d) {
109307                 return d.id || d;
109308               });
109309               toolbarItems.exit().each(function (d) {
109310                 if (d.uninstall) {
109311                   d.uninstall();
109312                 }
109313               }).remove();
109314               var itemsEnter = toolbarItems.enter().append('div').attr('class', function (d) {
109315                 var classes = 'toolbar-item ' + (d.id || d).replace('_', '-');
109316                 if (d.klass) classes += ' ' + d.klass;
109317                 return classes;
109318               });
109319               var actionableItems = itemsEnter.filter(function (d) {
109320                 return d !== 'spacer';
109321               });
109322               actionableItems.append('div').attr('class', 'item-content').each(function (d) {
109323                 select(this).call(d.render, bar);
109324               });
109325               actionableItems.append('div').attr('class', 'item-label').html(function (d) {
109326                 return d.label;
109327               });
109328             }
109329           }
109330
109331           return topToolbar;
109332         }
109333
109334         function uiZoomToSelection(context) {
109335           function isDisabled() {
109336             var mode = context.mode();
109337             return !mode || !mode.zoomToSelected;
109338           }
109339
109340           var _lastPointerUpType;
109341
109342           function pointerup(d3_event) {
109343             _lastPointerUpType = d3_event.pointerType;
109344           }
109345
109346           function click(d3_event) {
109347             d3_event.preventDefault();
109348
109349             if (isDisabled()) {
109350               if (_lastPointerUpType === 'touch' || _lastPointerUpType === 'pen') {
109351                 context.ui().flash.duration(2000).iconName('#iD-icon-framed-dot').iconClass('disabled').label(_t.html('inspector.zoom_to.no_selection'))();
109352               }
109353             } else {
109354               var mode = context.mode();
109355
109356               if (mode && mode.zoomToSelected) {
109357                 mode.zoomToSelected();
109358               }
109359             }
109360
109361             _lastPointerUpType = null;
109362           }
109363
109364           return function (selection) {
109365             var tooltipBehavior = uiTooltip().placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left').title(function () {
109366               if (isDisabled()) {
109367                 return _t.html('inspector.zoom_to.no_selection');
109368               }
109369
109370               return _t.html('inspector.zoom_to.title');
109371             }).keys([_t('inspector.zoom_to.key')]);
109372             var button = selection.append('button').on('pointerup', pointerup).on('click', click).call(svgIcon('#iD-icon-framed-dot', 'light')).call(tooltipBehavior);
109373
109374             function setEnabledState() {
109375               button.classed('disabled', isDisabled());
109376
109377               if (!button.select('.tooltip.in').empty()) {
109378                 button.call(tooltipBehavior.updateContent);
109379               }
109380             }
109381
109382             context.on('enter.uiZoomToSelection', setEnabledState);
109383             setEnabledState();
109384           };
109385         }
109386
109387         function uiPane(id, context) {
109388           var _key;
109389
109390           var _label = '';
109391           var _description = '';
109392           var _iconName = '';
109393
109394           var _sections; // array of uiSection objects
109395
109396
109397           var _paneSelection = select(null);
109398
109399           var _paneTooltip;
109400
109401           var pane = {
109402             id: id
109403           };
109404
109405           pane.label = function (val) {
109406             if (!arguments.length) return _label;
109407             _label = val;
109408             return pane;
109409           };
109410
109411           pane.key = function (val) {
109412             if (!arguments.length) return _key;
109413             _key = val;
109414             return pane;
109415           };
109416
109417           pane.description = function (val) {
109418             if (!arguments.length) return _description;
109419             _description = val;
109420             return pane;
109421           };
109422
109423           pane.iconName = function (val) {
109424             if (!arguments.length) return _iconName;
109425             _iconName = val;
109426             return pane;
109427           };
109428
109429           pane.sections = function (val) {
109430             if (!arguments.length) return _sections;
109431             _sections = val;
109432             return pane;
109433           };
109434
109435           pane.selection = function () {
109436             return _paneSelection;
109437           };
109438
109439           function hidePane() {
109440             context.ui().togglePanes();
109441           }
109442
109443           pane.togglePane = function (d3_event) {
109444             if (d3_event) d3_event.preventDefault();
109445
109446             _paneTooltip.hide();
109447
109448             context.ui().togglePanes(!_paneSelection.classed('shown') ? _paneSelection : undefined);
109449           };
109450
109451           pane.renderToggleButton = function (selection) {
109452             if (!_paneTooltip) {
109453               _paneTooltip = uiTooltip().placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left').title(_description).keys([_key]);
109454             }
109455
109456             selection.append('button').on('click', pane.togglePane).call(svgIcon('#' + _iconName, 'light')).call(_paneTooltip);
109457           };
109458
109459           pane.renderContent = function (selection) {
109460             // override to fully customize content
109461             if (_sections) {
109462               _sections.forEach(function (section) {
109463                 selection.call(section.render);
109464               });
109465             }
109466           };
109467
109468           pane.renderPane = function (selection) {
109469             _paneSelection = selection.append('div').attr('class', 'fillL map-pane hide ' + id + '-pane').attr('pane', id);
109470
109471             var heading = _paneSelection.append('div').attr('class', 'pane-heading');
109472
109473             heading.append('h2').html(_label);
109474             heading.append('button').attr('title', _t('icons.close')).on('click', hidePane).call(svgIcon('#iD-icon-close'));
109475
109476             _paneSelection.append('div').attr('class', 'pane-content').call(pane.renderContent);
109477
109478             if (_key) {
109479               context.keybinding().on(_key, pane.togglePane);
109480             }
109481           };
109482
109483           return pane;
109484         }
109485
109486         function uiSectionBackgroundDisplayOptions(context) {
109487           var section = uiSection('background-display-options', context).label(_t.html('background.display_options')).disclosureContent(renderDisclosureContent);
109488
109489           var _detected = utilDetect();
109490
109491           var _storedOpacity = corePreferences('background-opacity');
109492
109493           var _minVal = 0;
109494
109495           var _maxVal = _detected.cssfilters ? 3 : 1;
109496
109497           var _sliders = _detected.cssfilters ? ['brightness', 'contrast', 'saturation', 'sharpness'] : ['brightness'];
109498
109499           var _options = {
109500             brightness: _storedOpacity !== null ? +_storedOpacity : 1,
109501             contrast: 1,
109502             saturation: 1,
109503             sharpness: 1
109504           };
109505
109506           function clamp(x, min, max) {
109507             return Math.max(min, Math.min(x, max));
109508           }
109509
109510           function updateValue(d, val) {
109511             val = clamp(val, _minVal, _maxVal);
109512             _options[d] = val;
109513             context.background()[d](val);
109514
109515             if (d === 'brightness') {
109516               corePreferences('background-opacity', val);
109517             }
109518
109519             section.reRender();
109520           }
109521
109522           function renderDisclosureContent(selection) {
109523             var container = selection.selectAll('.display-options-container').data([0]);
109524             var containerEnter = container.enter().append('div').attr('class', 'display-options-container controls-list'); // add slider controls
109525
109526             var slidersEnter = containerEnter.selectAll('.display-control').data(_sliders).enter().append('label').attr('class', function (d) {
109527               return 'display-control display-control-' + d;
109528             });
109529             slidersEnter.html(function (d) {
109530               return _t.html('background.' + d);
109531             }).append('span').attr('class', function (d) {
109532               return 'display-option-value display-option-value-' + d;
109533             });
109534             var sildersControlEnter = slidersEnter.append('div').attr('class', 'control-wrap');
109535             sildersControlEnter.append('input').attr('class', function (d) {
109536               return 'display-option-input display-option-input-' + d;
109537             }).attr('type', 'range').attr('min', _minVal).attr('max', _maxVal).attr('step', '0.05').on('input', function (d3_event, d) {
109538               var val = select(this).property('value');
109539
109540               if (!val && d3_event && d3_event.target) {
109541                 val = d3_event.target.value;
109542               }
109543
109544               updateValue(d, val);
109545             });
109546             sildersControlEnter.append('button').attr('title', function (d) {
109547               return "".concat(_t('background.reset'), " ").concat(_t('background.' + d));
109548             }).attr('class', function (d) {
109549               return 'display-option-reset display-option-reset-' + d;
109550             }).on('click', function (d3_event, d) {
109551               if (d3_event.button !== 0) return;
109552               updateValue(d, 1);
109553             }).call(svgIcon('#iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'redo' : 'undo'))); // reset all button
109554
109555             containerEnter.append('a').attr('class', 'display-option-resetlink').attr('role', 'button').attr('href', '#').call(_t.append('background.reset_all')).on('click', function (d3_event) {
109556               d3_event.preventDefault();
109557
109558               for (var i = 0; i < _sliders.length; i++) {
109559                 updateValue(_sliders[i], 1);
109560               }
109561             }); // update
109562
109563             container = containerEnter.merge(container);
109564             container.selectAll('.display-option-input').property('value', function (d) {
109565               return _options[d];
109566             });
109567             container.selectAll('.display-option-value').text(function (d) {
109568               return Math.floor(_options[d] * 100) + '%';
109569             });
109570             container.selectAll('.display-option-reset').classed('disabled', function (d) {
109571               return _options[d] === 1;
109572             }); // first time only, set brightness if needed
109573
109574             if (containerEnter.size() && _options.brightness !== 1) {
109575               context.background().brightness(_options.brightness);
109576             }
109577           }
109578
109579           return section;
109580         }
109581
109582         function uiSettingsCustomBackground() {
109583           var dispatch = dispatch$8('change');
109584
109585           function render(selection) {
109586             // keep separate copies of original and current settings
109587             var _origSettings = {
109588               template: corePreferences('background-custom-template')
109589             };
109590             var _currSettings = {
109591               template: corePreferences('background-custom-template')
109592             };
109593             var example = 'https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png';
109594             var modal = uiConfirm(selection).okButton();
109595             modal.classed('settings-modal settings-custom-background', true);
109596             modal.select('.modal-section.header').append('h3').call(_t.append('settings.custom_background.header'));
109597             var textSection = modal.select('.modal-section.message-text');
109598             var instructions = "".concat(_t.html('settings.custom_background.instructions.info'), "\n") + '\n' + "#### ".concat(_t.html('settings.custom_background.instructions.wms.tokens_label'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.wms.tokens.proj'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.wms.tokens.wkid'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.wms.tokens.dimensions'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.wms.tokens.bbox'), "\n") + '\n' + "#### ".concat(_t.html('settings.custom_background.instructions.tms.tokens_label'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.tms.tokens.xyz'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.tms.tokens.flipped_y'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.tms.tokens.switch'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.tms.tokens.quadtile'), "\n") + "* ".concat(_t.html('settings.custom_background.instructions.tms.tokens.scale_factor'), "\n") + '\n' + "#### ".concat(_t.html('settings.custom_background.instructions.example'), "\n") + "`".concat(example, "`");
109599             textSection.append('div').attr('class', 'instructions-template').html(marked_1(instructions));
109600             textSection.append('textarea').attr('class', 'field-template').attr('placeholder', _t('settings.custom_background.template.placeholder')).call(utilNoAuto).property('value', _currSettings.template); // insert a cancel button
109601
109602             var buttonSection = modal.select('.modal-section.buttons');
109603             buttonSection.insert('button', '.ok-button').attr('class', 'button cancel-button secondary-action').call(_t.append('confirm.cancel'));
109604             buttonSection.select('.cancel-button').on('click.cancel', clickCancel);
109605             buttonSection.select('.ok-button').attr('disabled', isSaveDisabled).on('click.save', clickSave);
109606
109607             function isSaveDisabled() {
109608               return null;
109609             } // restore the original template
109610
109611
109612             function clickCancel() {
109613               textSection.select('.field-template').property('value', _origSettings.template);
109614               corePreferences('background-custom-template', _origSettings.template);
109615               this.blur();
109616               modal.close();
109617             } // accept the current template
109618
109619
109620             function clickSave() {
109621               _currSettings.template = textSection.select('.field-template').property('value');
109622               corePreferences('background-custom-template', _currSettings.template);
109623               this.blur();
109624               modal.close();
109625               dispatch.call('change', this, _currSettings);
109626             }
109627           }
109628
109629           return utilRebind(render, dispatch, 'on');
109630         }
109631
109632         function uiSectionBackgroundList(context) {
109633           var _backgroundList = select(null);
109634
109635           var _customSource = context.background().findSource('custom');
109636
109637           var _settingsCustomBackground = uiSettingsCustomBackground().on('change', customChanged);
109638
109639           var section = uiSection('background-list', context).label(_t.html('background.backgrounds')).disclosureContent(renderDisclosureContent);
109640
109641           function previousBackgroundID() {
109642             return corePreferences('background-last-used-toggle');
109643           }
109644
109645           function renderDisclosureContent(selection) {
109646             // the background list
109647             var container = selection.selectAll('.layer-background-list').data([0]);
109648             _backgroundList = container.enter().append('ul').attr('class', 'layer-list layer-background-list').attr('dir', 'auto').merge(container); // add minimap toggle below list
109649
109650             var bgExtrasListEnter = selection.selectAll('.bg-extras-list').data([0]).enter().append('ul').attr('class', 'layer-list bg-extras-list');
109651             var minimapLabelEnter = bgExtrasListEnter.append('li').attr('class', 'minimap-toggle-item').append('label').call(uiTooltip().title(_t.html('background.minimap.tooltip')).keys([_t('background.minimap.key')]).placement('top'));
109652             minimapLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
109653               d3_event.preventDefault();
109654               uiMapInMap.toggle();
109655             });
109656             minimapLabelEnter.append('span').call(_t.append('background.minimap.description'));
109657             var panelLabelEnter = bgExtrasListEnter.append('li').attr('class', 'background-panel-toggle-item').append('label').call(uiTooltip().title(_t.html('background.panel.tooltip')).keys([uiCmd('⌘⇧' + _t('info_panels.background.key'))]).placement('top'));
109658             panelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
109659               d3_event.preventDefault();
109660               context.ui().info.toggle('background');
109661             });
109662             panelLabelEnter.append('span').call(_t.append('background.panel.description'));
109663             var locPanelLabelEnter = bgExtrasListEnter.append('li').attr('class', 'location-panel-toggle-item').append('label').call(uiTooltip().title(_t.html('background.location_panel.tooltip')).keys([uiCmd('⌘⇧' + _t('info_panels.location.key'))]).placement('top'));
109664             locPanelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
109665               d3_event.preventDefault();
109666               context.ui().info.toggle('location');
109667             });
109668             locPanelLabelEnter.append('span').call(_t.append('background.location_panel.description')); // "Info / Report a Problem" link
109669
109670             selection.selectAll('.imagery-faq').data([0]).enter().append('div').attr('class', 'imagery-faq').append('a').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).attr('href', 'https://github.com/openstreetmap/iD/blob/develop/FAQ.md#how-can-i-report-an-issue-with-background-imagery').append('span').call(_t.append('background.imagery_problem_faq'));
109671
109672             _backgroundList.call(drawListItems, 'radio', function (d3_event, d) {
109673               chooseBackground(d);
109674             }, function (d) {
109675               return !d.isHidden() && !d.overlay;
109676             });
109677           }
109678
109679           function setTooltips(selection) {
109680             selection.each(function (d, i, nodes) {
109681               var item = select(this).select('label');
109682               var span = item.select('span');
109683               var placement = i < nodes.length / 2 ? 'bottom' : 'top';
109684               var description = d.description();
109685               var isOverflowing = span.property('clientWidth') !== span.property('scrollWidth');
109686               item.call(uiTooltip().destroyAny);
109687
109688               if (d.id === previousBackgroundID()) {
109689                 item.call(uiTooltip().placement(placement).title('<div>' + _t.html('background.switch') + '</div>').keys([uiCmd('⌘' + _t('background.key'))]));
109690               } else if (description || isOverflowing) {
109691                 item.call(uiTooltip().placement(placement).title(description || d.label()));
109692               }
109693             });
109694           }
109695
109696           function drawListItems(layerList, type, change, filter) {
109697             var sources = context.background().sources(context.map().extent(), context.map().zoom(), true).filter(filter).sort(function (a, b) {
109698               return a.best() && !b.best() ? -1 : b.best() && !a.best() ? 1 : d3_descending(a.area(), b.area()) || d3_ascending(a.name(), b.name()) || 0;
109699             });
109700             var layerLinks = layerList.selectAll('li') // We have to be a bit inefficient about reordering the list since
109701             // arrow key navigation of radio values likes to work in the order
109702             // they were added, not the display document order.
109703             .data(sources, function (d, i) {
109704               return d.id + '---' + i;
109705             });
109706             layerLinks.exit().remove();
109707             var enter = layerLinks.enter().append('li').classed('layer-custom', function (d) {
109708               return d.id === 'custom';
109709             }).classed('best', function (d) {
109710               return d.best();
109711             });
109712             var label = enter.append('label');
109713             label.append('input').attr('type', type).attr('name', 'background-layer').attr('value', function (d) {
109714               return d.id;
109715             }).on('change', change);
109716             label.append('span').html(function (d) {
109717               return d.label();
109718             });
109719             enter.filter(function (d) {
109720               return d.id === 'custom';
109721             }).append('button').attr('class', 'layer-browse').call(uiTooltip().title(_t.html('settings.custom_background.tooltip')).placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left')).on('click', function (d3_event) {
109722               d3_event.preventDefault();
109723               editCustom();
109724             }).call(svgIcon('#iD-icon-more'));
109725             enter.filter(function (d) {
109726               return d.best();
109727             }).append('div').attr('class', 'best').call(uiTooltip().title(_t.html('background.best_imagery')).placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left')).append('span').html('&#9733;');
109728             layerList.call(updateLayerSelections);
109729           }
109730
109731           function updateLayerSelections(selection) {
109732             function active(d) {
109733               return context.background().showsLayer(d);
109734             }
109735
109736             selection.selectAll('li').classed('active', active).classed('switch', function (d) {
109737               return d.id === previousBackgroundID();
109738             }).call(setTooltips).selectAll('input').property('checked', active);
109739           }
109740
109741           function chooseBackground(d) {
109742             if (d.id === 'custom' && !d.template()) {
109743               return editCustom();
109744             }
109745
109746             var previousBackground = context.background().baseLayerSource();
109747             corePreferences('background-last-used-toggle', previousBackground.id);
109748             corePreferences('background-last-used', d.id);
109749             context.background().baseLayerSource(d);
109750           }
109751
109752           function customChanged(d) {
109753             if (d && d.template) {
109754               _customSource.template(d.template);
109755
109756               chooseBackground(_customSource);
109757             } else {
109758               _customSource.template('');
109759
109760               chooseBackground(context.background().findSource('none'));
109761             }
109762           }
109763
109764           function editCustom() {
109765             context.container().call(_settingsCustomBackground);
109766           }
109767
109768           context.background().on('change.background_list', function () {
109769             _backgroundList.call(updateLayerSelections);
109770           });
109771           context.map().on('move.background_list', debounce(function () {
109772             // layers in-view may have changed due to map move
109773             window.requestIdleCallback(section.reRender);
109774           }, 1000));
109775           return section;
109776         }
109777
109778         function uiSectionBackgroundOffset(context) {
109779           var section = uiSection('background-offset', context).label(_t.html('background.fix_misalignment')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
109780
109781           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
109782
109783           var _directions = [['top', [0, -0.5]], ['left', [-0.5, 0]], ['right', [0.5, 0]], ['bottom', [0, 0.5]]];
109784
109785           function updateValue() {
109786             var meters = geoOffsetToMeters(context.background().offset());
109787             var x = +meters[0].toFixed(2);
109788             var y = +meters[1].toFixed(2);
109789             context.container().selectAll('.nudge-inner-rect').select('input').classed('error', false).property('value', x + ', ' + y);
109790             context.container().selectAll('.nudge-reset').classed('disabled', function () {
109791               return x === 0 && y === 0;
109792             });
109793           }
109794
109795           function resetOffset() {
109796             context.background().offset([0, 0]);
109797             updateValue();
109798           }
109799
109800           function nudge(d) {
109801             context.background().nudge(d, context.map().zoom());
109802             updateValue();
109803           }
109804
109805           function inputOffset() {
109806             var input = select(this);
109807             var d = input.node().value;
109808             if (d === '') return resetOffset();
109809             d = d.replace(/;/g, ',').split(',').map(function (n) {
109810               // if n is NaN, it will always get mapped to false.
109811               return !isNaN(n) && n;
109812             });
109813
109814             if (d.length !== 2 || !d[0] || !d[1]) {
109815               input.classed('error', true);
109816               return;
109817             }
109818
109819             context.background().offset(geoMetersToOffset(d));
109820             updateValue();
109821           }
109822
109823           function dragOffset(d3_event) {
109824             if (d3_event.button !== 0) return;
109825             var origin = [d3_event.clientX, d3_event.clientY];
109826             var pointerId = d3_event.pointerId || 'mouse';
109827             context.container().append('div').attr('class', 'nudge-surface');
109828             select(window).on(_pointerPrefix + 'move.drag-bg-offset', pointermove).on(_pointerPrefix + 'up.drag-bg-offset', pointerup);
109829
109830             if (_pointerPrefix === 'pointer') {
109831               select(window).on('pointercancel.drag-bg-offset', pointerup);
109832             }
109833
109834             function pointermove(d3_event) {
109835               if (pointerId !== (d3_event.pointerId || 'mouse')) return;
109836               var latest = [d3_event.clientX, d3_event.clientY];
109837               var d = [-(origin[0] - latest[0]) / 4, -(origin[1] - latest[1]) / 4];
109838               origin = latest;
109839               nudge(d);
109840             }
109841
109842             function pointerup(d3_event) {
109843               if (pointerId !== (d3_event.pointerId || 'mouse')) return;
109844               if (d3_event.button !== 0) return;
109845               context.container().selectAll('.nudge-surface').remove();
109846               select(window).on('.drag-bg-offset', null);
109847             }
109848           }
109849
109850           function renderDisclosureContent(selection) {
109851             var container = selection.selectAll('.nudge-container').data([0]);
109852             var containerEnter = container.enter().append('div').attr('class', 'nudge-container');
109853             containerEnter.append('div').attr('class', 'nudge-instructions').call(_t.append('background.offset'));
109854             var nudgeWrapEnter = containerEnter.append('div').attr('class', 'nudge-controls-wrap');
109855             var nudgeEnter = nudgeWrapEnter.append('div').attr('class', 'nudge-outer-rect').on(_pointerPrefix + 'down', dragOffset);
109856             nudgeEnter.append('div').attr('class', 'nudge-inner-rect').append('input').attr('type', 'text').attr('aria-label', _t('background.offset_label')).on('change', inputOffset);
109857             nudgeWrapEnter.append('div').selectAll('button').data(_directions).enter().append('button').attr('title', function (d) {
109858               return _t("background.nudge.".concat(d[0]));
109859             }).attr('class', function (d) {
109860               return d[0] + ' nudge';
109861             }).on('click', function (d3_event, d) {
109862               nudge(d[1]);
109863             });
109864             nudgeWrapEnter.append('button').attr('title', _t('background.reset')).attr('class', 'nudge-reset disabled').on('click', function (d3_event) {
109865               d3_event.preventDefault();
109866               resetOffset();
109867             }).call(svgIcon('#iD-icon-' + (_mainLocalizer.textDirection() === 'rtl' ? 'redo' : 'undo')));
109868             updateValue();
109869           }
109870
109871           context.background().on('change.backgroundOffset-update', updateValue);
109872           return section;
109873         }
109874
109875         function uiSectionOverlayList(context) {
109876           var section = uiSection('overlay-list', context).label(_t.html('background.overlays')).disclosureContent(renderDisclosureContent);
109877
109878           var _overlayList = select(null);
109879
109880           function setTooltips(selection) {
109881             selection.each(function (d, i, nodes) {
109882               var item = select(this).select('label');
109883               var span = item.select('span');
109884               var placement = i < nodes.length / 2 ? 'bottom' : 'top';
109885               var description = d.description();
109886               var isOverflowing = span.property('clientWidth') !== span.property('scrollWidth');
109887               item.call(uiTooltip().destroyAny);
109888
109889               if (description || isOverflowing) {
109890                 item.call(uiTooltip().placement(placement).title(description || d.name()));
109891               }
109892             });
109893           }
109894
109895           function updateLayerSelections(selection) {
109896             function active(d) {
109897               return context.background().showsLayer(d);
109898             }
109899
109900             selection.selectAll('li').classed('active', active).call(setTooltips).selectAll('input').property('checked', active);
109901           }
109902
109903           function chooseOverlay(d3_event, d) {
109904             d3_event.preventDefault();
109905             context.background().toggleOverlayLayer(d);
109906
109907             _overlayList.call(updateLayerSelections);
109908
109909             document.activeElement.blur();
109910           }
109911
109912           function drawListItems(layerList, type, change, filter) {
109913             var sources = context.background().sources(context.map().extent(), context.map().zoom(), true).filter(filter);
109914             var layerLinks = layerList.selectAll('li').data(sources, function (d) {
109915               return d.name();
109916             });
109917             layerLinks.exit().remove();
109918             var enter = layerLinks.enter().append('li');
109919             var label = enter.append('label');
109920             label.append('input').attr('type', type).attr('name', 'layers').on('change', change);
109921             label.append('span').html(function (d) {
109922               return d.label();
109923             });
109924             layerList.selectAll('li').sort(sortSources);
109925             layerList.call(updateLayerSelections);
109926
109927             function sortSources(a, b) {
109928               return a.best() && !b.best() ? -1 : b.best() && !a.best() ? 1 : d3_descending(a.area(), b.area()) || d3_ascending(a.name(), b.name()) || 0;
109929             }
109930           }
109931
109932           function renderDisclosureContent(selection) {
109933             var container = selection.selectAll('.layer-overlay-list').data([0]);
109934             _overlayList = container.enter().append('ul').attr('class', 'layer-list layer-overlay-list').attr('dir', 'auto').merge(container);
109935
109936             _overlayList.call(drawListItems, 'checkbox', chooseOverlay, function (d) {
109937               return !d.isHidden() && d.overlay;
109938             });
109939           }
109940
109941           context.map().on('move.overlay_list', debounce(function () {
109942             // layers in-view may have changed due to map move
109943             window.requestIdleCallback(section.reRender);
109944           }, 1000));
109945           return section;
109946         }
109947
109948         function uiPaneBackground(context) {
109949           var backgroundPane = uiPane('background', context).key(_t('background.key')).label(_t.html('background.title')).description(_t.html('background.description')).iconName('iD-icon-layers').sections([uiSectionBackgroundList(context), uiSectionOverlayList(context), uiSectionBackgroundDisplayOptions(context), uiSectionBackgroundOffset(context)]);
109950           return backgroundPane;
109951         }
109952
109953         function uiPaneHelp(context) {
109954           var docKeys = [['help', ['welcome', 'open_data_h', 'open_data', 'before_start_h', 'before_start', 'open_source_h', 'open_source', 'open_source_help']], ['overview', ['navigation_h', 'navigation_drag', 'navigation_zoom', 'features_h', 'features', 'nodes_ways']], ['editing', ['select_h', 'select_left_click', 'select_right_click', 'select_space', 'multiselect_h', 'multiselect', 'multiselect_shift_click', 'multiselect_lasso', 'undo_redo_h', 'undo_redo', 'save_h', 'save', 'save_validation', 'upload_h', 'upload', 'backups_h', 'backups', 'keyboard_h', 'keyboard']], ['feature_editor', ['intro', 'definitions', 'type_h', 'type', 'type_picker', 'fields_h', 'fields_all_fields', 'fields_example', 'fields_add_field', 'tags_h', 'tags_all_tags', 'tags_resources']], ['points', ['intro', 'add_point_h', 'add_point', 'add_point_finish', 'move_point_h', 'move_point', 'delete_point_h', 'delete_point', 'delete_point_command']], ['lines', ['intro', 'add_line_h', 'add_line', 'add_line_draw', 'add_line_continue', 'add_line_finish', 'modify_line_h', 'modify_line_dragnode', 'modify_line_addnode', 'connect_line_h', 'connect_line', 'connect_line_display', 'connect_line_drag', 'connect_line_tag', 'disconnect_line_h', 'disconnect_line_command', 'move_line_h', 'move_line_command', 'move_line_connected', 'delete_line_h', 'delete_line', 'delete_line_command']], ['areas', ['intro', 'point_or_area_h', 'point_or_area', 'add_area_h', 'add_area_command', 'add_area_draw', 'add_area_continue', 'add_area_finish', 'square_area_h', 'square_area_command', 'modify_area_h', 'modify_area_dragnode', 'modify_area_addnode', 'delete_area_h', 'delete_area', 'delete_area_command']], ['relations', ['intro', 'edit_relation_h', 'edit_relation', 'edit_relation_add', 'edit_relation_delete', 'maintain_relation_h', 'maintain_relation', 'relation_types_h', 'multipolygon_h', 'multipolygon', 'multipolygon_create', 'multipolygon_merge', 'turn_restriction_h', 'turn_restriction', 'turn_restriction_field', 'turn_restriction_editing', 'route_h', 'route', 'route_add', 'boundary_h', 'boundary', 'boundary_add']], ['operations', ['intro', 'intro_2', 'straighten', 'orthogonalize', 'circularize', 'move', 'rotate', 'reflect', 'continue', 'reverse', 'disconnect', 'split', 'extract', 'merge', 'delete', 'downgrade', 'copy_paste']], ['notes', ['intro', 'add_note_h', 'add_note', 'place_note', 'move_note', 'update_note_h', 'update_note', 'save_note_h', 'save_note']], ['imagery', ['intro', 'sources_h', 'choosing', 'sources', 'offsets_h', 'offset', 'offset_change']], ['streetlevel', ['intro', 'using_h', 'using', 'photos', 'viewer']], ['gps', ['intro', 'survey', 'using_h', 'using', 'tracing', 'upload']], ['qa', ['intro', 'tools_h', 'tools', 'issues_h', 'issues']]];
109955           var headings = {
109956             'help.help.open_data_h': 3,
109957             'help.help.before_start_h': 3,
109958             'help.help.open_source_h': 3,
109959             'help.overview.navigation_h': 3,
109960             'help.overview.features_h': 3,
109961             'help.editing.select_h': 3,
109962             'help.editing.multiselect_h': 3,
109963             'help.editing.undo_redo_h': 3,
109964             'help.editing.save_h': 3,
109965             'help.editing.upload_h': 3,
109966             'help.editing.backups_h': 3,
109967             'help.editing.keyboard_h': 3,
109968             'help.feature_editor.type_h': 3,
109969             'help.feature_editor.fields_h': 3,
109970             'help.feature_editor.tags_h': 3,
109971             'help.points.add_point_h': 3,
109972             'help.points.move_point_h': 3,
109973             'help.points.delete_point_h': 3,
109974             'help.lines.add_line_h': 3,
109975             'help.lines.modify_line_h': 3,
109976             'help.lines.connect_line_h': 3,
109977             'help.lines.disconnect_line_h': 3,
109978             'help.lines.move_line_h': 3,
109979             'help.lines.delete_line_h': 3,
109980             'help.areas.point_or_area_h': 3,
109981             'help.areas.add_area_h': 3,
109982             'help.areas.square_area_h': 3,
109983             'help.areas.modify_area_h': 3,
109984             'help.areas.delete_area_h': 3,
109985             'help.relations.edit_relation_h': 3,
109986             'help.relations.maintain_relation_h': 3,
109987             'help.relations.relation_types_h': 2,
109988             'help.relations.multipolygon_h': 3,
109989             'help.relations.turn_restriction_h': 3,
109990             'help.relations.route_h': 3,
109991             'help.relations.boundary_h': 3,
109992             'help.notes.add_note_h': 3,
109993             'help.notes.update_note_h': 3,
109994             'help.notes.save_note_h': 3,
109995             'help.imagery.sources_h': 3,
109996             'help.imagery.offsets_h': 3,
109997             'help.streetlevel.using_h': 3,
109998             'help.gps.using_h': 3,
109999             'help.qa.tools_h': 3,
110000             'help.qa.issues_h': 3
110001           }; // For each section, squash all the texts into a single markdown document
110002
110003           var docs = docKeys.map(function (key) {
110004             var helpkey = 'help.' + key[0];
110005             var helpPaneReplacements = {
110006               version: context.version
110007             };
110008             var text = key[1].reduce(function (all, part) {
110009               var subkey = helpkey + '.' + part;
110010               var depth = headings[subkey]; // is this subkey a heading?
110011
110012               var hhh = depth ? Array(depth + 1).join('#') + ' ' : ''; // if so, prepend with some ##'s
110013
110014               return all + hhh + helpHtml(subkey, helpPaneReplacements) + '\n\n';
110015             }, '');
110016             return {
110017               title: _t.html(helpkey + '.title'),
110018               content: marked_1(text.trim()) // use keyboard key styling for shortcuts
110019               .replace(/<code>/g, '<kbd>').replace(/<\/code>/g, '<\/kbd>')
110020             };
110021           });
110022           var helpPane = uiPane('help', context).key(_t('help.key')).label(_t.html('help.title')).description(_t.html('help.title')).iconName('iD-icon-help');
110023
110024           helpPane.renderContent = function (content) {
110025             function clickHelp(d, i) {
110026               var rtl = _mainLocalizer.textDirection() === 'rtl';
110027               content.property('scrollTop', 0);
110028               helpPane.selection().select('.pane-heading h2').html(d.title);
110029               body.html(d.content);
110030               body.selectAll('a').attr('target', '_blank');
110031               menuItems.classed('selected', function (m) {
110032                 return m.title === d.title;
110033               });
110034               nav.html('');
110035
110036               if (rtl) {
110037                 nav.call(drawNext).call(drawPrevious);
110038               } else {
110039                 nav.call(drawPrevious).call(drawNext);
110040               }
110041
110042               function drawNext(selection) {
110043                 if (i < docs.length - 1) {
110044                   var nextLink = selection.append('a').attr('href', '#').attr('class', 'next').on('click', function (d3_event) {
110045                     d3_event.preventDefault();
110046                     clickHelp(docs[i + 1], i + 1);
110047                   });
110048                   nextLink.append('span').html(docs[i + 1].title).call(svgIcon(rtl ? '#iD-icon-backward' : '#iD-icon-forward', 'inline'));
110049                 }
110050               }
110051
110052               function drawPrevious(selection) {
110053                 if (i > 0) {
110054                   var prevLink = selection.append('a').attr('href', '#').attr('class', 'previous').on('click', function (d3_event) {
110055                     d3_event.preventDefault();
110056                     clickHelp(docs[i - 1], i - 1);
110057                   });
110058                   prevLink.call(svgIcon(rtl ? '#iD-icon-forward' : '#iD-icon-backward', 'inline')).append('span').html(docs[i - 1].title);
110059                 }
110060               }
110061             }
110062
110063             function clickWalkthrough(d3_event) {
110064               d3_event.preventDefault();
110065               if (context.inIntro()) return;
110066               context.container().call(uiIntro(context));
110067               context.ui().togglePanes();
110068             }
110069
110070             function clickShortcuts(d3_event) {
110071               d3_event.preventDefault();
110072               context.container().call(context.ui().shortcuts, true);
110073             }
110074
110075             var toc = content.append('ul').attr('class', 'toc');
110076             var menuItems = toc.selectAll('li').data(docs).enter().append('li').append('a').attr('role', 'button').attr('href', '#').html(function (d) {
110077               return d.title;
110078             }).on('click', function (d3_event, d) {
110079               d3_event.preventDefault();
110080               clickHelp(d, docs.indexOf(d));
110081             });
110082             var shortcuts = toc.append('li').attr('class', 'shortcuts').call(uiTooltip().title(_t.html('shortcuts.tooltip')).keys(['?']).placement('top')).append('a').attr('href', '#').on('click', clickShortcuts);
110083             shortcuts.append('div').call(_t.append('shortcuts.title'));
110084             var walkthrough = toc.append('li').attr('class', 'walkthrough').append('a').attr('href', '#').on('click', clickWalkthrough);
110085             walkthrough.append('svg').attr('class', 'logo logo-walkthrough').append('use').attr('xlink:href', '#iD-logo-walkthrough');
110086             walkthrough.append('div').call(_t.append('splash.walkthrough'));
110087             var helpContent = content.append('div').attr('class', 'left-content');
110088             var body = helpContent.append('div').attr('class', 'body');
110089             var nav = helpContent.append('div').attr('class', 'nav');
110090             clickHelp(docs[0], 0);
110091           };
110092
110093           return helpPane;
110094         }
110095
110096         function uiSectionValidationIssues(id, severity, context) {
110097           var _issues = [];
110098           var section = uiSection(id, context).label(function () {
110099             if (!_issues) return '';
110100             var issueCountText = _issues.length > 1000 ? '1000+' : String(_issues.length);
110101             return _t.html('inspector.title_count', {
110102               title: {
110103                 html: _t.html('issues.' + severity + 's.list_title')
110104               },
110105               count: issueCountText
110106             });
110107           }).disclosureContent(renderDisclosureContent).shouldDisplay(function () {
110108             return _issues && _issues.length;
110109           });
110110
110111           function getOptions() {
110112             return {
110113               what: corePreferences('validate-what') || 'edited',
110114               where: corePreferences('validate-where') || 'all'
110115             };
110116           } // get and cache the issues to display, unordered
110117
110118
110119           function reloadIssues() {
110120             _issues = context.validator().getIssuesBySeverity(getOptions())[severity];
110121           }
110122
110123           function renderDisclosureContent(selection) {
110124             var center = context.map().center();
110125             var graph = context.graph(); // sort issues by distance away from the center of the map
110126
110127             var issues = _issues.map(function withDistance(issue) {
110128               var extent = issue.extent(graph);
110129               var dist = extent ? geoSphericalDistance(center, extent.center()) : 0;
110130               return Object.assign(issue, {
110131                 dist: dist
110132               });
110133             }).sort(function byDistance(a, b) {
110134               return a.dist - b.dist;
110135             }); // cut off at 1000
110136
110137
110138             issues = issues.slice(0, 1000); //renderIgnoredIssuesReset(_warningsSelection);
110139
110140             selection.call(drawIssuesList, issues);
110141           }
110142
110143           function drawIssuesList(selection, issues) {
110144             var list = selection.selectAll('.issues-list').data([0]);
110145             list = list.enter().append('ul').attr('class', 'layer-list issues-list ' + severity + 's-list').merge(list);
110146             var items = list.selectAll('li').data(issues, function (d) {
110147               return d.key;
110148             }); // Exit
110149
110150             items.exit().remove(); // Enter
110151
110152             var itemsEnter = items.enter().append('li').attr('class', function (d) {
110153               return 'issue severity-' + d.severity;
110154             });
110155             var labelsEnter = itemsEnter.append('button').attr('class', 'issue-label').on('click', function (d3_event, d) {
110156               context.validator().focusIssue(d);
110157             }).on('mouseover', function (d3_event, d) {
110158               utilHighlightEntities(d.entityIds, true, context);
110159             }).on('mouseout', function (d3_event, d) {
110160               utilHighlightEntities(d.entityIds, false, context);
110161             });
110162             var textEnter = labelsEnter.append('span').attr('class', 'issue-text');
110163             textEnter.append('span').attr('class', 'issue-icon').each(function (d) {
110164               var iconName = '#iD-icon-' + (d.severity === 'warning' ? 'alert' : 'error');
110165               select(this).call(svgIcon(iconName));
110166             });
110167             textEnter.append('span').attr('class', 'issue-message');
110168             /*
110169             labelsEnter
110170                 .append('span')
110171                 .attr('class', 'issue-autofix')
110172                 .each(function(d) {
110173                     if (!d.autoFix) return;
110174                      d3_select(this)
110175                         .append('button')
110176                         .attr('title', t('issues.fix_one.title'))
110177                         .datum(d.autoFix)  // set button datum to the autofix
110178                         .attr('class', 'autofix action')
110179                         .on('click', function(d3_event, d) {
110180                             d3_event.preventDefault();
110181                             d3_event.stopPropagation();
110182                              var issuesEntityIDs = d.issue.entityIds;
110183                             utilHighlightEntities(issuesEntityIDs.concat(d.entityIds), false, context);
110184                              context.perform.apply(context, d.autoArgs);
110185                             context.validator().validate();
110186                         })
110187                         .call(svgIcon('#iD-icon-wrench'));
110188                 });
110189             */
110190             // Update
110191
110192             items = items.merge(itemsEnter).order();
110193             items.selectAll('.issue-message').html(function (d) {
110194               return d.message(context);
110195             });
110196             /*
110197             // autofix
110198             var canAutoFix = issues.filter(function(issue) { return issue.autoFix; });
110199              var autoFixAll = selection.selectAll('.autofix-all')
110200                 .data(canAutoFix.length ? [0] : []);
110201              // exit
110202             autoFixAll.exit()
110203                 .remove();
110204              // enter
110205             var autoFixAllEnter = autoFixAll.enter()
110206                 .insert('div', '.issues-list')
110207                 .attr('class', 'autofix-all');
110208              var linkEnter = autoFixAllEnter
110209                 .append('a')
110210                 .attr('class', 'autofix-all-link')
110211                 .attr('href', '#');
110212              linkEnter
110213                 .append('span')
110214                 .attr('class', 'autofix-all-link-text')
110215                 .call(t.append('issues.fix_all.title'));
110216              linkEnter
110217                 .append('span')
110218                 .attr('class', 'autofix-all-link-icon')
110219                 .call(svgIcon('#iD-icon-wrench'));
110220              if (severity === 'warning') {
110221                 renderIgnoredIssuesReset(selection);
110222             }
110223              // update
110224             autoFixAll = autoFixAll
110225                 .merge(autoFixAllEnter);
110226              autoFixAll.selectAll('.autofix-all-link')
110227                 .on('click', function() {
110228                     context.pauseChangeDispatch();
110229                     context.perform(actionNoop());
110230                     canAutoFix.forEach(function(issue) {
110231                         var args = issue.autoFix.autoArgs.slice();  // copy
110232                         if (typeof args[args.length - 1] !== 'function') {
110233                             args.pop();
110234                         }
110235                         args.push(t('issues.fix_all.annotation'));
110236                         context.replace.apply(context, args);
110237                     });
110238                     context.resumeChangeDispatch();
110239                     context.validator().validate();
110240                 });
110241             */
110242           }
110243
110244           context.validator().on('validated.uiSectionValidationIssues' + id, function () {
110245             window.requestIdleCallback(function () {
110246               reloadIssues();
110247               section.reRender();
110248             });
110249           });
110250           context.map().on('move.uiSectionValidationIssues' + id, debounce(function () {
110251             window.requestIdleCallback(function () {
110252               if (getOptions().where === 'visible') {
110253                 // must refetch issues if they are viewport-dependent
110254                 reloadIssues();
110255               } // always reload list to re-sort-by-distance
110256
110257
110258               section.reRender();
110259             });
110260           }, 1000));
110261           return section;
110262         }
110263
110264         function uiSectionValidationOptions(context) {
110265           var section = uiSection('issues-options', context).content(renderContent);
110266
110267           function renderContent(selection) {
110268             var container = selection.selectAll('.issues-options-container').data([0]);
110269             container = container.enter().append('div').attr('class', 'issues-options-container').merge(container);
110270             var data = [{
110271               key: 'what',
110272               values: ['edited', 'all']
110273             }, {
110274               key: 'where',
110275               values: ['visible', 'all']
110276             }];
110277             var options = container.selectAll('.issues-option').data(data, function (d) {
110278               return d.key;
110279             });
110280             var optionsEnter = options.enter().append('div').attr('class', function (d) {
110281               return 'issues-option issues-option-' + d.key;
110282             });
110283             optionsEnter.append('div').attr('class', 'issues-option-title').html(function (d) {
110284               return _t.html('issues.options.' + d.key + '.title');
110285             });
110286             var valuesEnter = optionsEnter.selectAll('label').data(function (d) {
110287               return d.values.map(function (val) {
110288                 return {
110289                   value: val,
110290                   key: d.key
110291                 };
110292               });
110293             }).enter().append('label');
110294             valuesEnter.append('input').attr('type', 'radio').attr('name', function (d) {
110295               return 'issues-option-' + d.key;
110296             }).attr('value', function (d) {
110297               return d.value;
110298             }).property('checked', function (d) {
110299               return getOptions()[d.key] === d.value;
110300             }).on('change', function (d3_event, d) {
110301               updateOptionValue(d3_event, d.key, d.value);
110302             });
110303             valuesEnter.append('span').html(function (d) {
110304               return _t.html('issues.options.' + d.key + '.' + d.value);
110305             });
110306           }
110307
110308           function getOptions() {
110309             return {
110310               what: corePreferences('validate-what') || 'edited',
110311               // 'all', 'edited'
110312               where: corePreferences('validate-where') || 'all' // 'all', 'visible'
110313
110314             };
110315           }
110316
110317           function updateOptionValue(d3_event, d, val) {
110318             if (!val && d3_event && d3_event.target) {
110319               val = d3_event.target.value;
110320             }
110321
110322             corePreferences('validate-' + d, val);
110323             context.validator().validate();
110324           }
110325
110326           return section;
110327         }
110328
110329         function uiSectionValidationRules(context) {
110330           var MINSQUARE = 0;
110331           var MAXSQUARE = 20;
110332           var DEFAULTSQUARE = 5; // see also unsquare_way.js
110333
110334           var section = uiSection('issues-rules', context).disclosureContent(renderDisclosureContent).label(_t.html('issues.rules.title'));
110335
110336           var _ruleKeys = context.validator().getRuleKeys().filter(function (key) {
110337             return key !== 'maprules';
110338           }).sort(function (key1, key2) {
110339             // alphabetize by localized title
110340             return _t('issues.' + key1 + '.title') < _t('issues.' + key2 + '.title') ? -1 : 1;
110341           });
110342
110343           function renderDisclosureContent(selection) {
110344             var container = selection.selectAll('.issues-rulelist-container').data([0]);
110345             var containerEnter = container.enter().append('div').attr('class', 'issues-rulelist-container');
110346             containerEnter.append('ul').attr('class', 'layer-list issue-rules-list');
110347             var ruleLinks = containerEnter.append('div').attr('class', 'issue-rules-links section-footer');
110348             ruleLinks.append('a').attr('class', 'issue-rules-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.disable_all')).on('click', function (d3_event) {
110349               d3_event.preventDefault();
110350               context.validator().disableRules(_ruleKeys);
110351             });
110352             ruleLinks.append('a').attr('class', 'issue-rules-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.enable_all')).on('click', function (d3_event) {
110353               d3_event.preventDefault();
110354               context.validator().disableRules([]);
110355             }); // Update
110356
110357             container = container.merge(containerEnter);
110358             container.selectAll('.issue-rules-list').call(drawListItems, _ruleKeys, 'checkbox', 'rule', toggleRule, isRuleEnabled);
110359           }
110360
110361           function drawListItems(selection, data, type, name, change, active) {
110362             var items = selection.selectAll('li').data(data); // Exit
110363
110364             items.exit().remove(); // Enter
110365
110366             var enter = items.enter().append('li');
110367
110368             if (name === 'rule') {
110369               enter.call(uiTooltip().title(function (d) {
110370                 return _t.html('issues.' + d + '.tip');
110371               }).placement('top'));
110372             }
110373
110374             var label = enter.append('label');
110375             label.append('input').attr('type', type).attr('name', name).on('change', change);
110376             label.append('span').html(function (d) {
110377               var params = {};
110378
110379               if (d === 'unsquare_way') {
110380                 params.val = {
110381                   html: '<span class="square-degrees"></span>'
110382                 };
110383               }
110384
110385               return _t.html('issues.' + d + '.title', params);
110386             }); // Update
110387
110388             items = items.merge(enter);
110389             items.classed('active', active).selectAll('input').property('checked', active).property('indeterminate', false); // user-configurable square threshold
110390
110391             var degStr = corePreferences('validate-square-degrees');
110392
110393             if (degStr === null) {
110394               degStr = DEFAULTSQUARE.toString();
110395             }
110396
110397             var span = items.selectAll('.square-degrees');
110398             var input = span.selectAll('.square-degrees-input').data([0]); // enter / update
110399
110400             input.enter().append('input').attr('type', 'number').attr('min', MINSQUARE.toString()).attr('max', MAXSQUARE.toString()).attr('step', '0.5').attr('class', 'square-degrees-input').call(utilNoAuto).on('click', function (d3_event) {
110401               d3_event.preventDefault();
110402               d3_event.stopPropagation();
110403               this.select();
110404             }).on('keyup', function (d3_event) {
110405               if (d3_event.keyCode === 13) {
110406                 // ↩ Return
110407                 this.blur();
110408                 this.select();
110409               }
110410             }).on('blur', changeSquare).merge(input).property('value', degStr);
110411           }
110412
110413           function changeSquare() {
110414             var input = select(this);
110415             var degStr = utilGetSetValue(input).trim();
110416             var degNum = parseFloat(degStr, 10);
110417
110418             if (!isFinite(degNum)) {
110419               degNum = DEFAULTSQUARE;
110420             } else if (degNum > MAXSQUARE) {
110421               degNum = MAXSQUARE;
110422             } else if (degNum < MINSQUARE) {
110423               degNum = MINSQUARE;
110424             }
110425
110426             degNum = Math.round(degNum * 10) / 10; // round to 1 decimal
110427
110428             degStr = degNum.toString();
110429             input.property('value', degStr);
110430             corePreferences('validate-square-degrees', degStr);
110431             context.validator().revalidateUnsquare();
110432           }
110433
110434           function isRuleEnabled(d) {
110435             return context.validator().isRuleEnabled(d);
110436           }
110437
110438           function toggleRule(d3_event, d) {
110439             context.validator().toggleRule(d);
110440           }
110441
110442           context.validator().on('validated.uiSectionValidationRules', function () {
110443             window.requestIdleCallback(section.reRender);
110444           });
110445           return section;
110446         }
110447
110448         function uiSectionValidationStatus(context) {
110449           var section = uiSection('issues-status', context).content(renderContent).shouldDisplay(function () {
110450             var issues = context.validator().getIssues(getOptions());
110451             return issues.length === 0;
110452           });
110453
110454           function getOptions() {
110455             return {
110456               what: corePreferences('validate-what') || 'edited',
110457               where: corePreferences('validate-where') || 'all'
110458             };
110459           }
110460
110461           function renderContent(selection) {
110462             var box = selection.selectAll('.box').data([0]);
110463             var boxEnter = box.enter().append('div').attr('class', 'box');
110464             boxEnter.append('div').call(svgIcon('#iD-icon-apply', 'pre-text'));
110465             var noIssuesMessage = boxEnter.append('span');
110466             noIssuesMessage.append('strong').attr('class', 'message');
110467             noIssuesMessage.append('br');
110468             noIssuesMessage.append('span').attr('class', 'details');
110469             renderIgnoredIssuesReset(selection);
110470             setNoIssuesText(selection);
110471           }
110472
110473           function renderIgnoredIssuesReset(selection) {
110474             var ignoredIssues = context.validator().getIssues({
110475               what: 'all',
110476               where: 'all',
110477               includeDisabledRules: true,
110478               includeIgnored: 'only'
110479             });
110480             var resetIgnored = selection.selectAll('.reset-ignored').data(ignoredIssues.length ? [0] : []); // exit
110481
110482             resetIgnored.exit().remove(); // enter
110483
110484             var resetIgnoredEnter = resetIgnored.enter().append('div').attr('class', 'reset-ignored section-footer');
110485             resetIgnoredEnter.append('a').attr('href', '#'); // update
110486
110487             resetIgnored = resetIgnored.merge(resetIgnoredEnter);
110488             resetIgnored.select('a').html(_t.html('inspector.title_count', {
110489               title: {
110490                 html: _t.html('issues.reset_ignored')
110491               },
110492               count: ignoredIssues.length
110493             }));
110494             resetIgnored.on('click', function (d3_event) {
110495               d3_event.preventDefault();
110496               context.validator().resetIgnoredIssues();
110497             });
110498           }
110499
110500           function setNoIssuesText(selection) {
110501             var opts = getOptions();
110502
110503             function checkForHiddenIssues(cases) {
110504               for (var type in cases) {
110505                 var hiddenOpts = cases[type];
110506                 var hiddenIssues = context.validator().getIssues(hiddenOpts);
110507
110508                 if (hiddenIssues.length) {
110509                   selection.select('.box .details').html('').call(_t.append('issues.no_issues.hidden_issues.' + type, {
110510                     count: hiddenIssues.length.toString()
110511                   }));
110512                   return;
110513                 }
110514               }
110515
110516               selection.select('.box .details').html('').call(_t.append('issues.no_issues.hidden_issues.none'));
110517             }
110518
110519             var messageType;
110520
110521             if (opts.what === 'edited' && opts.where === 'visible') {
110522               messageType = 'edits_in_view';
110523               checkForHiddenIssues({
110524                 elsewhere: {
110525                   what: 'edited',
110526                   where: 'all'
110527                 },
110528                 everything_else: {
110529                   what: 'all',
110530                   where: 'visible'
110531                 },
110532                 disabled_rules: {
110533                   what: 'edited',
110534                   where: 'visible',
110535                   includeDisabledRules: 'only'
110536                 },
110537                 everything_else_elsewhere: {
110538                   what: 'all',
110539                   where: 'all'
110540                 },
110541                 disabled_rules_elsewhere: {
110542                   what: 'edited',
110543                   where: 'all',
110544                   includeDisabledRules: 'only'
110545                 },
110546                 ignored_issues: {
110547                   what: 'edited',
110548                   where: 'visible',
110549                   includeIgnored: 'only'
110550                 },
110551                 ignored_issues_elsewhere: {
110552                   what: 'edited',
110553                   where: 'all',
110554                   includeIgnored: 'only'
110555                 }
110556               });
110557             } else if (opts.what === 'edited' && opts.where === 'all') {
110558               messageType = 'edits';
110559               checkForHiddenIssues({
110560                 everything_else: {
110561                   what: 'all',
110562                   where: 'all'
110563                 },
110564                 disabled_rules: {
110565                   what: 'edited',
110566                   where: 'all',
110567                   includeDisabledRules: 'only'
110568                 },
110569                 ignored_issues: {
110570                   what: 'edited',
110571                   where: 'all',
110572                   includeIgnored: 'only'
110573                 }
110574               });
110575             } else if (opts.what === 'all' && opts.where === 'visible') {
110576               messageType = 'everything_in_view';
110577               checkForHiddenIssues({
110578                 elsewhere: {
110579                   what: 'all',
110580                   where: 'all'
110581                 },
110582                 disabled_rules: {
110583                   what: 'all',
110584                   where: 'visible',
110585                   includeDisabledRules: 'only'
110586                 },
110587                 disabled_rules_elsewhere: {
110588                   what: 'all',
110589                   where: 'all',
110590                   includeDisabledRules: 'only'
110591                 },
110592                 ignored_issues: {
110593                   what: 'all',
110594                   where: 'visible',
110595                   includeIgnored: 'only'
110596                 },
110597                 ignored_issues_elsewhere: {
110598                   what: 'all',
110599                   where: 'all',
110600                   includeIgnored: 'only'
110601                 }
110602               });
110603             } else if (opts.what === 'all' && opts.where === 'all') {
110604               messageType = 'everything';
110605               checkForHiddenIssues({
110606                 disabled_rules: {
110607                   what: 'all',
110608                   where: 'all',
110609                   includeDisabledRules: 'only'
110610                 },
110611                 ignored_issues: {
110612                   what: 'all',
110613                   where: 'all',
110614                   includeIgnored: 'only'
110615                 }
110616               });
110617             }
110618
110619             if (opts.what === 'edited' && context.history().difference().summary().length === 0) {
110620               messageType = 'no_edits';
110621             }
110622
110623             selection.select('.box .message').html('').call(_t.append('issues.no_issues.message.' + messageType));
110624           }
110625
110626           context.validator().on('validated.uiSectionValidationStatus', function () {
110627             window.requestIdleCallback(section.reRender);
110628           });
110629           context.map().on('move.uiSectionValidationStatus', debounce(function () {
110630             window.requestIdleCallback(section.reRender);
110631           }, 1000));
110632           return section;
110633         }
110634
110635         function uiPaneIssues(context) {
110636           var issuesPane = uiPane('issues', context).key(_t('issues.key')).label(_t.html('issues.title')).description(_t.html('issues.title')).iconName('iD-icon-alert').sections([uiSectionValidationOptions(context), uiSectionValidationStatus(context), uiSectionValidationIssues('issues-errors', 'error', context), uiSectionValidationIssues('issues-warnings', 'warning', context), uiSectionValidationRules(context)]);
110637           return issuesPane;
110638         }
110639
110640         function uiSettingsCustomData(context) {
110641           var dispatch = dispatch$8('change');
110642
110643           function render(selection) {
110644             var dataLayer = context.layers().layer('data'); // keep separate copies of original and current settings
110645
110646             var _origSettings = {
110647               fileList: dataLayer && dataLayer.fileList() || null,
110648               url: corePreferences('settings-custom-data-url')
110649             };
110650             var _currSettings = {
110651               fileList: dataLayer && dataLayer.fileList() || null,
110652               url: corePreferences('settings-custom-data-url')
110653             }; // var example = 'https://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png';
110654
110655             var modal = uiConfirm(selection).okButton();
110656             modal.classed('settings-modal settings-custom-data', true);
110657             modal.select('.modal-section.header').append('h3').call(_t.append('settings.custom_data.header'));
110658             var textSection = modal.select('.modal-section.message-text');
110659             textSection.append('pre').attr('class', 'instructions-file').call(_t.append('settings.custom_data.file.instructions'));
110660             textSection.append('input').attr('class', 'field-file').attr('type', 'file').attr('accept', '.gpx,.kml,.geojson,.json,application/gpx+xml,application/vnd.google-earth.kml+xml,application/geo+json,application/json').property('files', _currSettings.fileList) // works for all except IE11
110661             .on('change', function (d3_event) {
110662               var files = d3_event.target.files;
110663
110664               if (files && files.length) {
110665                 _currSettings.url = '';
110666                 textSection.select('.field-url').property('value', '');
110667                 _currSettings.fileList = files;
110668               } else {
110669                 _currSettings.fileList = null;
110670               }
110671             });
110672             textSection.append('h4').call(_t.append('settings.custom_data.or'));
110673             textSection.append('pre').attr('class', 'instructions-url').call(_t.append('settings.custom_data.url.instructions'));
110674             textSection.append('textarea').attr('class', 'field-url').attr('placeholder', _t('settings.custom_data.url.placeholder')).call(utilNoAuto).property('value', _currSettings.url); // insert a cancel button
110675
110676             var buttonSection = modal.select('.modal-section.buttons');
110677             buttonSection.insert('button', '.ok-button').attr('class', 'button cancel-button secondary-action').call(_t.append('confirm.cancel'));
110678             buttonSection.select('.cancel-button').on('click.cancel', clickCancel);
110679             buttonSection.select('.ok-button').attr('disabled', isSaveDisabled).on('click.save', clickSave);
110680
110681             function isSaveDisabled() {
110682               return null;
110683             } // restore the original url
110684
110685
110686             function clickCancel() {
110687               textSection.select('.field-url').property('value', _origSettings.url);
110688               corePreferences('settings-custom-data-url', _origSettings.url);
110689               this.blur();
110690               modal.close();
110691             } // accept the current url
110692
110693
110694             function clickSave() {
110695               _currSettings.url = textSection.select('.field-url').property('value').trim(); // one or the other but not both
110696
110697               if (_currSettings.url) {
110698                 _currSettings.fileList = null;
110699               }
110700
110701               if (_currSettings.fileList) {
110702                 _currSettings.url = '';
110703               }
110704
110705               corePreferences('settings-custom-data-url', _currSettings.url);
110706               this.blur();
110707               modal.close();
110708               dispatch.call('change', this, _currSettings);
110709             }
110710           }
110711
110712           return utilRebind(render, dispatch, 'on');
110713         }
110714
110715         function uiSectionDataLayers(context) {
110716           var settingsCustomData = uiSettingsCustomData(context).on('change', customChanged);
110717           var layers = context.layers();
110718           var section = uiSection('data-layers', context).label(_t.html('map_data.data_layers')).disclosureContent(renderDisclosureContent);
110719
110720           function renderDisclosureContent(selection) {
110721             var container = selection.selectAll('.data-layer-container').data([0]);
110722             container.enter().append('div').attr('class', 'data-layer-container').merge(container).call(drawOsmItems).call(drawQAItems).call(drawCustomDataItems).call(drawVectorItems) // Beta - Detroit mapping challenge
110723             .call(drawPanelItems);
110724           }
110725
110726           function showsLayer(which) {
110727             var layer = layers.layer(which);
110728
110729             if (layer) {
110730               return layer.enabled();
110731             }
110732
110733             return false;
110734           }
110735
110736           function setLayer(which, enabled) {
110737             // Don't allow layer changes while drawing - #6584
110738             var mode = context.mode();
110739             if (mode && /^draw/.test(mode.id)) return;
110740             var layer = layers.layer(which);
110741
110742             if (layer) {
110743               layer.enabled(enabled);
110744
110745               if (!enabled && (which === 'osm' || which === 'notes')) {
110746                 context.enter(modeBrowse(context));
110747               }
110748             }
110749           }
110750
110751           function toggleLayer(which) {
110752             setLayer(which, !showsLayer(which));
110753           }
110754
110755           function drawOsmItems(selection) {
110756             var osmKeys = ['osm', 'notes'];
110757             var osmLayers = layers.all().filter(function (obj) {
110758               return osmKeys.indexOf(obj.id) !== -1;
110759             });
110760             var ul = selection.selectAll('.layer-list-osm').data([0]);
110761             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-osm').merge(ul);
110762             var li = ul.selectAll('.list-item').data(osmLayers);
110763             li.exit().remove();
110764             var liEnter = li.enter().append('li').attr('class', function (d) {
110765               return 'list-item list-item-' + d.id;
110766             });
110767             var labelEnter = liEnter.append('label').each(function (d) {
110768               if (d.id === 'osm') {
110769                 select(this).call(uiTooltip().title(_t.html('map_data.layers.' + d.id + '.tooltip')).keys([uiCmd('⌥' + _t('area_fill.wireframe.key'))]).placement('bottom'));
110770               } else {
110771                 select(this).call(uiTooltip().title(_t.html('map_data.layers.' + d.id + '.tooltip')).placement('bottom'));
110772               }
110773             });
110774             labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
110775               toggleLayer(d.id);
110776             });
110777             labelEnter.append('span').html(function (d) {
110778               return _t.html('map_data.layers.' + d.id + '.title');
110779             }); // Update
110780
110781             li.merge(liEnter).classed('active', function (d) {
110782               return d.layer.enabled();
110783             }).selectAll('input').property('checked', function (d) {
110784               return d.layer.enabled();
110785             });
110786           }
110787
110788           function drawQAItems(selection) {
110789             var qaKeys = ['keepRight', 'improveOSM', 'osmose'];
110790             var qaLayers = layers.all().filter(function (obj) {
110791               return qaKeys.indexOf(obj.id) !== -1;
110792             });
110793             var ul = selection.selectAll('.layer-list-qa').data([0]);
110794             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-qa').merge(ul);
110795             var li = ul.selectAll('.list-item').data(qaLayers);
110796             li.exit().remove();
110797             var liEnter = li.enter().append('li').attr('class', function (d) {
110798               return 'list-item list-item-' + d.id;
110799             });
110800             var labelEnter = liEnter.append('label').each(function (d) {
110801               select(this).call(uiTooltip().title(_t.html('map_data.layers.' + d.id + '.tooltip')).placement('bottom'));
110802             });
110803             labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
110804               toggleLayer(d.id);
110805             });
110806             labelEnter.append('span').html(function (d) {
110807               return _t.html('map_data.layers.' + d.id + '.title');
110808             }); // Update
110809
110810             li.merge(liEnter).classed('active', function (d) {
110811               return d.layer.enabled();
110812             }).selectAll('input').property('checked', function (d) {
110813               return d.layer.enabled();
110814             });
110815           } // Beta feature - sample vector layers to support Detroit Mapping Challenge
110816           // https://github.com/osmus/detroit-mapping-challenge
110817
110818
110819           function drawVectorItems(selection) {
110820             var dataLayer = layers.layer('data');
110821             var vtData = [{
110822               name: 'Detroit Neighborhoods/Parks',
110823               src: 'neighborhoods-parks',
110824               tooltip: 'Neighborhood boundaries and parks as compiled by City of Detroit in concert with community groups.',
110825               template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmur6x34562qp9iv1u3ksf-54hev,jonahadkins.cjksmqxdx33jj2wp90xd9x2md-4e5y2/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
110826             }, {
110827               name: 'Detroit Composite POIs',
110828               src: 'composite-poi',
110829               tooltip: 'Fire Inspections, Business Licenses, and other public location data collated from the City of Detroit.',
110830               template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmm6a02sli31myxhsr7zf3-2sw8h/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
110831             }, {
110832               name: 'Detroit All-The-Places POIs',
110833               src: 'alltheplaces-poi',
110834               tooltip: 'Public domain business location data created by web scrapers.',
110835               template: 'https://{switch:a,b,c,d}.tiles.mapbox.com/v4/jonahadkins.cjksmswgk340g2vo06p1w9w0j-8fjjc/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1Ijoiam9uYWhhZGtpbnMiLCJhIjoiRlVVVkx3VSJ9.9sdVEK_B_VkEXPjssU5MqA'
110836             }]; // Only show this if the map is around Detroit..
110837
110838             var detroit = geoExtent([-83.5, 42.1], [-82.8, 42.5]);
110839             var showVectorItems = context.map().zoom() > 9 && detroit.contains(context.map().center());
110840             var container = selection.selectAll('.vectortile-container').data(showVectorItems ? [0] : []);
110841             container.exit().remove();
110842             var containerEnter = container.enter().append('div').attr('class', 'vectortile-container');
110843             containerEnter.append('h4').attr('class', 'vectortile-header').text('Detroit Vector Tiles (Beta)');
110844             containerEnter.append('ul').attr('class', 'layer-list layer-list-vectortile');
110845             containerEnter.append('div').attr('class', 'vectortile-footer').append('a').attr('target', '_blank').call(svgIcon('#iD-icon-out-link', 'inline')).attr('href', 'https://github.com/osmus/detroit-mapping-challenge').append('span').text('About these layers');
110846             container = container.merge(containerEnter);
110847             var ul = container.selectAll('.layer-list-vectortile');
110848             var li = ul.selectAll('.list-item').data(vtData);
110849             li.exit().remove();
110850             var liEnter = li.enter().append('li').attr('class', function (d) {
110851               return 'list-item list-item-' + d.src;
110852             });
110853             var labelEnter = liEnter.append('label').each(function (d) {
110854               select(this).call(uiTooltip().title(d.tooltip).placement('top'));
110855             });
110856             labelEnter.append('input').attr('type', 'radio').attr('name', 'vectortile').on('change', selectVTLayer);
110857             labelEnter.append('span').text(function (d) {
110858               return d.name;
110859             }); // Update
110860
110861             li.merge(liEnter).classed('active', isVTLayerSelected).selectAll('input').property('checked', isVTLayerSelected);
110862
110863             function isVTLayerSelected(d) {
110864               return dataLayer && dataLayer.template() === d.template;
110865             }
110866
110867             function selectVTLayer(d3_event, d) {
110868               corePreferences('settings-custom-data-url', d.template);
110869
110870               if (dataLayer) {
110871                 dataLayer.template(d.template, d.src);
110872                 dataLayer.enabled(true);
110873               }
110874             }
110875           }
110876
110877           function drawCustomDataItems(selection) {
110878             var dataLayer = layers.layer('data');
110879             var hasData = dataLayer && dataLayer.hasData();
110880             var showsData = hasData && dataLayer.enabled();
110881             var ul = selection.selectAll('.layer-list-data').data(dataLayer ? [0] : []); // Exit
110882
110883             ul.exit().remove(); // Enter
110884
110885             var ulEnter = ul.enter().append('ul').attr('class', 'layer-list layer-list-data');
110886             var liEnter = ulEnter.append('li').attr('class', 'list-item-data');
110887             var labelEnter = liEnter.append('label').call(uiTooltip().title(_t.html('map_data.layers.custom.tooltip')).placement('top'));
110888             labelEnter.append('input').attr('type', 'checkbox').on('change', function () {
110889               toggleLayer('data');
110890             });
110891             labelEnter.append('span').call(_t.append('map_data.layers.custom.title'));
110892             liEnter.append('button').attr('class', 'open-data-options').call(uiTooltip().title(_t.html('settings.custom_data.tooltip')).placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left')).on('click', function (d3_event) {
110893               d3_event.preventDefault();
110894               editCustom();
110895             }).call(svgIcon('#iD-icon-more'));
110896             liEnter.append('button').attr('class', 'zoom-to-data').call(uiTooltip().title(_t.html('map_data.layers.custom.zoom')).placement(_mainLocalizer.textDirection() === 'rtl' ? 'right' : 'left')).on('click', function (d3_event) {
110897               if (select(this).classed('disabled')) return;
110898               d3_event.preventDefault();
110899               d3_event.stopPropagation();
110900               dataLayer.fitZoom();
110901             }).call(svgIcon('#iD-icon-framed-dot', 'monochrome')); // Update
110902
110903             ul = ul.merge(ulEnter);
110904             ul.selectAll('.list-item-data').classed('active', showsData).selectAll('label').classed('deemphasize', !hasData).selectAll('input').property('disabled', !hasData).property('checked', showsData);
110905             ul.selectAll('button.zoom-to-data').classed('disabled', !hasData);
110906           }
110907
110908           function editCustom() {
110909             context.container().call(settingsCustomData);
110910           }
110911
110912           function customChanged(d) {
110913             var dataLayer = layers.layer('data');
110914
110915             if (d && d.url) {
110916               dataLayer.url(d.url);
110917             } else if (d && d.fileList) {
110918               dataLayer.fileList(d.fileList);
110919             }
110920           }
110921
110922           function drawPanelItems(selection) {
110923             var panelsListEnter = selection.selectAll('.md-extras-list').data([0]).enter().append('ul').attr('class', 'layer-list md-extras-list');
110924             var historyPanelLabelEnter = panelsListEnter.append('li').attr('class', 'history-panel-toggle-item').append('label').call(uiTooltip().title(_t.html('map_data.history_panel.tooltip')).keys([uiCmd('⌘⇧' + _t('info_panels.history.key'))]).placement('top'));
110925             historyPanelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
110926               d3_event.preventDefault();
110927               context.ui().info.toggle('history');
110928             });
110929             historyPanelLabelEnter.append('span').call(_t.append('map_data.history_panel.title'));
110930             var measurementPanelLabelEnter = panelsListEnter.append('li').attr('class', 'measurement-panel-toggle-item').append('label').call(uiTooltip().title(_t.html('map_data.measurement_panel.tooltip')).keys([uiCmd('⌘⇧' + _t('info_panels.measurement.key'))]).placement('top'));
110931             measurementPanelLabelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event) {
110932               d3_event.preventDefault();
110933               context.ui().info.toggle('measurement');
110934             });
110935             measurementPanelLabelEnter.append('span').call(_t.append('map_data.measurement_panel.title'));
110936           }
110937
110938           context.layers().on('change.uiSectionDataLayers', section.reRender);
110939           context.map().on('move.uiSectionDataLayers', debounce(function () {
110940             // Detroit layers may have moved in or out of view
110941             window.requestIdleCallback(section.reRender);
110942           }, 1000));
110943           return section;
110944         }
110945
110946         function uiSectionMapFeatures(context) {
110947           var _features = context.features().keys();
110948
110949           var section = uiSection('map-features', context).label(_t.html('map_data.map_features')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
110950
110951           function renderDisclosureContent(selection) {
110952             var container = selection.selectAll('.layer-feature-list-container').data([0]);
110953             var containerEnter = container.enter().append('div').attr('class', 'layer-feature-list-container');
110954             containerEnter.append('ul').attr('class', 'layer-list layer-feature-list');
110955             var footer = containerEnter.append('div').attr('class', 'feature-list-links section-footer');
110956             footer.append('a').attr('class', 'feature-list-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.disable_all')).on('click', function (d3_event) {
110957               d3_event.preventDefault();
110958               context.features().disableAll();
110959             });
110960             footer.append('a').attr('class', 'feature-list-link').attr('role', 'button').attr('href', '#').call(_t.append('issues.enable_all')).on('click', function (d3_event) {
110961               d3_event.preventDefault();
110962               context.features().enableAll();
110963             }); // Update
110964
110965             container = container.merge(containerEnter);
110966             container.selectAll('.layer-feature-list').call(drawListItems, _features, 'checkbox', 'feature', clickFeature, showsFeature);
110967           }
110968
110969           function drawListItems(selection, data, type, name, change, active) {
110970             var items = selection.selectAll('li').data(data); // Exit
110971
110972             items.exit().remove(); // Enter
110973
110974             var enter = items.enter().append('li').call(uiTooltip().title(function (d) {
110975               var tip = _t.html(name + '.' + d + '.tooltip');
110976
110977               if (autoHiddenFeature(d)) {
110978                 var msg = showsLayer('osm') ? _t.html('map_data.autohidden') : _t.html('map_data.osmhidden');
110979                 tip += '<div>' + msg + '</div>';
110980               }
110981
110982               return tip;
110983             }).placement('top'));
110984             var label = enter.append('label');
110985             label.append('input').attr('type', type).attr('name', name).on('change', change);
110986             label.append('span').html(function (d) {
110987               return _t.html(name + '.' + d + '.description');
110988             }); // Update
110989
110990             items = items.merge(enter);
110991             items.classed('active', active).selectAll('input').property('checked', active).property('indeterminate', autoHiddenFeature);
110992           }
110993
110994           function autoHiddenFeature(d) {
110995             return context.features().autoHidden(d);
110996           }
110997
110998           function showsFeature(d) {
110999             return context.features().enabled(d);
111000           }
111001
111002           function clickFeature(d3_event, d) {
111003             context.features().toggle(d);
111004           }
111005
111006           function showsLayer(id) {
111007             var layer = context.layers().layer(id);
111008             return layer && layer.enabled();
111009           } // add listeners
111010
111011
111012           context.features().on('change.map_features', section.reRender);
111013           return section;
111014         }
111015
111016         function uiSectionMapStyleOptions(context) {
111017           var section = uiSection('fill-area', context).label(_t.html('map_data.style_options')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
111018
111019           function renderDisclosureContent(selection) {
111020             var container = selection.selectAll('.layer-fill-list').data([0]);
111021             container.enter().append('ul').attr('class', 'layer-list layer-fill-list').merge(container).call(drawListItems, context.map().areaFillOptions, 'radio', 'area_fill', setFill, isActiveFill);
111022             var container2 = selection.selectAll('.layer-visual-diff-list').data([0]);
111023             container2.enter().append('ul').attr('class', 'layer-list layer-visual-diff-list').merge(container2).call(drawListItems, ['highlight_edits'], 'checkbox', 'visual_diff', toggleHighlightEdited, function () {
111024               return context.surface().classed('highlight-edited');
111025             });
111026           }
111027
111028           function drawListItems(selection, data, type, name, change, active) {
111029             var items = selection.selectAll('li').data(data); // Exit
111030
111031             items.exit().remove(); // Enter
111032
111033             var enter = items.enter().append('li').call(uiTooltip().title(function (d) {
111034               return _t.html(name + '.' + d + '.tooltip');
111035             }).keys(function (d) {
111036               var key = d === 'wireframe' ? _t('area_fill.wireframe.key') : null;
111037               if (d === 'highlight_edits') key = _t('map_data.highlight_edits.key');
111038               return key ? [key] : null;
111039             }).placement('top'));
111040             var label = enter.append('label');
111041             label.append('input').attr('type', type).attr('name', name).on('change', change);
111042             label.append('span').html(function (d) {
111043               return _t.html(name + '.' + d + '.description');
111044             }); // Update
111045
111046             items = items.merge(enter);
111047             items.classed('active', active).selectAll('input').property('checked', active).property('indeterminate', false);
111048           }
111049
111050           function isActiveFill(d) {
111051             return context.map().activeAreaFill() === d;
111052           }
111053
111054           function toggleHighlightEdited(d3_event) {
111055             d3_event.preventDefault();
111056             context.map().toggleHighlightEdited();
111057           }
111058
111059           function setFill(d3_event, d) {
111060             context.map().activeAreaFill(d);
111061           }
111062
111063           context.map().on('changeHighlighting.ui_style, changeAreaFill.ui_style', section.reRender);
111064           return section;
111065         }
111066
111067         function uiSectionPhotoOverlays(context) {
111068           var layers = context.layers();
111069           var section = uiSection('photo-overlays', context).label(_t.html('photo_overlays.title')).disclosureContent(renderDisclosureContent).expandedByDefault(false);
111070
111071           function renderDisclosureContent(selection) {
111072             var container = selection.selectAll('.photo-overlay-container').data([0]);
111073             container.enter().append('div').attr('class', 'photo-overlay-container').merge(container).call(drawPhotoItems).call(drawPhotoTypeItems).call(drawDateFilter).call(drawUsernameFilter);
111074           }
111075
111076           function drawPhotoItems(selection) {
111077             var photoKeys = context.photos().overlayLayerIDs();
111078             var photoLayers = layers.all().filter(function (obj) {
111079               return photoKeys.indexOf(obj.id) !== -1;
111080             });
111081             var data = photoLayers.filter(function (obj) {
111082               return obj.layer.supported();
111083             });
111084
111085             function layerSupported(d) {
111086               return d.layer && d.layer.supported();
111087             }
111088
111089             function layerEnabled(d) {
111090               return layerSupported(d) && d.layer.enabled();
111091             }
111092
111093             var ul = selection.selectAll('.layer-list-photos').data([0]);
111094             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-photos').merge(ul);
111095             var li = ul.selectAll('.list-item-photos').data(data);
111096             li.exit().remove();
111097             var liEnter = li.enter().append('li').attr('class', function (d) {
111098               var classes = 'list-item-photos list-item-' + d.id;
111099
111100               if (d.id === 'mapillary-signs' || d.id === 'mapillary-map-features') {
111101                 classes += ' indented';
111102               }
111103
111104               return classes;
111105             });
111106             var labelEnter = liEnter.append('label').each(function (d) {
111107               var titleID;
111108               if (d.id === 'mapillary-signs') titleID = 'mapillary.signs.tooltip';else if (d.id === 'mapillary') titleID = 'mapillary_images.tooltip';else if (d.id === 'kartaview') titleID = 'kartaview_images.tooltip';else titleID = d.id.replace(/-/g, '_') + '.tooltip';
111109               select(this).call(uiTooltip().title(_t.html(titleID)).placement('top'));
111110             });
111111             labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
111112               toggleLayer(d.id);
111113             });
111114             labelEnter.append('span').html(function (d) {
111115               var id = d.id;
111116               if (id === 'mapillary-signs') id = 'photo_overlays.traffic_signs';
111117               return _t.html(id.replace(/-/g, '_') + '.title');
111118             }); // Update
111119
111120             li.merge(liEnter).classed('active', layerEnabled).selectAll('input').property('checked', layerEnabled);
111121           }
111122
111123           function drawPhotoTypeItems(selection) {
111124             var data = context.photos().allPhotoTypes();
111125
111126             function typeEnabled(d) {
111127               return context.photos().showsPhotoType(d);
111128             }
111129
111130             var ul = selection.selectAll('.layer-list-photo-types').data([0]);
111131             ul.exit().remove();
111132             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-photo-types').merge(ul);
111133             var li = ul.selectAll('.list-item-photo-types').data(context.photos().shouldFilterByPhotoType() ? data : []);
111134             li.exit().remove();
111135             var liEnter = li.enter().append('li').attr('class', function (d) {
111136               return 'list-item-photo-types list-item-' + d;
111137             });
111138             var labelEnter = liEnter.append('label').each(function (d) {
111139               select(this).call(uiTooltip().title(_t.html('photo_overlays.photo_type.' + d + '.tooltip')).placement('top'));
111140             });
111141             labelEnter.append('input').attr('type', 'checkbox').on('change', function (d3_event, d) {
111142               context.photos().togglePhotoType(d);
111143             });
111144             labelEnter.append('span').html(function (d) {
111145               return _t.html('photo_overlays.photo_type.' + d + '.title');
111146             }); // Update
111147
111148             li.merge(liEnter).classed('active', typeEnabled).selectAll('input').property('checked', typeEnabled);
111149           }
111150
111151           function drawDateFilter(selection) {
111152             var data = context.photos().dateFilters();
111153
111154             function filterEnabled(d) {
111155               return context.photos().dateFilterValue(d);
111156             }
111157
111158             var ul = selection.selectAll('.layer-list-date-filter').data([0]);
111159             ul.exit().remove();
111160             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-date-filter').merge(ul);
111161             var li = ul.selectAll('.list-item-date-filter').data(context.photos().shouldFilterByDate() ? data : []);
111162             li.exit().remove();
111163             var liEnter = li.enter().append('li').attr('class', 'list-item-date-filter');
111164             var labelEnter = liEnter.append('label').each(function (d) {
111165               select(this).call(uiTooltip().title(_t.html('photo_overlays.date_filter.' + d + '.tooltip')).placement('top'));
111166             });
111167             labelEnter.append('span').html(function (d) {
111168               return _t.html('photo_overlays.date_filter.' + d + '.title');
111169             });
111170             labelEnter.append('input').attr('type', 'date').attr('class', 'list-item-input').attr('placeholder', _t('units.year_month_day')).call(utilNoAuto).each(function (d) {
111171               utilGetSetValue(select(this), context.photos().dateFilterValue(d) || '');
111172             }).on('change', function (d3_event, d) {
111173               var value = utilGetSetValue(select(this)).trim();
111174               context.photos().setDateFilter(d, value, true); // reload the displayed dates
111175
111176               li.selectAll('input').each(function (d) {
111177                 utilGetSetValue(select(this), context.photos().dateFilterValue(d) || '');
111178               });
111179             });
111180             li = li.merge(liEnter).classed('active', filterEnabled);
111181           }
111182
111183           function drawUsernameFilter(selection) {
111184             function filterEnabled() {
111185               return context.photos().usernames();
111186             }
111187
111188             var ul = selection.selectAll('.layer-list-username-filter').data([0]);
111189             ul.exit().remove();
111190             ul = ul.enter().append('ul').attr('class', 'layer-list layer-list-username-filter').merge(ul);
111191             var li = ul.selectAll('.list-item-username-filter').data(context.photos().shouldFilterByUsername() ? ['username-filter'] : []);
111192             li.exit().remove();
111193             var liEnter = li.enter().append('li').attr('class', 'list-item-username-filter');
111194             var labelEnter = liEnter.append('label').each(function () {
111195               select(this).call(uiTooltip().title(_t.html('photo_overlays.username_filter.tooltip')).placement('top'));
111196             });
111197             labelEnter.append('span').call(_t.append('photo_overlays.username_filter.title'));
111198             labelEnter.append('input').attr('type', 'text').attr('class', 'list-item-input').call(utilNoAuto).property('value', usernameValue).on('change', function () {
111199               var value = select(this).property('value');
111200               context.photos().setUsernameFilter(value, true);
111201               select(this).property('value', usernameValue);
111202             });
111203             li.merge(liEnter).classed('active', filterEnabled);
111204
111205             function usernameValue() {
111206               var usernames = context.photos().usernames();
111207               if (usernames) return usernames.join('; ');
111208               return usernames;
111209             }
111210           }
111211
111212           function toggleLayer(which) {
111213             setLayer(which, !showsLayer(which));
111214           }
111215
111216           function showsLayer(which) {
111217             var layer = layers.layer(which);
111218
111219             if (layer) {
111220               return layer.enabled();
111221             }
111222
111223             return false;
111224           }
111225
111226           function setLayer(which, enabled) {
111227             var layer = layers.layer(which);
111228
111229             if (layer) {
111230               layer.enabled(enabled);
111231             }
111232           }
111233
111234           context.layers().on('change.uiSectionPhotoOverlays', section.reRender);
111235           context.photos().on('change.uiSectionPhotoOverlays', section.reRender);
111236           return section;
111237         }
111238
111239         function uiPaneMapData(context) {
111240           var mapDataPane = uiPane('map-data', context).key(_t('map_data.key')).label(_t.html('map_data.title')).description(_t.html('map_data.description')).iconName('iD-icon-data').sections([uiSectionDataLayers(context), uiSectionPhotoOverlays(context), uiSectionMapStyleOptions(context), uiSectionMapFeatures(context)]);
111241           return mapDataPane;
111242         }
111243
111244         function uiPanePreferences(context) {
111245           var preferencesPane = uiPane('preferences', context).key(_t('preferences.key')).label(_t.html('preferences.title')).description(_t.html('preferences.description')).iconName('fas-user-cog').sections([uiSectionPrivacy(context)]);
111246           return preferencesPane;
111247         }
111248
111249         function uiInit(context) {
111250           var _initCounter = 0;
111251           var _needWidth = {};
111252
111253           var _lastPointerType;
111254
111255           function render(container) {
111256             container.on('click.ui', function (d3_event) {
111257               // we're only concerned with the primary mouse button
111258               if (d3_event.button !== 0) return;
111259               if (!d3_event.composedPath) return; // some targets have default click events we don't want to override
111260
111261               var isOkayTarget = d3_event.composedPath().some(function (node) {
111262                 // we only care about element nodes
111263                 return node.nodeType === 1 && ( // clicking <input> focuses it and/or changes a value
111264                 node.nodeName === 'INPUT' || // clicking <label> affects its <input> by default
111265                 node.nodeName === 'LABEL' || // clicking <a> opens a hyperlink by default
111266                 node.nodeName === 'A');
111267               });
111268               if (isOkayTarget) return; // disable double-tap-to-zoom on touchscreens
111269
111270               d3_event.preventDefault();
111271             });
111272             var detected = utilDetect(); // only WebKit supports gesture events
111273
111274             if ('GestureEvent' in window && // Listening for gesture events on iOS 13.4+ breaks double-tapping,
111275             // but we only need to do this on desktop Safari anyway. – #7694
111276             !detected.isMobileWebKit) {
111277               // On iOS we disable pinch-to-zoom of the UI via the `touch-action`
111278               // CSS property, but on desktop Safari we need to manually cancel the
111279               // default gesture events.
111280               container.on('gesturestart.ui gesturechange.ui gestureend.ui', function (d3_event) {
111281                 // disable pinch-to-zoom of the UI via multitouch trackpads on macOS Safari
111282                 d3_event.preventDefault();
111283               });
111284             }
111285
111286             if ('PointerEvent' in window) {
111287               select(window).on('pointerdown.ui pointerup.ui', function (d3_event) {
111288                 var pointerType = d3_event.pointerType || 'mouse';
111289
111290                 if (_lastPointerType !== pointerType) {
111291                   _lastPointerType = pointerType;
111292                   container.attr('pointer', pointerType);
111293                 }
111294               }, true);
111295             } else {
111296               _lastPointerType = 'mouse';
111297               container.attr('pointer', 'mouse');
111298             }
111299
111300             container.attr('lang', _mainLocalizer.localeCode()).attr('dir', _mainLocalizer.textDirection()); // setup fullscreen keybindings (no button shown at this time)
111301
111302             container.call(uiFullScreen(context));
111303             var map = context.map();
111304             map.redrawEnable(false); // don't draw until we've set zoom/lat/long
111305
111306             map.on('hitMinZoom.ui', function () {
111307               ui.flash.iconName('#iD-icon-no').label(_t.html('cannot_zoom'))();
111308             });
111309             container.append('svg').attr('id', 'ideditor-defs').call(ui.svgDefs);
111310             container.append('div').attr('class', 'sidebar').call(ui.sidebar);
111311             var content = container.append('div').attr('class', 'main-content active'); // Top toolbar
111312
111313             content.append('div').attr('class', 'top-toolbar-wrap').append('div').attr('class', 'top-toolbar fillD').call(uiTopToolbar(context));
111314             content.append('div').attr('class', 'main-map').attr('dir', 'ltr').call(map);
111315             var overMap = content.append('div').attr('class', 'over-map'); // HACK: Mobile Safari 14 likes to select anything selectable when long-
111316             // pressing, even if it's not targeted. This conflicts with long-pressing
111317             // to show the edit menu. We add a selectable offscreen element as the first
111318             // child to trick Safari into not showing the selection UI.
111319
111320             overMap.append('div').attr('class', 'select-trap').text('t');
111321             overMap.call(uiMapInMap(context)).call(uiNotice(context));
111322             overMap.append('div').attr('class', 'spinner').call(uiSpinner(context)); // Map controls
111323
111324             var controlsWrap = overMap.append('div').attr('class', 'map-controls-wrap');
111325             var controls = controlsWrap.append('div').attr('class', 'map-controls');
111326             controls.append('div').attr('class', 'map-control zoombuttons').call(uiZoom(context));
111327             controls.append('div').attr('class', 'map-control zoom-to-selection-control').call(uiZoomToSelection(context));
111328             controls.append('div').attr('class', 'map-control geolocate-control').call(uiGeolocate(context));
111329             controlsWrap.on('wheel.mapControls', function (d3_event) {
111330               if (!d3_event.deltaX) {
111331                 controlsWrap.node().scrollTop += d3_event.deltaY;
111332               }
111333             }); // Add panes
111334             // This should happen after map is initialized, as some require surface()
111335
111336             var panes = overMap.append('div').attr('class', 'map-panes');
111337             var uiPanes = [uiPaneBackground(context), uiPaneMapData(context), uiPaneIssues(context), uiPanePreferences(context), uiPaneHelp(context)];
111338             uiPanes.forEach(function (pane) {
111339               controls.append('div').attr('class', 'map-control map-pane-control ' + pane.id + '-control').call(pane.renderToggleButton);
111340               panes.call(pane.renderPane);
111341             });
111342             ui.info = uiInfo(context);
111343             overMap.call(ui.info);
111344             overMap.append('div').attr('class', 'photoviewer').classed('al', true) // 'al'=left,  'ar'=right
111345             .classed('hide', true).call(ui.photoviewer);
111346             overMap.append('div').attr('class', 'attribution-wrap').attr('dir', 'ltr').call(uiAttribution(context)); // Add footer
111347
111348             var about = content.append('div').attr('class', 'map-footer');
111349             about.append('div').attr('class', 'api-status').call(uiStatus(context));
111350             var footer = about.append('div').attr('class', 'map-footer-bar fillD');
111351             footer.append('div').attr('class', 'flash-wrap footer-hide');
111352             var footerWrap = footer.append('div').attr('class', 'main-footer-wrap footer-show');
111353             footerWrap.append('div').attr('class', 'scale-block').call(uiScale(context));
111354             var aboutList = footerWrap.append('div').attr('class', 'info-block').append('ul').attr('class', 'map-footer-list');
111355             aboutList.append('li').attr('class', 'user-list').call(uiContributors(context));
111356             var apiConnections = context.apiConnections();
111357
111358             if (apiConnections && apiConnections.length > 1) {
111359               aboutList.append('li').attr('class', 'source-switch').call(uiSourceSwitch(context).keys(apiConnections));
111360             }
111361
111362             aboutList.append('li').attr('class', 'issues-info').call(uiIssuesInfo(context));
111363             aboutList.append('li').attr('class', 'feature-warning').call(uiFeatureInfo(context));
111364             var issueLinks = aboutList.append('li');
111365             issueLinks.append('a').attr('target', '_blank').attr('href', 'https://github.com/openstreetmap/iD/issues').attr('aria-label', _t('report_a_bug')).call(svgIcon('#iD-icon-bug', 'light')).call(uiTooltip().title(_t.html('report_a_bug')).placement('top'));
111366             issueLinks.append('a').attr('target', '_blank').attr('href', 'https://github.com/openstreetmap/iD/blob/develop/CONTRIBUTING.md#translating').attr('aria-label', _t('help_translate')).call(svgIcon('#iD-icon-translate', 'light')).call(uiTooltip().title(_t.html('help_translate')).placement('top'));
111367             aboutList.append('li').attr('class', 'version').call(uiVersion(context));
111368
111369             if (!context.embed()) {
111370               aboutList.call(uiAccount(context));
111371             } // Setup map dimensions and move map to initial center/zoom.
111372             // This should happen after .main-content and toolbars exist.
111373
111374
111375             ui.onResize();
111376             map.redrawEnable(true);
111377             ui.hash = behaviorHash(context);
111378             ui.hash();
111379
111380             if (!ui.hash.hadHash) {
111381               map.centerZoom([0, 0], 2);
111382             } // Bind events
111383
111384
111385             window.onbeforeunload = function () {
111386               return context.save();
111387             };
111388
111389             window.onunload = function () {
111390               context.history().unlock();
111391             };
111392
111393             select(window).on('resize.editor', function () {
111394               ui.onResize();
111395             });
111396             var panPixels = 80;
111397             context.keybinding().on('⌫', function (d3_event) {
111398               d3_event.preventDefault();
111399             }).on([_t('sidebar.key'), '`', '²', '@'], ui.sidebar.toggle) // #5663, #6864 - common QWERTY, AZERTY
111400             .on('←', pan([panPixels, 0])).on('↑', pan([0, panPixels])).on('→', pan([-panPixels, 0])).on('↓', pan([0, -panPixels])).on(uiCmd('⌥←'), pan([map.dimensions()[0], 0])).on(uiCmd('⌥↑'), pan([0, map.dimensions()[1]])).on(uiCmd('⌥→'), pan([-map.dimensions()[0], 0])).on(uiCmd('⌥↓'), pan([0, -map.dimensions()[1]])).on(uiCmd('⌘' + _t('background.key')), function quickSwitch(d3_event) {
111401               if (d3_event) {
111402                 d3_event.stopImmediatePropagation();
111403                 d3_event.preventDefault();
111404               }
111405
111406               var previousBackground = context.background().findSource(corePreferences('background-last-used-toggle'));
111407
111408               if (previousBackground) {
111409                 var currentBackground = context.background().baseLayerSource();
111410                 corePreferences('background-last-used-toggle', currentBackground.id);
111411                 corePreferences('background-last-used', previousBackground.id);
111412                 context.background().baseLayerSource(previousBackground);
111413               }
111414             }).on(_t('area_fill.wireframe.key'), function toggleWireframe(d3_event) {
111415               d3_event.preventDefault();
111416               d3_event.stopPropagation();
111417               context.map().toggleWireframe();
111418             }).on(uiCmd('⌥' + _t('area_fill.wireframe.key')), function toggleOsmData(d3_event) {
111419               d3_event.preventDefault();
111420               d3_event.stopPropagation(); // Don't allow layer changes while drawing - #6584
111421
111422               var mode = context.mode();
111423               if (mode && /^draw/.test(mode.id)) return;
111424               var layer = context.layers().layer('osm');
111425
111426               if (layer) {
111427                 layer.enabled(!layer.enabled());
111428
111429                 if (!layer.enabled()) {
111430                   context.enter(modeBrowse(context));
111431                 }
111432               }
111433             }).on(_t('map_data.highlight_edits.key'), function toggleHighlightEdited(d3_event) {
111434               d3_event.preventDefault();
111435               context.map().toggleHighlightEdited();
111436             });
111437             context.on('enter.editor', function (entered) {
111438               container.classed('mode-' + entered.id, true);
111439             }).on('exit.editor', function (exited) {
111440               container.classed('mode-' + exited.id, false);
111441             });
111442             context.enter(modeBrowse(context));
111443
111444             if (!_initCounter++) {
111445               if (!ui.hash.startWalkthrough) {
111446                 context.container().call(uiSplash(context)).call(uiRestore(context));
111447               }
111448
111449               context.container().call(ui.shortcuts);
111450             }
111451
111452             var osm = context.connection();
111453             var auth = uiLoading(context).message(_t.html('loading_auth')).blocking(true);
111454
111455             if (osm && auth) {
111456               osm.on('authLoading.ui', function () {
111457                 context.container().call(auth);
111458               }).on('authDone.ui', function () {
111459                 auth.close();
111460               });
111461             }
111462
111463             _initCounter++;
111464
111465             if (ui.hash.startWalkthrough) {
111466               ui.hash.startWalkthrough = false;
111467               context.container().call(uiIntro(context));
111468             }
111469
111470             function pan(d) {
111471               return function (d3_event) {
111472                 if (d3_event.shiftKey) return;
111473                 if (context.container().select('.combobox').size()) return;
111474                 d3_event.preventDefault();
111475                 context.map().pan(d, 100);
111476               };
111477             }
111478           }
111479
111480           var ui = {};
111481
111482           var _loadPromise; // renders the iD interface into the container node
111483
111484
111485           ui.ensureLoaded = function () {
111486             if (_loadPromise) return _loadPromise;
111487             return _loadPromise = Promise.all([// must have strings and presets before loading the UI
111488             _mainLocalizer.ensureLoaded(), _mainPresetIndex.ensureLoaded()]).then(function () {
111489               if (!context.container().empty()) render(context.container());
111490             })["catch"](function (err) {
111491               return console.error(err);
111492             }); // eslint-disable-line
111493           }; // `ui.restart()` will destroy and rebuild the entire iD interface,
111494           // for example to switch the locale while iD is running.
111495
111496
111497           ui.restart = function () {
111498             context.keybinding().clear();
111499             _loadPromise = null;
111500             context.container().selectAll('*').remove();
111501             ui.ensureLoaded();
111502           };
111503
111504           ui.lastPointerType = function () {
111505             return _lastPointerType;
111506           };
111507
111508           ui.svgDefs = svgDefs(context);
111509           ui.flash = uiFlash(context);
111510           ui.sidebar = uiSidebar(context);
111511           ui.photoviewer = uiPhotoviewer(context);
111512           ui.shortcuts = uiShortcuts(context);
111513
111514           ui.onResize = function (withPan) {
111515             var map = context.map(); // Recalc dimensions of map and sidebar.. (`true` = force recalc)
111516             // This will call `getBoundingClientRect` and trigger reflow,
111517             //  but the values will be cached for later use.
111518
111519             var mapDimensions = utilGetDimensions(context.container().select('.main-content'), true);
111520             utilGetDimensions(context.container().select('.sidebar'), true);
111521
111522             if (withPan !== undefined) {
111523               map.redrawEnable(false);
111524               map.pan(withPan);
111525               map.redrawEnable(true);
111526             }
111527
111528             map.dimensions(mapDimensions);
111529             ui.photoviewer.onMapResize(); // check if header or footer have overflowed
111530
111531             ui.checkOverflow('.top-toolbar');
111532             ui.checkOverflow('.map-footer-bar'); // Use outdated code so it works on Explorer
111533
111534             var resizeWindowEvent = document.createEvent('Event');
111535             resizeWindowEvent.initEvent('resizeWindow', true, true);
111536             document.dispatchEvent(resizeWindowEvent);
111537           }; // Call checkOverflow when resizing or whenever the contents change.
111538
111539
111540           ui.checkOverflow = function (selector, reset) {
111541             if (reset) {
111542               delete _needWidth[selector];
111543             }
111544
111545             var selection = context.container().select(selector);
111546             if (selection.empty()) return;
111547             var scrollWidth = selection.property('scrollWidth');
111548             var clientWidth = selection.property('clientWidth');
111549             var needed = _needWidth[selector] || scrollWidth;
111550
111551             if (scrollWidth > clientWidth) {
111552               // overflow happening
111553               selection.classed('narrow', true);
111554
111555               if (!_needWidth[selector]) {
111556                 _needWidth[selector] = scrollWidth;
111557               }
111558             } else if (scrollWidth >= needed) {
111559               selection.classed('narrow', false);
111560             }
111561           };
111562
111563           ui.togglePanes = function (showPane) {
111564             var hidePanes = context.container().selectAll('.map-pane.shown');
111565             var side = _mainLocalizer.textDirection() === 'ltr' ? 'right' : 'left';
111566             hidePanes.classed('shown', false).classed('hide', true);
111567             context.container().selectAll('.map-pane-control button').classed('active', false);
111568
111569             if (showPane) {
111570               hidePanes.classed('shown', false).classed('hide', true).style(side, '-500px');
111571               context.container().selectAll('.' + showPane.attr('pane') + '-control button').classed('active', true);
111572               showPane.classed('shown', true).classed('hide', false);
111573
111574               if (hidePanes.empty()) {
111575                 showPane.style(side, '-500px').transition().duration(200).style(side, '0px');
111576               } else {
111577                 showPane.style(side, '0px');
111578               }
111579             } else {
111580               hidePanes.classed('shown', true).classed('hide', false).style(side, '0px').transition().duration(200).style(side, '-500px').on('end', function () {
111581                 select(this).classed('shown', false).classed('hide', true);
111582               });
111583             }
111584           };
111585
111586           var _editMenu = uiEditMenu(context);
111587
111588           ui.editMenu = function () {
111589             return _editMenu;
111590           };
111591
111592           ui.showEditMenu = function (anchorPoint, triggerType, operations) {
111593             // remove any displayed menu
111594             ui.closeEditMenu();
111595             if (!operations && context.mode().operations) operations = context.mode().operations();
111596             if (!operations || !operations.length) return; // disable menu if in wide selection, for example
111597
111598             if (!context.map().editableDataEnabled()) return;
111599             var surfaceNode = context.surface().node();
111600
111601             if (surfaceNode.focus) {
111602               // FF doesn't support it
111603               // focus the surface or else clicking off the menu may not trigger modeBrowse
111604               surfaceNode.focus();
111605             }
111606
111607             operations.forEach(function (operation) {
111608               if (operation.point) operation.point(anchorPoint);
111609             });
111610
111611             _editMenu.anchorLoc(anchorPoint).triggerType(triggerType).operations(operations); // render the menu
111612
111613
111614             context.map().supersurface.call(_editMenu);
111615           };
111616
111617           ui.closeEditMenu = function () {
111618             // remove any existing menu no matter how it was added
111619             context.map().supersurface.select('.edit-menu').remove();
111620           };
111621
111622           var _saveLoading = select(null);
111623
111624           context.uploader().on('saveStarted.ui', function () {
111625             _saveLoading = uiLoading(context).message(_t.html('save.uploading')).blocking(true);
111626             context.container().call(_saveLoading); // block input during upload
111627           }).on('saveEnded.ui', function () {
111628             _saveLoading.close();
111629
111630             _saveLoading = select(null);
111631           });
111632           return ui;
111633         }
111634
111635         function coreContext() {
111636           var _this = this;
111637
111638           var dispatch = dispatch$8('enter', 'exit', 'change');
111639           var context = utilRebind({}, dispatch, 'on');
111640
111641           var _deferred = new Set();
111642
111643           context.version = '2.20.4';
111644           context.privacyVersion = '20201202'; // iD will alter the hash so cache the parameters intended to setup the session
111645
111646           context.initialHashParams = window.location.hash ? utilStringQs(window.location.hash) : {};
111647           /* Changeset */
111648           // An osmChangeset object. Not loaded until needed.
111649
111650           context.changeset = null;
111651           var _defaultChangesetComment = context.initialHashParams.comment;
111652           var _defaultChangesetSource = context.initialHashParams.source;
111653           var _defaultChangesetHashtags = context.initialHashParams.hashtags;
111654
111655           context.defaultChangesetComment = function (val) {
111656             if (!arguments.length) return _defaultChangesetComment;
111657             _defaultChangesetComment = val;
111658             return context;
111659           };
111660
111661           context.defaultChangesetSource = function (val) {
111662             if (!arguments.length) return _defaultChangesetSource;
111663             _defaultChangesetSource = val;
111664             return context;
111665           };
111666
111667           context.defaultChangesetHashtags = function (val) {
111668             if (!arguments.length) return _defaultChangesetHashtags;
111669             _defaultChangesetHashtags = val;
111670             return context;
111671           };
111672           /* Document title */
111673
111674           /* (typically shown as the label for the browser window/tab) */
111675           // If true, iD will update the title based on what the user is doing
111676
111677
111678           var _setsDocumentTitle = true;
111679
111680           context.setsDocumentTitle = function (val) {
111681             if (!arguments.length) return _setsDocumentTitle;
111682             _setsDocumentTitle = val;
111683             return context;
111684           }; // The part of the title that is always the same
111685
111686
111687           var _documentTitleBase = document.title;
111688
111689           context.documentTitleBase = function (val) {
111690             if (!arguments.length) return _documentTitleBase;
111691             _documentTitleBase = val;
111692             return context;
111693           };
111694           /* User interface and keybinding */
111695
111696
111697           var _ui;
111698
111699           context.ui = function () {
111700             return _ui;
111701           };
111702
111703           context.lastPointerType = function () {
111704             return _ui.lastPointerType();
111705           };
111706
111707           var _keybinding = utilKeybinding('context');
111708
111709           context.keybinding = function () {
111710             return _keybinding;
111711           };
111712
111713           select(document).call(_keybinding);
111714           /* Straight accessors. Avoid using these if you can. */
111715           // Instantiate the connection here because it doesn't require passing in
111716           // `context` and it's needed for pre-init calls like `preauth`
111717
111718           var _connection = services.osm;
111719
111720           var _history;
111721
111722           var _validator;
111723
111724           var _uploader;
111725
111726           context.connection = function () {
111727             return _connection;
111728           };
111729
111730           context.history = function () {
111731             return _history;
111732           };
111733
111734           context.validator = function () {
111735             return _validator;
111736           };
111737
111738           context.uploader = function () {
111739             return _uploader;
111740           };
111741           /* Connection */
111742
111743
111744           context.preauth = function (options) {
111745             if (_connection) {
111746               _connection["switch"](options);
111747             }
111748
111749             return context;
111750           };
111751           /* connection options for source switcher (optional) */
111752
111753
111754           var _apiConnections;
111755
111756           context.apiConnections = function (val) {
111757             if (!arguments.length) return _apiConnections;
111758             _apiConnections = val;
111759             return context;
111760           }; // A string or array or locale codes to prefer over the browser's settings
111761
111762
111763           context.locale = function (locale) {
111764             if (!arguments.length) return _mainLocalizer.localeCode();
111765             _mainLocalizer.preferredLocaleCodes(locale);
111766             return context;
111767           };
111768
111769           function afterLoad(cid, callback) {
111770             return function (err, result) {
111771               if (err) {
111772                 // 400 Bad Request, 401 Unauthorized, 403 Forbidden..
111773                 if (err.status === 400 || err.status === 401 || err.status === 403) {
111774                   if (_connection) {
111775                     _connection.logout();
111776                   }
111777                 }
111778
111779                 if (typeof callback === 'function') {
111780                   callback(err);
111781                 }
111782
111783                 return;
111784               } else if (_connection && _connection.getConnectionId() !== cid) {
111785                 if (typeof callback === 'function') {
111786                   callback({
111787                     message: 'Connection Switched',
111788                     status: -1
111789                   });
111790                 }
111791
111792                 return;
111793               } else {
111794                 _history.merge(result.data, result.extent);
111795
111796                 if (typeof callback === 'function') {
111797                   callback(err, result);
111798                 }
111799
111800                 return;
111801               }
111802             };
111803           }
111804
111805           context.loadTiles = function (projection, callback) {
111806             var handle = window.requestIdleCallback(function () {
111807               _deferred["delete"](handle);
111808
111809               if (_connection && context.editableDataEnabled()) {
111810                 var cid = _connection.getConnectionId();
111811
111812                 _connection.loadTiles(projection, afterLoad(cid, callback));
111813               }
111814             });
111815
111816             _deferred.add(handle);
111817           };
111818
111819           context.loadTileAtLoc = function (loc, callback) {
111820             var handle = window.requestIdleCallback(function () {
111821               _deferred["delete"](handle);
111822
111823               if (_connection && context.editableDataEnabled()) {
111824                 var cid = _connection.getConnectionId();
111825
111826                 _connection.loadTileAtLoc(loc, afterLoad(cid, callback));
111827               }
111828             });
111829
111830             _deferred.add(handle);
111831           }; // Download the full entity and its parent relations. The callback may be called multiple times.
111832
111833
111834           context.loadEntity = function (entityID, callback) {
111835             if (_connection) {
111836               var cid = _connection.getConnectionId();
111837
111838               _connection.loadEntity(entityID, afterLoad(cid, callback)); // We need to fetch the parent relations separately.
111839
111840
111841               _connection.loadEntityRelations(entityID, afterLoad(cid, callback));
111842             }
111843           };
111844
111845           context.zoomToEntity = function (entityID, zoomTo) {
111846             // be sure to load the entity even if we're not going to zoom to it
111847             context.loadEntity(entityID, function (err, result) {
111848               if (err) return;
111849
111850               if (zoomTo !== false) {
111851                 var entity = result.data.find(function (e) {
111852                   return e.id === entityID;
111853                 });
111854
111855                 if (entity) {
111856                   _map.zoomTo(entity);
111857                 }
111858               }
111859             });
111860
111861             _map.on('drawn.zoomToEntity', function () {
111862               if (!context.hasEntity(entityID)) return;
111863
111864               _map.on('drawn.zoomToEntity', null);
111865
111866               context.on('enter.zoomToEntity', null);
111867               context.enter(modeSelect(context, [entityID]));
111868             });
111869
111870             context.on('enter.zoomToEntity', function () {
111871               if (_mode.id !== 'browse') {
111872                 _map.on('drawn.zoomToEntity', null);
111873
111874                 context.on('enter.zoomToEntity', null);
111875               }
111876             });
111877           };
111878
111879           var _minEditableZoom = 16;
111880
111881           context.minEditableZoom = function (val) {
111882             if (!arguments.length) return _minEditableZoom;
111883             _minEditableZoom = val;
111884
111885             if (_connection) {
111886               _connection.tileZoom(val);
111887             }
111888
111889             return context;
111890           }; // String length limits in Unicode characters, not JavaScript UTF-16 code units
111891
111892
111893           context.maxCharsForTagKey = function () {
111894             return 255;
111895           };
111896
111897           context.maxCharsForTagValue = function () {
111898             return 255;
111899           };
111900
111901           context.maxCharsForRelationRole = function () {
111902             return 255;
111903           };
111904
111905           function cleanOsmString(val, maxChars) {
111906             // be lenient with input
111907             if (val === undefined || val === null) {
111908               val = '';
111909             } else {
111910               val = val.toString();
111911             } // remove whitespace
111912
111913
111914             val = val.trim(); // use the canonical form of the string
111915
111916             if (val.normalize) val = val.normalize('NFC'); // trim to the number of allowed characters
111917
111918             return utilUnicodeCharsTruncated(val, maxChars);
111919           }
111920
111921           context.cleanTagKey = function (val) {
111922             return cleanOsmString(val, context.maxCharsForTagKey());
111923           };
111924
111925           context.cleanTagValue = function (val) {
111926             return cleanOsmString(val, context.maxCharsForTagValue());
111927           };
111928
111929           context.cleanRelationRole = function (val) {
111930             return cleanOsmString(val, context.maxCharsForRelationRole());
111931           };
111932           /* History */
111933
111934
111935           var _inIntro = false;
111936
111937           context.inIntro = function (val) {
111938             if (!arguments.length) return _inIntro;
111939             _inIntro = val;
111940             return context;
111941           }; // Immediately save the user's history to localstorage, if possible
111942           // This is called someteimes, but also on the `window.onbeforeunload` handler
111943
111944
111945           context.save = function () {
111946             // no history save, no message onbeforeunload
111947             if (_inIntro || context.container().select('.modal').size()) return;
111948             var canSave;
111949
111950             if (_mode && _mode.id === 'save') {
111951               canSave = false; // Attempt to prevent user from creating duplicate changes - see #5200
111952
111953               if (services.osm && services.osm.isChangesetInflight()) {
111954                 _history.clearSaved();
111955
111956                 return;
111957               }
111958             } else {
111959               canSave = context.selectedIDs().every(function (id) {
111960                 var entity = context.hasEntity(id);
111961                 return entity && !entity.isDegenerate();
111962               });
111963             }
111964
111965             if (canSave) {
111966               _history.save();
111967             }
111968
111969             if (_history.hasChanges()) {
111970               return _t('save.unsaved_changes');
111971             }
111972           }; // Debounce save, since it's a synchronous localStorage write,
111973           // and history changes can happen frequently (e.g. when dragging).
111974
111975
111976           context.debouncedSave = debounce(context.save, 350);
111977
111978           function withDebouncedSave(fn) {
111979             return function () {
111980               var result = fn.apply(_history, arguments);
111981               context.debouncedSave();
111982               return result;
111983             };
111984           }
111985           /* Graph */
111986
111987
111988           context.hasEntity = function (id) {
111989             return _history.graph().hasEntity(id);
111990           };
111991
111992           context.entity = function (id) {
111993             return _history.graph().entity(id);
111994           };
111995           /* Modes */
111996
111997
111998           var _mode;
111999
112000           context.mode = function () {
112001             return _mode;
112002           };
112003
112004           context.enter = function (newMode) {
112005             if (_mode) {
112006               _mode.exit();
112007
112008               dispatch.call('exit', _this, _mode);
112009             }
112010
112011             _mode = newMode;
112012
112013             _mode.enter();
112014
112015             dispatch.call('enter', _this, _mode);
112016           };
112017
112018           context.selectedIDs = function () {
112019             return _mode && _mode.selectedIDs && _mode.selectedIDs() || [];
112020           };
112021
112022           context.activeID = function () {
112023             return _mode && _mode.activeID && _mode.activeID();
112024           };
112025
112026           var _selectedNoteID;
112027
112028           context.selectedNoteID = function (noteID) {
112029             if (!arguments.length) return _selectedNoteID;
112030             _selectedNoteID = noteID;
112031             return context;
112032           }; // NOTE: Don't change the name of this until UI v3 is merged
112033
112034
112035           var _selectedErrorID;
112036
112037           context.selectedErrorID = function (errorID) {
112038             if (!arguments.length) return _selectedErrorID;
112039             _selectedErrorID = errorID;
112040             return context;
112041           };
112042           /* Behaviors */
112043
112044
112045           context.install = function (behavior) {
112046             return context.surface().call(behavior);
112047           };
112048
112049           context.uninstall = function (behavior) {
112050             return context.surface().call(behavior.off);
112051           };
112052           /* Copy/Paste */
112053
112054
112055           var _copyGraph;
112056
112057           context.copyGraph = function () {
112058             return _copyGraph;
112059           };
112060
112061           var _copyIDs = [];
112062
112063           context.copyIDs = function (val) {
112064             if (!arguments.length) return _copyIDs;
112065             _copyIDs = val;
112066             _copyGraph = _history.graph();
112067             return context;
112068           };
112069
112070           var _copyLonLat;
112071
112072           context.copyLonLat = function (val) {
112073             if (!arguments.length) return _copyLonLat;
112074             _copyLonLat = val;
112075             return context;
112076           };
112077           /* Background */
112078
112079
112080           var _background;
112081
112082           context.background = function () {
112083             return _background;
112084           };
112085           /* Features */
112086
112087
112088           var _features;
112089
112090           context.features = function () {
112091             return _features;
112092           };
112093
112094           context.hasHiddenConnections = function (id) {
112095             var graph = _history.graph();
112096
112097             var entity = graph.entity(id);
112098             return _features.hasHiddenConnections(entity, graph);
112099           };
112100           /* Photos */
112101
112102
112103           var _photos;
112104
112105           context.photos = function () {
112106             return _photos;
112107           };
112108           /* Map */
112109
112110
112111           var _map;
112112
112113           context.map = function () {
112114             return _map;
112115           };
112116
112117           context.layers = function () {
112118             return _map.layers();
112119           };
112120
112121           context.surface = function () {
112122             return _map.surface;
112123           };
112124
112125           context.editableDataEnabled = function () {
112126             return _map.editableDataEnabled();
112127           };
112128
112129           context.surfaceRect = function () {
112130             return _map.surface.node().getBoundingClientRect();
112131           };
112132
112133           context.editable = function () {
112134             // don't allow editing during save
112135             var mode = context.mode();
112136             if (!mode || mode.id === 'save') return false;
112137             return _map.editableDataEnabled();
112138           };
112139           /* Debug */
112140
112141
112142           var _debugFlags = {
112143             tile: false,
112144             // tile boundaries
112145             collision: false,
112146             // label collision bounding boxes
112147             imagery: false,
112148             // imagery bounding polygons
112149             target: false,
112150             // touch targets
112151             downloaded: false // downloaded data from osm
112152
112153           };
112154
112155           context.debugFlags = function () {
112156             return _debugFlags;
112157           };
112158
112159           context.getDebug = function (flag) {
112160             return flag && _debugFlags[flag];
112161           };
112162
112163           context.setDebug = function (flag, val) {
112164             if (arguments.length === 1) val = true;
112165             _debugFlags[flag] = val;
112166             dispatch.call('change');
112167             return context;
112168           };
112169           /* Container */
112170
112171
112172           var _container = select(null);
112173
112174           context.container = function (val) {
112175             if (!arguments.length) return _container;
112176             _container = val;
112177
112178             _container.classed('ideditor', true);
112179
112180             return context;
112181           };
112182
112183           context.containerNode = function (val) {
112184             if (!arguments.length) return context.container().node();
112185             context.container(select(val));
112186             return context;
112187           };
112188
112189           var _embed;
112190
112191           context.embed = function (val) {
112192             if (!arguments.length) return _embed;
112193             _embed = val;
112194             return context;
112195           };
112196           /* Assets */
112197
112198
112199           var _assetPath = '';
112200
112201           context.assetPath = function (val) {
112202             if (!arguments.length) return _assetPath;
112203             _assetPath = val;
112204             _mainFileFetcher.assetPath(val);
112205             return context;
112206           };
112207
112208           var _assetMap = {};
112209
112210           context.assetMap = function (val) {
112211             if (!arguments.length) return _assetMap;
112212             _assetMap = val;
112213             _mainFileFetcher.assetMap(val);
112214             return context;
112215           };
112216
112217           context.asset = function (val) {
112218             if (/^http(s)?:\/\//i.test(val)) return val;
112219             var filename = _assetPath + val;
112220             return _assetMap[filename] || filename;
112221           };
112222
112223           context.imagePath = function (val) {
112224             return context.asset("img/".concat(val));
112225           };
112226           /* reset (aka flush) */
112227
112228
112229           context.reset = context.flush = function () {
112230             context.debouncedSave.cancel();
112231             Array.from(_deferred).forEach(function (handle) {
112232               window.cancelIdleCallback(handle);
112233
112234               _deferred["delete"](handle);
112235             });
112236             Object.values(services).forEach(function (service) {
112237               if (service && typeof service.reset === 'function') {
112238                 service.reset(context);
112239               }
112240             });
112241             context.changeset = null;
112242
112243             _validator.reset();
112244
112245             _features.reset();
112246
112247             _history.reset();
112248
112249             _uploader.reset(); // don't leave stale state in the inspector
112250
112251
112252             context.container().select('.inspector-wrap *').remove();
112253             return context;
112254           };
112255           /* Projections */
112256
112257
112258           context.projection = geoRawMercator();
112259           context.curtainProjection = geoRawMercator();
112260           /* Init */
112261
112262           context.init = function () {
112263             instantiateInternal();
112264             initializeDependents();
112265             return context; // Load variables and properties. No property of `context` should be accessed
112266             // until this is complete since load statuses are indeterminate. The order
112267             // of instantiation shouldn't matter.
112268
112269             function instantiateInternal() {
112270               _history = coreHistory(context);
112271               context.graph = _history.graph;
112272               context.pauseChangeDispatch = _history.pauseChangeDispatch;
112273               context.resumeChangeDispatch = _history.resumeChangeDispatch;
112274               context.perform = withDebouncedSave(_history.perform);
112275               context.replace = withDebouncedSave(_history.replace);
112276               context.pop = withDebouncedSave(_history.pop);
112277               context.overwrite = withDebouncedSave(_history.overwrite);
112278               context.undo = withDebouncedSave(_history.undo);
112279               context.redo = withDebouncedSave(_history.redo);
112280               _validator = coreValidator(context);
112281               _uploader = coreUploader(context);
112282               _background = rendererBackground(context);
112283               _features = rendererFeatures(context);
112284               _map = rendererMap(context);
112285               _photos = rendererPhotos(context);
112286               _ui = uiInit(context);
112287             } // Set up objects that might need to access properties of `context`. The order
112288             // might matter if dependents make calls to each other. Be wary of async calls.
112289
112290
112291             function initializeDependents() {
112292               if (context.initialHashParams.presets) {
112293                 _mainPresetIndex.addablePresetIDs(new Set(context.initialHashParams.presets.split(',')));
112294               }
112295
112296               if (context.initialHashParams.locale) {
112297                 _mainLocalizer.preferredLocaleCodes(context.initialHashParams.locale);
112298               } // kick off some async work
112299
112300
112301               _mainLocalizer.ensureLoaded();
112302
112303               _background.ensureLoaded();
112304
112305               _mainPresetIndex.ensureLoaded();
112306               Object.values(services).forEach(function (service) {
112307                 if (service && typeof service.init === 'function') {
112308                   service.init();
112309                 }
112310               });
112311
112312               _map.init();
112313
112314               _validator.init();
112315
112316               _features.init();
112317
112318               if (services.maprules && context.initialHashParams.maprules) {
112319                 d3_json(context.initialHashParams.maprules).then(function (mapcss) {
112320                   services.maprules.init();
112321                   mapcss.forEach(function (mapcssSelector) {
112322                     return services.maprules.addRule(mapcssSelector);
112323                   });
112324                 })["catch"](function () {
112325                   /* ignore */
112326                 });
112327               } // if the container isn't available, e.g. when testing, don't load the UI
112328
112329
112330               if (!context.container().empty()) {
112331                 _ui.ensureLoaded().then(function () {
112332                   _photos.init();
112333                 });
112334               }
112335             }
112336           };
112337
112338           return context;
112339         }
112340
112341         // NSI contains the most correct tagging for many commonly mapped features.
112342         // See https://github.com/osmlab/name-suggestion-index  and  https://nsi.guide
112343         // DATA
112344
112345         var _nsiStatus = 'loading'; // 'loading', 'ok', 'failed'
112346
112347         var _nsi = {}; // Sometimes we can upgrade a feature tagged like `building=yes` to a better tag.
112348
112349         var buildingPreset = {
112350           'building/commercial': true,
112351           'building/government': true,
112352           'building/hotel': true,
112353           'building/retail': true,
112354           'building/office': true,
112355           'building/supermarket': true,
112356           'building/yes': true
112357         }; // Exceptions to the namelike regexes.
112358         // Usually a tag suffix contains a language code like `name:en`, `name:ru`
112359         // but we want to exclude things like `operator:type`, `name:etymology`, etc..
112360
112361         var notNames = /:(colou?r|type|forward|backward|left|right|etymology|pronunciation|wikipedia)$/i; // Exceptions to the branchlike regexes
112362
112363         var notBranches = /(coop|express|wireless|factory|outlet)/i; // PRIVATE FUNCTIONS
112364         // `setNsiSources()`
112365         // Adds the sources to iD's filemap so we can start downloading data.
112366         //
112367
112368         function setNsiSources() {
112369           var nsiVersion = packageJSON.devDependencies['name-suggestion-index'];
112370           var v = parseVersion(nsiVersion);
112371           var vMinor = "".concat(v.major, ".").concat(v.minor);
112372           var sources = {
112373             'nsi_data': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/nsi.min.json"),
112374             'nsi_dissolved': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/dissolved.min.json"),
112375             'nsi_features': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/featureCollection.min.json"),
112376             'nsi_generics': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/genericWords.min.json"),
112377             'nsi_presets': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/presets/nsi-id-presets.min.json"),
112378             'nsi_replacements': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/replacements.min.json"),
112379             'nsi_trees': "https://cdn.jsdelivr.net/npm/name-suggestion-index@".concat(vMinor, "/dist/trees.min.json")
112380           };
112381           var fileMap = _mainFileFetcher.fileMap();
112382
112383           for (var k in sources) {
112384             if (!fileMap[k]) fileMap[k] = sources[k];
112385           }
112386         } // `loadNsiPresets()`
112387         //  Returns a Promise fulfilled when the presets have been downloaded and merged into iD.
112388         //
112389
112390
112391         function loadNsiPresets() {
112392           return Promise.all([_mainFileFetcher.get('nsi_presets'), _mainFileFetcher.get('nsi_features')]).then(function (vals) {
112393             // Add `suggestion=true` to all the nsi presets
112394             // The preset json schema doesn't include it, but the iD code still uses it
112395             Object.values(vals[0].presets).forEach(function (preset) {
112396               return preset.suggestion = true;
112397             });
112398             _mainPresetIndex.merge({
112399               presets: vals[0].presets,
112400               featureCollection: vals[1]
112401             });
112402           });
112403         } // `loadNsiData()`
112404         //  Returns a Promise fulfilled when the other data have been downloaded and processed
112405         //
112406
112407
112408         function loadNsiData() {
112409           return Promise.all([_mainFileFetcher.get('nsi_data'), _mainFileFetcher.get('nsi_dissolved'), _mainFileFetcher.get('nsi_replacements'), _mainFileFetcher.get('nsi_trees')]).then(function (vals) {
112410             _nsi = {
112411               data: vals[0].nsi,
112412               // the raw name-suggestion-index data
112413               dissolved: vals[1].dissolved,
112414               // list of dissolved items
112415               replacements: vals[2].replacements,
112416               // trivial old->new qid replacements
112417               trees: vals[3].trees,
112418               // metadata about trees, main tags
112419               kvt: new Map(),
112420               // Map (k -> Map (v -> t) )
112421               qids: new Map(),
112422               // Map (wd/wp tag values -> qids)
112423               ids: new Map() // Map (id -> NSI item)
112424
112425             };
112426             _nsi.matcher = new Matcher();
112427
112428             _nsi.matcher.buildMatchIndex(_nsi.data);
112429
112430             _nsi.matcher.buildLocationIndex(_nsi.data, _mainLocations.loco());
112431
112432             Object.keys(_nsi.data).forEach(function (tkv) {
112433               var category = _nsi.data[tkv];
112434               var parts = tkv.split('/', 3); // tkv = "tree/key/value"
112435
112436               var t = parts[0];
112437               var k = parts[1];
112438               var v = parts[2]; // Build a reverse index of keys -> values -> trees present in the name-suggestion-index
112439               // Collect primary keys  (e.g. "amenity", "craft", "shop", "man_made", "route", etc)
112440               // "amenity": {
112441               //   "restaurant": "brands"
112442               // }
112443
112444               var vmap = _nsi.kvt.get(k);
112445
112446               if (!vmap) {
112447                 vmap = new Map();
112448
112449                 _nsi.kvt.set(k, vmap);
112450               }
112451
112452               vmap.set(v, t);
112453               var tree = _nsi.trees[t]; // e.g. "brands", "operators"
112454
112455               var mainTag = tree.mainTag; // e.g. "brand:wikidata", "operator:wikidata", etc
112456
112457               var items = category.items || [];
112458               items.forEach(function (item) {
112459                 // Remember some useful things for later, cache NSI id -> item
112460                 item.tkv = tkv;
112461                 item.mainTag = mainTag;
112462
112463                 _nsi.ids.set(item.id, item); // Cache Wikidata/Wikipedia values -> qid, for #6416
112464
112465
112466                 var wd = item.tags[mainTag];
112467                 var wp = item.tags[mainTag.replace('wikidata', 'wikipedia')];
112468                 if (wd) _nsi.qids.set(wd, wd);
112469                 if (wp && wd) _nsi.qids.set(wp, wd);
112470               });
112471             });
112472           });
112473         } // `gatherKVs()`
112474         // Gather all the k/v pairs that we will run through the NSI matcher.
112475         // An OSM tags object can contain anything, but only a few tags will be interesting to NSI.
112476         //
112477         // This function will return the interesting tag pairs like:
112478         //   "amenity/restaurant", "man_made/flagpole"
112479         // and fallbacks like
112480         //   "amenity/yes"
112481         // excluding things like
112482         //   "tiger:reviewed", "surface", "ref", etc.
112483         //
112484         // Arguments
112485         //   `tags`: `Object` containing the feature's OSM tags
112486         // Returns
112487         //   `Object` containing kv pairs to test:
112488         //   {
112489         //     'primary': Set(),
112490         //     'alternate': Set()
112491         //   }
112492         //
112493
112494
112495         function gatherKVs(tags) {
112496           var primary = new Set();
112497           var alternate = new Set();
112498           Object.keys(tags).forEach(function (osmkey) {
112499             var osmvalue = tags[osmkey];
112500             if (!osmvalue) return; // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184
112501
112502             if (osmkey === 'route_master') osmkey = 'route';
112503
112504             var vmap = _nsi.kvt.get(osmkey);
112505
112506             if (!vmap) return; // not an interesting key
112507
112508             if (vmap.get(osmvalue)) {
112509               // Matched a category in NSI
112510               primary.add("".concat(osmkey, "/").concat(osmvalue)); // interesting key/value
112511             } else if (osmvalue === 'yes') {
112512               alternate.add("".concat(osmkey, "/").concat(osmvalue)); // fallback key/yes
112513             }
112514           }); // Can we try a generic building fallback match? - See #6122, #7197
112515           // Only try this if we do a preset match and find nothing else remarkable about that building.
112516           // For example, a way with `building=yes` + `name=Westfield` may be a Westfield department store.
112517           // But a way with `building=yes` + `name=Westfield` + `public_transport=station` is a train station for a town named "Westfield"
112518
112519           var preset = _mainPresetIndex.matchTags(tags, 'area');
112520
112521           if (buildingPreset[preset.id]) {
112522             alternate.add('building/yes');
112523           }
112524
112525           return {
112526             primary: primary,
112527             alternate: alternate
112528           };
112529         } // `identifyTree()`
112530         // NSI has a concept of trees: "brands", "operators", "flags", "transit".
112531         // The tree determines things like which tags are namelike, and which tags hold important wikidata.
112532         // This takes an Object of tags and tries to identify what tree to use.
112533         //
112534         // Arguments
112535         //   `tags`: `Object` containing the feature's OSM tags
112536         // Returns
112537         //   `string` the name of the tree if known
112538         //   or 'unknown' if it could match several trees (e.g. amenity/yes)
112539         //   or null if no match
112540         //
112541
112542
112543         function identifyTree(tags) {
112544           var unknown;
112545           var t; // Check all tags
112546
112547           Object.keys(tags).forEach(function (osmkey) {
112548             if (t) return; // found already
112549
112550             var osmvalue = tags[osmkey];
112551             if (!osmvalue) return; // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184
112552
112553             if (osmkey === 'route_master') osmkey = 'route';
112554
112555             var vmap = _nsi.kvt.get(osmkey);
112556
112557             if (!vmap) return; // this key is not in nsi
112558
112559             if (osmvalue === 'yes') {
112560               unknown = 'unknown';
112561             } else {
112562               t = vmap.get(osmvalue);
112563             }
112564           });
112565           return t || unknown || null;
112566         } // `gatherNames()`
112567         // Gather all the namelike values that we will run through the NSI matcher.
112568         // It will gather values primarily from tags `name`, `name:ru`, `flag:name`
112569         //  and fallback to alternate tags like `brand`, `brand:ru`, `alt_name`
112570         //
112571         // Arguments
112572         //   `tags`: `Object` containing the feature's OSM tags
112573         // Returns
112574         //   `Object` containing namelike values to test:
112575         //   {
112576         //     'primary': Set(),
112577         //     'fallbacks': Set()
112578         //   }
112579         //
112580
112581
112582         function gatherNames(tags) {
112583           var empty = {
112584             primary: new Set(),
112585             alternate: new Set()
112586           };
112587           var primary = new Set();
112588           var alternate = new Set();
112589           var foundSemi = false;
112590           var testNameFragments = false;
112591           var patterns; // Patterns for matching OSM keys that might contain namelike values.
112592           // These roughly correspond to the "trees" concept in name-suggestion-index,
112593
112594           var t = identifyTree(tags);
112595           if (!t) return empty;
112596
112597           if (t === 'transit') {
112598             patterns = {
112599               primary: /^network$/i,
112600               alternate: /^(operator|operator:\w+|network:\w+|\w+_name|\w+_name:\w+)$/i
112601             };
112602           } else if (t === 'flags') {
112603             patterns = {
112604               primary: /^(flag:name|flag:name:\w+)$/i,
112605               alternate: /^(flag|flag:\w+|subject|subject:\w+)$/i // note: no `country`, we special-case it below
112606
112607             };
112608           } else if (t === 'brands') {
112609             testNameFragments = true;
112610             patterns = {
112611               primary: /^(name|name:\w+)$/i,
112612               alternate: /^(brand|brand:\w+|operator|operator:\w+|\w+_name|\w+_name:\w+)/i
112613             };
112614           } else if (t === 'operators') {
112615             testNameFragments = true;
112616             patterns = {
112617               primary: /^(name|name:\w+|operator|operator:\w+)$/i,
112618               alternate: /^(brand|brand:\w+|\w+_name|\w+_name:\w+)/i
112619             };
112620           } else {
112621             // unknown/multiple
112622             testNameFragments = true;
112623             patterns = {
112624               primary: /^(name|name:\w+)$/i,
112625               alternate: /^(brand|brand:\w+|network|network:\w+|operator|operator:\w+|\w+_name|\w+_name:\w+)/i
112626             };
112627           } // Test `name` fragments, longest to shortest, to fit them into a "Name Branch" pattern.
112628           // e.g. "TUI ReiseCenter - Neuss Innenstadt" -> ["TUI", "ReiseCenter", "Neuss", "Innenstadt"]
112629
112630
112631           if (tags.name && testNameFragments) {
112632             var nameParts = tags.name.split(/[\s\-\/,.]/);
112633
112634             for (var split = nameParts.length; split > 0; split--) {
112635               var name = nameParts.slice(0, split).join(' '); // e.g. "TUI ReiseCenter"
112636
112637               primary.add(name);
112638             }
112639           } // Check all tags
112640
112641
112642           Object.keys(tags).forEach(function (osmkey) {
112643             var osmvalue = tags[osmkey];
112644             if (!osmvalue) return;
112645
112646             if (isNamelike(osmkey, 'primary')) {
112647               if (/;/.test(osmvalue)) {
112648                 foundSemi = true;
112649               } else {
112650                 primary.add(osmvalue);
112651                 alternate["delete"](osmvalue);
112652               }
112653             } else if (!primary.has(osmvalue) && isNamelike(osmkey, 'alternate')) {
112654               if (/;/.test(osmvalue)) {
112655                 foundSemi = true;
112656               } else {
112657                 alternate.add(osmvalue);
112658               }
112659             }
112660           }); // For flags only, fallback to `country` tag only if no other namelike values were found.
112661           // See https://github.com/openstreetmap/iD/pull/8305#issuecomment-769174070
112662
112663           if (tags.man_made === 'flagpole' && !primary.size && !alternate.size && !!tags.country) {
112664             var osmvalue = tags.country;
112665
112666             if (/;/.test(osmvalue)) {
112667               foundSemi = true;
112668             } else {
112669               alternate.add(osmvalue);
112670             }
112671           } // If any namelike value contained a semicolon, return empty set and don't try matching anything.
112672
112673
112674           if (foundSemi) {
112675             return empty;
112676           } else {
112677             return {
112678               primary: primary,
112679               alternate: alternate
112680             };
112681           }
112682
112683           function isNamelike(osmkey, which) {
112684             if (osmkey === 'old_name') return false;
112685             return patterns[which].test(osmkey) && !notNames.test(osmkey);
112686           }
112687         } // `gatherTuples()`
112688         // Generate all combinations of [key,value,name] that we want to test.
112689         // This prioritizes them so that the primary name and k/v pairs go first
112690         //
112691         // Arguments
112692         //   `tryKVs`: `Object` containing primary and alternate k/v pairs to test
112693         //   `tryNames`: `Object` containing primary and alternate names to test
112694         // Returns
112695         //   `Array`: tuple objects ordered by priority
112696         //
112697
112698
112699         function gatherTuples(tryKVs, tryNames) {
112700           var tuples = [];
112701           ['primary', 'alternate'].forEach(function (whichName) {
112702             // test names longest to shortest
112703             var arr = Array.from(tryNames[whichName]).sort(function (a, b) {
112704               return b.length - a.length;
112705             });
112706             arr.forEach(function (n) {
112707               ['primary', 'alternate'].forEach(function (whichKV) {
112708                 tryKVs[whichKV].forEach(function (kv) {
112709                   var parts = kv.split('/', 2);
112710                   var k = parts[0];
112711                   var v = parts[1];
112712                   tuples.push({
112713                     k: k,
112714                     v: v,
112715                     n: n
112716                   });
112717                 });
112718               });
112719             });
112720           });
112721           return tuples;
112722         } // `_upgradeTags()`
112723         // Try to match a feature to a canonical record in name-suggestion-index
112724         // and upgrade the tags to match.
112725         //
112726         // Arguments
112727         //   `tags`: `Object` containing the feature's OSM tags
112728         //   `loc`: Location where this feature exists, as a [lon, lat]
112729         // Returns
112730         //   `Object` containing the result, or `null` if no changes needed:
112731         //   {
112732         //     'newTags': `Object` - The tags the the feature should have
112733         //     'matched': `Object` - The matched item
112734         //   }
112735         //
112736
112737
112738         function _upgradeTags(tags, loc) {
112739           var newTags = Object.assign({}, tags); // shallow copy
112740
112741           var changed = false; // Before anything, perform trivial Wikipedia/Wikidata replacements
112742
112743           Object.keys(newTags).forEach(function (osmkey) {
112744             var matchTag = osmkey.match(/^(\w+:)?wikidata$/);
112745
112746             if (matchTag) {
112747               // Look at '*:wikidata' tags
112748               var prefix = matchTag[1] || '';
112749               var wd = newTags[osmkey];
112750               var replace = _nsi.replacements[wd]; // If it matches a QID in the replacement list...
112751
112752               if (replace && replace.wikidata !== undefined) {
112753                 // replace or delete `*:wikidata` tag
112754                 changed = true;
112755
112756                 if (replace.wikidata) {
112757                   newTags[osmkey] = replace.wikidata;
112758                 } else {
112759                   delete newTags[osmkey];
112760                 }
112761               }
112762
112763               if (replace && replace.wikipedia !== undefined) {
112764                 // replace or delete `*:wikipedia` tag
112765                 changed = true;
112766                 var wpkey = "".concat(prefix, "wikipedia");
112767
112768                 if (replace.wikipedia) {
112769                   newTags[wpkey] = replace.wikipedia;
112770                 } else {
112771                   delete newTags[wpkey];
112772                 }
112773               }
112774             }
112775           }); // Match a 'route_master' as if it were a 'route' - name-suggestion-index#5184
112776
112777           var isRouteMaster = tags.type === 'route_master'; // Gather key/value tag pairs to try to match
112778
112779           var tryKVs = gatherKVs(tags);
112780
112781           if (!tryKVs.primary.size && !tryKVs.alternate.size) {
112782             return changed ? {
112783               newTags: newTags,
112784               matched: null
112785             } : null;
112786           } // Gather namelike tag values to try to match
112787
112788
112789           var tryNames = gatherNames(tags); // Do `wikidata=*` or `wikipedia=*` tags identify this entity as a chain? - See #6416
112790           // If so, these tags can be swapped to e.g. `brand:wikidata`/`brand:wikipedia`.
112791
112792           var foundQID = _nsi.qids.get(tags.wikidata) || _nsi.qids.get(tags.wikipedia);
112793
112794           if (foundQID) tryNames.primary.add(foundQID); // matcher will recognize the Wikidata QID as name too
112795
112796           if (!tryNames.primary.size && !tryNames.alternate.size) {
112797             return changed ? {
112798               newTags: newTags,
112799               matched: null
112800             } : null;
112801           } // Order the [key,value,name] tuples - test primary names before alternate names
112802
112803
112804           var tuples = gatherTuples(tryKVs, tryNames);
112805           var foundPrimary = false;
112806           var bestItem; // Test [key,value,name] tuples against the NSI matcher until we get a primary match or exhaust all options.
112807
112808           for (var i = 0; i < tuples.length && !foundPrimary; i++) {
112809             var tuple = tuples[i];
112810
112811             var hits = _nsi.matcher.match(tuple.k, tuple.v, tuple.n, loc); // Attempt to match an item in NSI
112812
112813
112814             if (!hits || !hits.length) continue; // no match, try next tuple
112815
112816             if (hits[0].match !== 'primary' && hits[0].match !== 'alternate') break; // a generic match, stop looking
112817             // A match may contain multiple results, the first one is likely the best one for this location
112818             // e.g. `['pfk-a54c14', 'kfc-1ff19c', 'kfc-658eea']`
112819
112820             for (var j = 0; j < hits.length; j++) {
112821               var hit = hits[j];
112822               var isPrimary = hits[j].match === 'primary';
112823               var itemID = hit.itemID;
112824               if (_nsi.dissolved[itemID]) continue; // Don't upgrade to a dissolved item
112825
112826               var item = _nsi.ids.get(itemID);
112827
112828               if (!item) continue;
112829               var mainTag = item.mainTag; // e.g. `brand:wikidata`
112830
112831               var itemQID = item.tags[mainTag]; // e.g. `brand:wikidata` qid
112832
112833               var notQID = newTags["not:".concat(mainTag)]; // e.g. `not:brand:wikidata` qid
112834
112835               if ( // Exceptions, skip this hit
112836               !itemQID || itemQID === notQID || // No `*:wikidata` or matched a `not:*:wikidata`
112837               newTags.office && !item.tags.office // feature may be a corporate office for a brand? - #6416
112838               ) {
112839                 continue; // continue looking
112840               } // If we get here, the hit is good..
112841
112842
112843               if (!bestItem || isPrimary) {
112844                 bestItem = item;
112845
112846                 if (isPrimary) {
112847                   foundPrimary = true;
112848                 }
112849
112850                 break; // can ignore the rest of the hits from this match
112851               }
112852             }
112853           } // At this point we have matched a canonical item and can suggest tag upgrades..
112854
112855
112856           if (bestItem) {
112857             var _ret = function () {
112858               var itemID = bestItem.id;
112859               var item = JSON.parse(JSON.stringify(bestItem)); // deep copy
112860
112861               var tkv = item.tkv;
112862               var parts = tkv.split('/', 3); // tkv = "tree/key/value"
112863
112864               var k = parts[1];
112865               var v = parts[2];
112866               var category = _nsi.data[tkv];
112867               var properties = category.properties || {}; // Preserve some tags that we specifically don't want NSI to overwrite. ('^name', sometimes)
112868
112869               var preserveTags = item.preserveTags || properties.preserveTags || []; // These tags can be toplevel tags -or- attributes - so we generally want to preserve existing values - #8615
112870               // We'll only _replace_ the tag value if this tag is the toplevel/defining tag for the matched item (`k`)
112871
112872               ['building', 'emergency', 'internet_access', 'takeaway'].forEach(function (osmkey) {
112873                 if (k !== osmkey) preserveTags.push("^".concat(osmkey, "$"));
112874               });
112875               var regexes = preserveTags.map(function (s) {
112876                 return new RegExp(s, 'i');
112877               });
112878               var keepTags = {};
112879               Object.keys(newTags).forEach(function (osmkey) {
112880                 if (regexes.some(function (regex) {
112881                   return regex.test(osmkey);
112882                 })) {
112883                   keepTags[osmkey] = newTags[osmkey];
112884                 }
112885               }); // Remove any primary tags ("amenity", "craft", "shop", "man_made", "route", etc) that have a
112886               // value like `amenity=yes` or `shop=yes` (exceptions have already been added to `keepTags` above)
112887
112888               _nsi.kvt.forEach(function (vmap, k) {
112889                 if (newTags[k] === 'yes') delete newTags[k];
112890               }); // Replace mistagged `wikidata`/`wikipedia` with e.g. `brand:wikidata`/`brand:wikipedia`
112891
112892
112893               if (foundQID) {
112894                 delete newTags.wikipedia;
112895                 delete newTags.wikidata;
112896               } // Do the tag upgrade
112897
112898
112899               Object.assign(newTags, item.tags, keepTags); // Swap `route` back to `route_master` - name-suggestion-index#5184
112900
112901               if (isRouteMaster) {
112902                 newTags.route_master = newTags.route;
112903                 delete newTags.route;
112904               } // Special `branch` splitting rules - IF..
112905               // - NSI is suggesting to replace `name`, AND
112906               // - `branch` doesn't already contain something, AND
112907               // - original name has not moved to an alternate name (e.g. "Dunkin' Donuts" -> "Dunkin'"), AND
112908               // - original name is "some name" + "some stuff", THEN
112909               // consider splitting `name` into `name`/`branch`..
112910
112911
112912               var origName = tags.name;
112913               var newName = newTags.name;
112914
112915               if (newName && origName && newName !== origName && !newTags.branch) {
112916                 var newNames = gatherNames(newTags);
112917                 var newSet = new Set([].concat(_toConsumableArray(newNames.primary), _toConsumableArray(newNames.alternate)));
112918                 var isMoved = newSet.has(origName); // another tag holds the original name now
112919
112920                 if (!isMoved) {
112921                   // Test name fragments, longest to shortest, to fit them into a "Name Branch" pattern.
112922                   // e.g. "TUI ReiseCenter - Neuss Innenstadt" -> ["TUI", "ReiseCenter", "Neuss", "Innenstadt"]
112923                   var nameParts = origName.split(/[\s\-\/,.]/);
112924
112925                   for (var split = nameParts.length; split > 0; split--) {
112926                     var name = nameParts.slice(0, split).join(' '); // e.g. "TUI ReiseCenter"
112927
112928                     var branch = nameParts.slice(split).join(' '); // e.g. "Neuss Innenstadt"
112929
112930                     var nameHits = _nsi.matcher.match(k, v, name, loc);
112931
112932                     if (!nameHits || !nameHits.length) continue; // no match, try next name fragment
112933
112934                     if (nameHits.some(function (hit) {
112935                       return hit.itemID === itemID;
112936                     })) {
112937                       // matched the name fragment to the same itemID above
112938                       if (branch) {
112939                         if (notBranches.test(branch)) {
112940                           // "branch" was detected but is noise ("factory outlet", etc)
112941                           newTags.name = origName; // Leave `name` alone, this part of the name may be significant..
112942                         } else {
112943                           var branchHits = _nsi.matcher.match(k, v, branch, loc);
112944
112945                           if (branchHits && branchHits.length) {
112946                             // if "branch" matched something else in NSI..
112947                             if (branchHits[0].match === 'primary' || branchHits[0].match === 'alternate') {
112948                               // if another brand! (e.g. "KFC - Taco Bell"?)
112949                               return {
112950                                 v: null
112951                               }; //   bail out - can't suggest tags in this case
112952                             } // else a generic (e.g. "gas", "cafe") - ignore
112953
112954                           } else {
112955                             // "branch" is not noise and not something in NSI
112956                             newTags.branch = branch; // Stick it in the `branch` tag..
112957                           }
112958                         }
112959                       }
112960
112961                       break;
112962                     }
112963                   }
112964                 }
112965               }
112966
112967               return {
112968                 v: {
112969                   newTags: newTags,
112970                   matched: item
112971                 }
112972               };
112973             }();
112974
112975             if (_typeof(_ret) === "object") return _ret.v;
112976           }
112977
112978           return changed ? {
112979             newTags: newTags,
112980             matched: null
112981           } : null;
112982         } // `_isGenericName()`
112983         // Is the `name` tag generic?
112984         //
112985         // Arguments
112986         //   `tags`: `Object` containing the feature's OSM tags
112987         // Returns
112988         //   `true` if it is generic, `false` if not
112989         //
112990
112991
112992         function _isGenericName(tags) {
112993           var n = tags.name;
112994           if (!n) return false; // tryNames just contains the `name` tag value and nothing else
112995
112996           var tryNames = {
112997             primary: new Set([n]),
112998             alternate: new Set()
112999           }; // Gather key/value tag pairs to try to match
113000
113001           var tryKVs = gatherKVs(tags);
113002           if (!tryKVs.primary.size && !tryKVs.alternate.size) return false; // Order the [key,value,name] tuples - test primary before alternate
113003
113004           var tuples = gatherTuples(tryKVs, tryNames);
113005
113006           for (var i = 0; i < tuples.length; i++) {
113007             var tuple = tuples[i];
113008
113009             var hits = _nsi.matcher.match(tuple.k, tuple.v, tuple.n); // Attempt to match an item in NSI
113010             // If we get a `excludeGeneric` hit, this is a generic name.
113011
113012
113013             if (hits && hits.length && hits[0].match === 'excludeGeneric') return true;
113014           }
113015
113016           return false;
113017         } // PUBLIC INTERFACE
113018
113019
113020         var serviceNsi = {
113021           // `init()`
113022           // On init, start preparing the name-suggestion-index
113023           //
113024           init: function init() {
113025             // Note: service.init is called immediately after the presetManager has started loading its data.
113026             // We expect to chain onto an unfulfilled promise here.
113027             setNsiSources();
113028             _mainPresetIndex.ensureLoaded().then(function () {
113029               return loadNsiPresets();
113030             }).then(function () {
113031               return delay(100);
113032             }) // wait briefly for locationSets to enter the locationManager queue
113033             .then(function () {
113034               return _mainLocations.mergeLocationSets([]);
113035             }) // wait for locationSets to resolve
113036             .then(function () {
113037               return loadNsiData();
113038             }).then(function () {
113039               return _nsiStatus = 'ok';
113040             })["catch"](function () {
113041               return _nsiStatus = 'failed';
113042             });
113043
113044             function delay(msec) {
113045               return new Promise(function (resolve) {
113046                 window.setTimeout(resolve, msec);
113047               });
113048             }
113049           },
113050           // `reset()`
113051           // Reset is called when user saves data to OSM (does nothing here)
113052           //
113053           reset: function reset() {},
113054           // `status()`
113055           // To let other code know how it's going...
113056           //
113057           // Returns
113058           //   `String`: 'loading', 'ok', 'failed'
113059           //
113060           status: function status() {
113061             return _nsiStatus;
113062           },
113063           // `isGenericName()`
113064           // Is the `name` tag generic?
113065           //
113066           // Arguments
113067           //   `tags`: `Object` containing the feature's OSM tags
113068           // Returns
113069           //   `true` if it is generic, `false` if not
113070           //
113071           isGenericName: function isGenericName(tags) {
113072             return _isGenericName(tags);
113073           },
113074           // `upgradeTags()`
113075           // Suggest tag upgrades.
113076           // This function will not modify the input tags, it makes a copy.
113077           //
113078           // Arguments
113079           //   `tags`: `Object` containing the feature's OSM tags
113080           //   `loc`: Location where this feature exists, as a [lon, lat]
113081           // Returns
113082           //   `Object` containing the result, or `null` if no changes needed:
113083           //   {
113084           //     'newTags': `Object` - The tags the the feature should have
113085           //     'matched': `Object` - The matched item
113086           //   }
113087           //
113088           upgradeTags: function upgradeTags(tags, loc) {
113089             return _upgradeTags(tags, loc);
113090           },
113091           // `cache()`
113092           // Direct access to the NSI cache, useful for testing or breaking things
113093           //
113094           // Returns
113095           //   `Object`: the internal NSI cache
113096           //
113097           cache: function cache() {
113098             return _nsi;
113099           }
113100         };
113101
113102         var apibase$1 = 'https://kartaview.org';
113103         var maxResults$1 = 1000;
113104         var tileZoom$1 = 14;
113105         var tiler$3 = utilTiler().zoomExtent([tileZoom$1, tileZoom$1]).skipNullIsland(true);
113106         var dispatch$3 = dispatch$8('loadedImages');
113107         var imgZoom = d3_zoom().extent([[0, 0], [320, 240]]).translateExtent([[0, 0], [320, 240]]).scaleExtent([1, 15]);
113108
113109         var _oscCache;
113110
113111         var _oscSelectedImage;
113112
113113         var _loadViewerPromise$1;
113114
113115         function abortRequest$3(controller) {
113116           controller.abort();
113117         }
113118
113119         function maxPageAtZoom(z) {
113120           if (z < 15) return 2;
113121           if (z === 15) return 5;
113122           if (z === 16) return 10;
113123           if (z === 17) return 20;
113124           if (z === 18) return 40;
113125           if (z > 18) return 80;
113126         }
113127
113128         function loadTiles$1(which, url, projection) {
113129           var currZoom = Math.floor(geoScaleToZoom(projection.scale()));
113130           var tiles = tiler$3.getTiles(projection); // abort inflight requests that are no longer needed
113131
113132           var cache = _oscCache[which];
113133           Object.keys(cache.inflight).forEach(function (k) {
113134             var wanted = tiles.find(function (tile) {
113135               return k.indexOf(tile.id + ',') === 0;
113136             });
113137
113138             if (!wanted) {
113139               abortRequest$3(cache.inflight[k]);
113140               delete cache.inflight[k];
113141             }
113142           });
113143           tiles.forEach(function (tile) {
113144             loadNextTilePage$1(which, currZoom, url, tile);
113145           });
113146         }
113147
113148         function loadNextTilePage$1(which, currZoom, url, tile) {
113149           var cache = _oscCache[which];
113150           var bbox = tile.extent.bbox();
113151           var maxPages = maxPageAtZoom(currZoom);
113152           var nextPage = cache.nextPage[tile.id] || 1;
113153           var params = utilQsString({
113154             ipp: maxResults$1,
113155             page: nextPage,
113156             // client_id: clientId,
113157             bbTopLeft: [bbox.maxY, bbox.minX].join(','),
113158             bbBottomRight: [bbox.minY, bbox.maxX].join(',')
113159           }, true);
113160           if (nextPage > maxPages) return;
113161           var id = tile.id + ',' + String(nextPage);
113162           if (cache.loaded[id] || cache.inflight[id]) return;
113163           var controller = new AbortController();
113164           cache.inflight[id] = controller;
113165           var options = {
113166             method: 'POST',
113167             signal: controller.signal,
113168             body: params,
113169             headers: {
113170               'Content-Type': 'application/x-www-form-urlencoded'
113171             }
113172           };
113173           d3_json(url, options).then(function (data) {
113174             cache.loaded[id] = true;
113175             delete cache.inflight[id];
113176
113177             if (!data || !data.currentPageItems || !data.currentPageItems.length) {
113178               throw new Error('No Data');
113179             }
113180
113181             var features = data.currentPageItems.map(function (item) {
113182               var loc = [+item.lng, +item.lat];
113183               var d;
113184
113185               if (which === 'images') {
113186                 d = {
113187                   loc: loc,
113188                   key: item.id,
113189                   ca: +item.heading,
113190                   captured_at: item.shot_date || item.date_added,
113191                   captured_by: item.username,
113192                   imagePath: item.lth_name,
113193                   sequence_id: item.sequence_id,
113194                   sequence_index: +item.sequence_index
113195                 }; // cache sequence info
113196
113197                 var seq = _oscCache.sequences[d.sequence_id];
113198
113199                 if (!seq) {
113200                   seq = {
113201                     rotation: 0,
113202                     images: []
113203                   };
113204                   _oscCache.sequences[d.sequence_id] = seq;
113205                 }
113206
113207                 seq.images[d.sequence_index] = d;
113208                 _oscCache.images.forImageKey[d.key] = d; // cache imageKey -> image
113209               }
113210
113211               return {
113212                 minX: loc[0],
113213                 minY: loc[1],
113214                 maxX: loc[0],
113215                 maxY: loc[1],
113216                 data: d
113217               };
113218             });
113219             cache.rtree.load(features);
113220
113221             if (data.currentPageItems.length === maxResults$1) {
113222               // more pages to load
113223               cache.nextPage[tile.id] = nextPage + 1;
113224               loadNextTilePage$1(which, currZoom, url, tile);
113225             } else {
113226               cache.nextPage[tile.id] = Infinity; // no more pages to load
113227             }
113228
113229             if (which === 'images') {
113230               dispatch$3.call('loadedImages');
113231             }
113232           })["catch"](function () {
113233             cache.loaded[id] = true;
113234             delete cache.inflight[id];
113235           });
113236         } // partition viewport into higher zoom tiles
113237
113238
113239         function partitionViewport$1(projection) {
113240           var z = geoScaleToZoom(projection.scale());
113241           var z2 = Math.ceil(z * 2) / 2 + 2.5; // round to next 0.5 and add 2.5
113242
113243           var tiler = utilTiler().zoomExtent([z2, z2]);
113244           return tiler.getTiles(projection).map(function (tile) {
113245             return tile.extent;
113246           });
113247         } // no more than `limit` results per partition.
113248
113249
113250         function searchLimited$1(limit, projection, rtree) {
113251           limit = limit || 5;
113252           return partitionViewport$1(projection).reduce(function (result, extent) {
113253             var found = rtree.search(extent.bbox()).slice(0, limit).map(function (d) {
113254               return d.data;
113255             });
113256             return found.length ? result.concat(found) : result;
113257           }, []);
113258         }
113259
113260         var serviceKartaview = {
113261           init: function init() {
113262             if (!_oscCache) {
113263               this.reset();
113264             }
113265
113266             this.event = utilRebind(this, dispatch$3, 'on');
113267           },
113268           reset: function reset() {
113269             if (_oscCache) {
113270               Object.values(_oscCache.images.inflight).forEach(abortRequest$3);
113271             }
113272
113273             _oscCache = {
113274               images: {
113275                 inflight: {},
113276                 loaded: {},
113277                 nextPage: {},
113278                 rtree: new RBush(),
113279                 forImageKey: {}
113280               },
113281               sequences: {}
113282             };
113283             _oscSelectedImage = null;
113284           },
113285           images: function images(projection) {
113286             var limit = 5;
113287             return searchLimited$1(limit, projection, _oscCache.images.rtree);
113288           },
113289           sequences: function sequences(projection) {
113290             var viewport = projection.clipExtent();
113291             var min = [viewport[0][0], viewport[1][1]];
113292             var max = [viewport[1][0], viewport[0][1]];
113293             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
113294             var sequenceKeys = {}; // all sequences for images in viewport
113295
113296             _oscCache.images.rtree.search(bbox).forEach(function (d) {
113297               sequenceKeys[d.data.sequence_id] = true;
113298             }); // make linestrings from those sequences
113299
113300
113301             var lineStrings = [];
113302             Object.keys(sequenceKeys).forEach(function (sequenceKey) {
113303               var seq = _oscCache.sequences[sequenceKey];
113304               var images = seq && seq.images;
113305
113306               if (images) {
113307                 lineStrings.push({
113308                   type: 'LineString',
113309                   coordinates: images.map(function (d) {
113310                     return d.loc;
113311                   }).filter(Boolean),
113312                   properties: {
113313                     captured_at: images[0] ? images[0].captured_at : null,
113314                     captured_by: images[0] ? images[0].captured_by : null,
113315                     key: sequenceKey
113316                   }
113317                 });
113318               }
113319             });
113320             return lineStrings;
113321           },
113322           cachedImage: function cachedImage(imageKey) {
113323             return _oscCache.images.forImageKey[imageKey];
113324           },
113325           loadImages: function loadImages(projection) {
113326             var url = apibase$1 + '/1.0/list/nearby-photos/';
113327             loadTiles$1('images', url, projection);
113328           },
113329           ensureViewerLoaded: function ensureViewerLoaded(context) {
113330             if (_loadViewerPromise$1) return _loadViewerPromise$1; // add kartaview-wrapper
113331
113332             var wrap = context.container().select('.photoviewer').selectAll('.kartaview-wrapper').data([0]);
113333             var that = this;
113334             var wrapEnter = wrap.enter().append('div').attr('class', 'photo-wrapper kartaview-wrapper').classed('hide', true).call(imgZoom.on('zoom', zoomPan)).on('dblclick.zoom', null);
113335             wrapEnter.append('div').attr('class', 'photo-attribution fillD');
113336             var controlsEnter = wrapEnter.append('div').attr('class', 'photo-controls-wrap').append('div').attr('class', 'photo-controls');
113337             controlsEnter.append('button').on('click.back', step(-1)).text('◄');
113338             controlsEnter.append('button').on('click.rotate-ccw', rotate(-90)).text('⤿');
113339             controlsEnter.append('button').on('click.rotate-cw', rotate(90)).text('⤾');
113340             controlsEnter.append('button').on('click.forward', step(1)).text('►');
113341             wrapEnter.append('div').attr('class', 'kartaview-image-wrap'); // Register viewer resize handler
113342
113343             context.ui().photoviewer.on('resize.kartaview', function (dimensions) {
113344               imgZoom = d3_zoom().extent([[0, 0], dimensions]).translateExtent([[0, 0], dimensions]).scaleExtent([1, 15]).on('zoom', zoomPan);
113345             });
113346
113347             function zoomPan(d3_event) {
113348               var t = d3_event.transform;
113349               context.container().select('.photoviewer .kartaview-image-wrap').call(utilSetTransform, t.x, t.y, t.k);
113350             }
113351
113352             function rotate(deg) {
113353               return function () {
113354                 if (!_oscSelectedImage) return;
113355                 var sequenceKey = _oscSelectedImage.sequence_id;
113356                 var sequence = _oscCache.sequences[sequenceKey];
113357                 if (!sequence) return;
113358                 var r = sequence.rotation || 0;
113359                 r += deg;
113360                 if (r > 180) r -= 360;
113361                 if (r < -180) r += 360;
113362                 sequence.rotation = r;
113363                 var wrap = context.container().select('.photoviewer .kartaview-wrapper');
113364                 wrap.transition().duration(100).call(imgZoom.transform, identity$2);
113365                 wrap.selectAll('.kartaview-image').transition().duration(100).style('transform', 'rotate(' + r + 'deg)');
113366               };
113367             }
113368
113369             function step(stepBy) {
113370               return function () {
113371                 if (!_oscSelectedImage) return;
113372                 var sequenceKey = _oscSelectedImage.sequence_id;
113373                 var sequence = _oscCache.sequences[sequenceKey];
113374                 if (!sequence) return;
113375                 var nextIndex = _oscSelectedImage.sequence_index + stepBy;
113376                 var nextImage = sequence.images[nextIndex];
113377                 if (!nextImage) return;
113378                 context.map().centerEase(nextImage.loc);
113379                 that.selectImage(context, nextImage.key);
113380               };
113381             } // don't need any async loading so resolve immediately
113382
113383
113384             _loadViewerPromise$1 = Promise.resolve();
113385             return _loadViewerPromise$1;
113386           },
113387           showViewer: function showViewer(context) {
113388             var viewer = context.container().select('.photoviewer').classed('hide', false);
113389             var isHidden = viewer.selectAll('.photo-wrapper.kartaview-wrapper.hide').size();
113390
113391             if (isHidden) {
113392               viewer.selectAll('.photo-wrapper:not(.kartaview-wrapper)').classed('hide', true);
113393               viewer.selectAll('.photo-wrapper.kartaview-wrapper').classed('hide', false);
113394             }
113395
113396             return this;
113397           },
113398           hideViewer: function hideViewer(context) {
113399             _oscSelectedImage = null;
113400             this.updateUrlImage(null);
113401             var viewer = context.container().select('.photoviewer');
113402             if (!viewer.empty()) viewer.datum(null);
113403             viewer.classed('hide', true).selectAll('.photo-wrapper').classed('hide', true);
113404             context.container().selectAll('.viewfield-group, .sequence, .icon-sign').classed('currentView', false);
113405             return this.setStyles(context, null, true);
113406           },
113407           selectImage: function selectImage(context, imageKey) {
113408             var d = this.cachedImage(imageKey);
113409             _oscSelectedImage = d;
113410             this.updateUrlImage(imageKey);
113411             var viewer = context.container().select('.photoviewer');
113412             if (!viewer.empty()) viewer.datum(d);
113413             this.setStyles(context, null, true);
113414             context.container().selectAll('.icon-sign').classed('currentView', false);
113415             if (!d) return this;
113416             var wrap = context.container().select('.photoviewer .kartaview-wrapper');
113417             var imageWrap = wrap.selectAll('.kartaview-image-wrap');
113418             var attribution = wrap.selectAll('.photo-attribution').text('');
113419             wrap.transition().duration(100).call(imgZoom.transform, identity$2);
113420             imageWrap.selectAll('.kartaview-image').remove();
113421
113422             if (d) {
113423               var sequence = _oscCache.sequences[d.sequence_id];
113424               var r = sequence && sequence.rotation || 0;
113425               imageWrap.append('img').attr('class', 'kartaview-image').attr('src', apibase$1 + '/' + d.imagePath).style('transform', 'rotate(' + r + 'deg)');
113426
113427               if (d.captured_by) {
113428                 attribution.append('a').attr('class', 'captured_by').attr('target', '_blank').attr('href', 'https://kartaview.org/user/' + encodeURIComponent(d.captured_by)).text('@' + d.captured_by);
113429                 attribution.append('span').text('|');
113430               }
113431
113432               if (d.captured_at) {
113433                 attribution.append('span').attr('class', 'captured_at').text(localeDateString(d.captured_at));
113434                 attribution.append('span').text('|');
113435               }
113436
113437               attribution.append('a').attr('class', 'image-link').attr('target', '_blank').attr('href', 'https://kartaview.org/details/' + d.sequence_id + '/' + d.sequence_index).text('kartaview.org');
113438             }
113439
113440             return this;
113441
113442             function localeDateString(s) {
113443               if (!s) return null;
113444               var options = {
113445                 day: 'numeric',
113446                 month: 'short',
113447                 year: 'numeric'
113448               };
113449               var d = new Date(s);
113450               if (isNaN(d.getTime())) return null;
113451               return d.toLocaleDateString(_mainLocalizer.localeCode(), options);
113452             }
113453           },
113454           getSelectedImage: function getSelectedImage() {
113455             return _oscSelectedImage;
113456           },
113457           getSequenceKeyForImage: function getSequenceKeyForImage(d) {
113458             return d && d.sequence_id;
113459           },
113460           // Updates the currently highlighted sequence and selected bubble.
113461           // Reset is only necessary when interacting with the viewport because
113462           // this implicitly changes the currently selected bubble/sequence
113463           setStyles: function setStyles(context, hovered, reset) {
113464             if (reset) {
113465               // reset all layers
113466               context.container().selectAll('.viewfield-group').classed('highlighted', false).classed('hovered', false).classed('currentView', false);
113467               context.container().selectAll('.sequence').classed('highlighted', false).classed('currentView', false);
113468             }
113469
113470             var hoveredImageKey = hovered && hovered.key;
113471             var hoveredSequenceKey = this.getSequenceKeyForImage(hovered);
113472             var hoveredSequence = hoveredSequenceKey && _oscCache.sequences[hoveredSequenceKey];
113473             var hoveredImageKeys = hoveredSequence && hoveredSequence.images.map(function (d) {
113474               return d.key;
113475             }) || [];
113476             var viewer = context.container().select('.photoviewer');
113477             var selected = viewer.empty() ? undefined : viewer.datum();
113478             var selectedImageKey = selected && selected.key;
113479             var selectedSequenceKey = this.getSequenceKeyForImage(selected);
113480             var selectedSequence = selectedSequenceKey && _oscCache.sequences[selectedSequenceKey];
113481             var selectedImageKeys = selectedSequence && selectedSequence.images.map(function (d) {
113482               return d.key;
113483             }) || []; // highlight sibling viewfields on either the selected or the hovered sequences
113484
113485             var highlightedImageKeys = utilArrayUnion(hoveredImageKeys, selectedImageKeys);
113486             context.container().selectAll('.layer-kartaview .viewfield-group').classed('highlighted', function (d) {
113487               return highlightedImageKeys.indexOf(d.key) !== -1;
113488             }).classed('hovered', function (d) {
113489               return d.key === hoveredImageKey;
113490             }).classed('currentView', function (d) {
113491               return d.key === selectedImageKey;
113492             });
113493             context.container().selectAll('.layer-kartaview .sequence').classed('highlighted', function (d) {
113494               return d.properties.key === hoveredSequenceKey;
113495             }).classed('currentView', function (d) {
113496               return d.properties.key === selectedSequenceKey;
113497             }); // update viewfields if needed
113498
113499             context.container().selectAll('.layer-kartaview .viewfield-group .viewfield').attr('d', viewfieldPath);
113500
113501             function viewfieldPath() {
113502               var d = this.parentNode.__data__;
113503
113504               if (d.pano && d.key !== selectedImageKey) {
113505                 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
113506               } else {
113507                 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
113508               }
113509             }
113510
113511             return this;
113512           },
113513           updateUrlImage: function updateUrlImage(imageKey) {
113514             if (!window.mocha) {
113515               var hash = utilStringQs(window.location.hash);
113516
113517               if (imageKey) {
113518                 hash.photo = 'kartaview/' + imageKey;
113519               } else {
113520                 delete hash.photo;
113521               }
113522
113523               window.location.replace('#' + utilQsString(hash, true));
113524             }
113525           },
113526           cache: function cache() {
113527             return _oscCache;
113528           }
113529         };
113530
113531         var hashes$1 = {exports: {}};
113532
113533         (function (module, exports) {
113534           (function () {
113535             var Hashes;
113536
113537             function utf8Encode(str) {
113538               var x,
113539                   y,
113540                   output = '',
113541                   i = -1,
113542                   l;
113543
113544               if (str && str.length) {
113545                 l = str.length;
113546
113547                 while ((i += 1) < l) {
113548                   /* Decode utf-16 surrogate pairs */
113549                   x = str.charCodeAt(i);
113550                   y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
113551
113552                   if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
113553                     x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
113554                     i += 1;
113555                   }
113556                   /* Encode output as utf-8 */
113557
113558
113559                   if (x <= 0x7F) {
113560                     output += String.fromCharCode(x);
113561                   } else if (x <= 0x7FF) {
113562                     output += String.fromCharCode(0xC0 | x >>> 6 & 0x1F, 0x80 | x & 0x3F);
113563                   } else if (x <= 0xFFFF) {
113564                     output += String.fromCharCode(0xE0 | x >>> 12 & 0x0F, 0x80 | x >>> 6 & 0x3F, 0x80 | x & 0x3F);
113565                   } else if (x <= 0x1FFFFF) {
113566                     output += String.fromCharCode(0xF0 | x >>> 18 & 0x07, 0x80 | x >>> 12 & 0x3F, 0x80 | x >>> 6 & 0x3F, 0x80 | x & 0x3F);
113567                   }
113568                 }
113569               }
113570
113571               return output;
113572             }
113573
113574             function utf8Decode(str) {
113575               var i,
113576                   ac,
113577                   c1,
113578                   c2,
113579                   c3,
113580                   arr = [],
113581                   l;
113582               i = ac = c1 = c2 = c3 = 0;
113583
113584               if (str && str.length) {
113585                 l = str.length;
113586                 str += '';
113587
113588                 while (i < l) {
113589                   c1 = str.charCodeAt(i);
113590                   ac += 1;
113591
113592                   if (c1 < 128) {
113593                     arr[ac] = String.fromCharCode(c1);
113594                     i += 1;
113595                   } else if (c1 > 191 && c1 < 224) {
113596                     c2 = str.charCodeAt(i + 1);
113597                     arr[ac] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
113598                     i += 2;
113599                   } else {
113600                     c2 = str.charCodeAt(i + 1);
113601                     c3 = str.charCodeAt(i + 2);
113602                     arr[ac] = String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
113603                     i += 3;
113604                   }
113605                 }
113606               }
113607
113608               return arr.join('');
113609             }
113610             /**
113611              * Add integers, wrapping at 2^32. This uses 16-bit operations internally
113612              * to work around bugs in some JS interpreters.
113613              */
113614
113615
113616             function safe_add(x, y) {
113617               var lsw = (x & 0xFFFF) + (y & 0xFFFF),
113618                   msw = (x >> 16) + (y >> 16) + (lsw >> 16);
113619               return msw << 16 | lsw & 0xFFFF;
113620             }
113621             /**
113622              * Bitwise rotate a 32-bit number to the left.
113623              */
113624
113625
113626             function bit_rol(num, cnt) {
113627               return num << cnt | num >>> 32 - cnt;
113628             }
113629             /**
113630              * Convert a raw string to a hex string
113631              */
113632
113633
113634             function rstr2hex(input, hexcase) {
113635               var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
113636                   output = '',
113637                   x,
113638                   i = 0,
113639                   l = input.length;
113640
113641               for (; i < l; i += 1) {
113642                 x = input.charCodeAt(i);
113643                 output += hex_tab.charAt(x >>> 4 & 0x0F) + hex_tab.charAt(x & 0x0F);
113644               }
113645
113646               return output;
113647             }
113648             /**
113649              * Convert an array of big-endian words to a string
113650              */
113651
113652
113653             function binb2rstr(input) {
113654               var i,
113655                   l = input.length * 32,
113656                   output = '';
113657
113658               for (i = 0; i < l; i += 8) {
113659                 output += String.fromCharCode(input[i >> 5] >>> 24 - i % 32 & 0xFF);
113660               }
113661
113662               return output;
113663             }
113664             /**
113665              * Convert an array of little-endian words to a string
113666              */
113667
113668
113669             function binl2rstr(input) {
113670               var i,
113671                   l = input.length * 32,
113672                   output = '';
113673
113674               for (i = 0; i < l; i += 8) {
113675                 output += String.fromCharCode(input[i >> 5] >>> i % 32 & 0xFF);
113676               }
113677
113678               return output;
113679             }
113680             /**
113681              * Convert a raw string to an array of little-endian words
113682              * Characters >255 have their high-byte silently ignored.
113683              */
113684
113685
113686             function rstr2binl(input) {
113687               var i,
113688                   l = input.length * 8,
113689                   output = Array(input.length >> 2),
113690                   lo = output.length;
113691
113692               for (i = 0; i < lo; i += 1) {
113693                 output[i] = 0;
113694               }
113695
113696               for (i = 0; i < l; i += 8) {
113697                 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << i % 32;
113698               }
113699
113700               return output;
113701             }
113702             /**
113703              * Convert a raw string to an array of big-endian words
113704              * Characters >255 have their high-byte silently ignored.
113705              */
113706
113707
113708             function rstr2binb(input) {
113709               var i,
113710                   l = input.length * 8,
113711                   output = Array(input.length >> 2),
113712                   lo = output.length;
113713
113714               for (i = 0; i < lo; i += 1) {
113715                 output[i] = 0;
113716               }
113717
113718               for (i = 0; i < l; i += 8) {
113719                 output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << 24 - i % 32;
113720               }
113721
113722               return output;
113723             }
113724             /**
113725              * Convert a raw string to an arbitrary string encoding
113726              */
113727
113728
113729             function rstr2any(input, encoding) {
113730               var divisor = encoding.length,
113731                   remainders = Array(),
113732                   i,
113733                   q,
113734                   x,
113735                   ld,
113736                   quotient,
113737                   dividend,
113738                   output,
113739                   full_length;
113740               /* Convert to an array of 16-bit big-endian values, forming the dividend */
113741
113742               dividend = Array(Math.ceil(input.length / 2));
113743               ld = dividend.length;
113744
113745               for (i = 0; i < ld; i += 1) {
113746                 dividend[i] = input.charCodeAt(i * 2) << 8 | input.charCodeAt(i * 2 + 1);
113747               }
113748               /**
113749                * Repeatedly perform a long division. The binary array forms the dividend,
113750                * the length of the encoding is the divisor. Once computed, the quotient
113751                * forms the dividend for the next step. We stop when the dividend is zerHashes.
113752                * All remainders are stored for later use.
113753                */
113754
113755
113756               while (dividend.length > 0) {
113757                 quotient = Array();
113758                 x = 0;
113759
113760                 for (i = 0; i < dividend.length; i += 1) {
113761                   x = (x << 16) + dividend[i];
113762                   q = Math.floor(x / divisor);
113763                   x -= q * divisor;
113764
113765                   if (quotient.length > 0 || q > 0) {
113766                     quotient[quotient.length] = q;
113767                   }
113768                 }
113769
113770                 remainders[remainders.length] = x;
113771                 dividend = quotient;
113772               }
113773               /* Convert the remainders to the output string */
113774
113775
113776               output = '';
113777
113778               for (i = remainders.length - 1; i >= 0; i--) {
113779                 output += encoding.charAt(remainders[i]);
113780               }
113781               /* Append leading zero equivalents */
113782
113783
113784               full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
113785
113786               for (i = output.length; i < full_length; i += 1) {
113787                 output = encoding[0] + output;
113788               }
113789
113790               return output;
113791             }
113792             /**
113793              * Convert a raw string to a base-64 string
113794              */
113795
113796
113797             function rstr2b64(input, b64pad) {
113798               var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
113799                   output = '',
113800                   len = input.length,
113801                   i,
113802                   j,
113803                   triplet;
113804               b64pad = b64pad || '=';
113805
113806               for (i = 0; i < len; i += 3) {
113807                 triplet = input.charCodeAt(i) << 16 | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
113808
113809                 for (j = 0; j < 4; j += 1) {
113810                   if (i * 8 + j * 6 > input.length * 8) {
113811                     output += b64pad;
113812                   } else {
113813                     output += tab.charAt(triplet >>> 6 * (3 - j) & 0x3F);
113814                   }
113815                 }
113816               }
113817
113818               return output;
113819             }
113820
113821             Hashes = {
113822               /**
113823                * @property {String} version
113824                * @readonly
113825                */
113826               VERSION: '1.0.6',
113827
113828               /**
113829                * @member Hashes
113830                * @class Base64
113831                * @constructor
113832                */
113833               Base64: function Base64() {
113834                 // private properties
113835                 var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
113836                     pad = '=',
113837                     // URL encoding support @todo
113838                 utf8 = true; // by default enable UTF-8 support encoding
113839                 // public method for encoding
113840
113841                 this.encode = function (input) {
113842                   var i,
113843                       j,
113844                       triplet,
113845                       output = '',
113846                       len = input.length;
113847                   pad = pad || '=';
113848                   input = utf8 ? utf8Encode(input) : input;
113849
113850                   for (i = 0; i < len; i += 3) {
113851                     triplet = input.charCodeAt(i) << 16 | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
113852
113853                     for (j = 0; j < 4; j += 1) {
113854                       if (i * 8 + j * 6 > len * 8) {
113855                         output += pad;
113856                       } else {
113857                         output += tab.charAt(triplet >>> 6 * (3 - j) & 0x3F);
113858                       }
113859                     }
113860                   }
113861
113862                   return output;
113863                 }; // public method for decoding
113864
113865
113866                 this.decode = function (input) {
113867                   // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
113868                   var i,
113869                       o1,
113870                       o2,
113871                       o3,
113872                       h1,
113873                       h2,
113874                       h3,
113875                       h4,
113876                       bits,
113877                       ac,
113878                       dec = '',
113879                       arr = [];
113880
113881                   if (!input) {
113882                     return input;
113883                   }
113884
113885                   i = ac = 0;
113886                   input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
113887                   //input += '';
113888
113889                   do {
113890                     // unpack four hexets into three octets using index points in b64
113891                     h1 = tab.indexOf(input.charAt(i += 1));
113892                     h2 = tab.indexOf(input.charAt(i += 1));
113893                     h3 = tab.indexOf(input.charAt(i += 1));
113894                     h4 = tab.indexOf(input.charAt(i += 1));
113895                     bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
113896                     o1 = bits >> 16 & 0xff;
113897                     o2 = bits >> 8 & 0xff;
113898                     o3 = bits & 0xff;
113899                     ac += 1;
113900
113901                     if (h3 === 64) {
113902                       arr[ac] = String.fromCharCode(o1);
113903                     } else if (h4 === 64) {
113904                       arr[ac] = String.fromCharCode(o1, o2);
113905                     } else {
113906                       arr[ac] = String.fromCharCode(o1, o2, o3);
113907                     }
113908                   } while (i < input.length);
113909
113910                   dec = arr.join('');
113911                   dec = utf8 ? utf8Decode(dec) : dec;
113912                   return dec;
113913                 }; // set custom pad string
113914
113915
113916                 this.setPad = function (str) {
113917                   pad = str || pad;
113918                   return this;
113919                 }; // set custom tab string characters
113920
113921
113922                 this.setTab = function (str) {
113923                   tab = str || tab;
113924                   return this;
113925                 };
113926
113927                 this.setUTF8 = function (bool) {
113928                   if (typeof bool === 'boolean') {
113929                     utf8 = bool;
113930                   }
113931
113932                   return this;
113933                 };
113934               },
113935
113936               /**
113937                * CRC-32 calculation
113938                * @member Hashes
113939                * @method CRC32
113940                * @static
113941                * @param {String} str Input String
113942                * @return {String}
113943                */
113944               CRC32: function CRC32(str) {
113945                 var crc = 0,
113946                     x = 0,
113947                     y = 0,
113948                     table,
113949                     i,
113950                     iTop;
113951                 str = utf8Encode(str);
113952                 table = ['00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ', '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ', '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ', '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ', 'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ', '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ', 'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ', '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ', 'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ', '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ', 'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ', '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ', 'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ', '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ', '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ', '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ', '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ', 'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ', '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ', 'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ', '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ', 'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ', '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ', 'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ', '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ', 'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'].join('');
113953                 crc = crc ^ -1;
113954
113955                 for (i = 0, iTop = str.length; i < iTop; i += 1) {
113956                   y = (crc ^ str.charCodeAt(i)) & 0xFF;
113957                   x = '0x' + table.substr(y * 9, 8);
113958                   crc = crc >>> 8 ^ x;
113959                 } // always return a positive number (that's what >>> 0 does)
113960
113961
113962                 return (crc ^ -1) >>> 0;
113963               },
113964
113965               /**
113966                * @member Hashes
113967                * @class MD5
113968                * @constructor
113969                * @param {Object} [config]
113970                *
113971                * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
113972                * Digest Algorithm, as defined in RFC 1321.
113973                * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
113974                * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
113975                * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
113976                */
113977               MD5: function MD5(options) {
113978                 /**
113979                  * Private config properties. You may need to tweak these to be compatible with
113980                  * the server-side, but the defaults work in most cases.
113981                  * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
113982                  */
113983                 var hexcase = options && typeof options.uppercase === 'boolean' ? options.uppercase : false,
113984                     // hexadecimal output case format. false - lowercase; true - uppercase
113985                 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
113986                     // base-64 pad character. Defaults to '=' for strict RFC compliance
113987                 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true; // enable/disable utf8 encoding
113988                 // privileged (public) methods
113989
113990                 this.hex = function (s) {
113991                   return rstr2hex(rstr(s), hexcase);
113992                 };
113993
113994                 this.b64 = function (s) {
113995                   return rstr2b64(rstr(s), b64pad);
113996                 };
113997
113998                 this.any = function (s, e) {
113999                   return rstr2any(rstr(s), e);
114000                 };
114001
114002                 this.raw = function (s) {
114003                   return rstr(s);
114004                 };
114005
114006                 this.hex_hmac = function (k, d) {
114007                   return rstr2hex(rstr_hmac(k, d), hexcase);
114008                 };
114009
114010                 this.b64_hmac = function (k, d) {
114011                   return rstr2b64(rstr_hmac(k, d), b64pad);
114012                 };
114013
114014                 this.any_hmac = function (k, d, e) {
114015                   return rstr2any(rstr_hmac(k, d), e);
114016                 };
114017                 /**
114018                  * Perform a simple self-test to see if the VM is working
114019                  * @return {String} Hexadecimal hash sample
114020                  */
114021
114022
114023                 this.vm_test = function () {
114024                   return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
114025                 };
114026                 /**
114027                  * Enable/disable uppercase hexadecimal returned string
114028                  * @param {Boolean}
114029                  * @return {Object} this
114030                  */
114031
114032
114033                 this.setUpperCase = function (a) {
114034                   if (typeof a === 'boolean') {
114035                     hexcase = a;
114036                   }
114037
114038                   return this;
114039                 };
114040                 /**
114041                  * Defines a base64 pad string
114042                  * @param {String} Pad
114043                  * @return {Object} this
114044                  */
114045
114046
114047                 this.setPad = function (a) {
114048                   b64pad = a || b64pad;
114049                   return this;
114050                 };
114051                 /**
114052                  * Defines a base64 pad string
114053                  * @param {Boolean}
114054                  * @return {Object} [this]
114055                  */
114056
114057
114058                 this.setUTF8 = function (a) {
114059                   if (typeof a === 'boolean') {
114060                     utf8 = a;
114061                   }
114062
114063                   return this;
114064                 }; // private methods
114065
114066                 /**
114067                  * Calculate the MD5 of a raw string
114068                  */
114069
114070
114071                 function rstr(s) {
114072                   s = utf8 ? utf8Encode(s) : s;
114073                   return binl2rstr(binl(rstr2binl(s), s.length * 8));
114074                 }
114075                 /**
114076                  * Calculate the HMAC-MD5, of a key and some data (raw strings)
114077                  */
114078
114079
114080                 function rstr_hmac(key, data) {
114081                   var bkey, ipad, opad, hash, i;
114082                   key = utf8 ? utf8Encode(key) : key;
114083                   data = utf8 ? utf8Encode(data) : data;
114084                   bkey = rstr2binl(key);
114085
114086                   if (bkey.length > 16) {
114087                     bkey = binl(bkey, key.length * 8);
114088                   }
114089
114090                   ipad = Array(16), opad = Array(16);
114091
114092                   for (i = 0; i < 16; i += 1) {
114093                     ipad[i] = bkey[i] ^ 0x36363636;
114094                     opad[i] = bkey[i] ^ 0x5C5C5C5C;
114095                   }
114096
114097                   hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
114098                   return binl2rstr(binl(opad.concat(hash), 512 + 128));
114099                 }
114100                 /**
114101                  * Calculate the MD5 of an array of little-endian words, and a bit length.
114102                  */
114103
114104
114105                 function binl(x, len) {
114106                   var i,
114107                       olda,
114108                       oldb,
114109                       oldc,
114110                       oldd,
114111                       a = 1732584193,
114112                       b = -271733879,
114113                       c = -1732584194,
114114                       d = 271733878;
114115                   /* append padding */
114116
114117                   x[len >> 5] |= 0x80 << len % 32;
114118                   x[(len + 64 >>> 9 << 4) + 14] = len;
114119
114120                   for (i = 0; i < x.length; i += 16) {
114121                     olda = a;
114122                     oldb = b;
114123                     oldc = c;
114124                     oldd = d;
114125                     a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
114126                     d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
114127                     c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
114128                     b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
114129                     a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
114130                     d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
114131                     c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
114132                     b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
114133                     a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
114134                     d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
114135                     c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
114136                     b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
114137                     a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
114138                     d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
114139                     c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
114140                     b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
114141                     a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
114142                     d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
114143                     c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
114144                     b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
114145                     a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
114146                     d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
114147                     c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
114148                     b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
114149                     a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
114150                     d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
114151                     c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
114152                     b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
114153                     a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
114154                     d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
114155                     c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
114156                     b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
114157                     a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
114158                     d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
114159                     c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
114160                     b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
114161                     a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
114162                     d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
114163                     c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
114164                     b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
114165                     a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
114166                     d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
114167                     c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
114168                     b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
114169                     a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
114170                     d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
114171                     c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
114172                     b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
114173                     a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
114174                     d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
114175                     c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
114176                     b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
114177                     a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
114178                     d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
114179                     c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
114180                     b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
114181                     a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
114182                     d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
114183                     c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
114184                     b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
114185                     a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
114186                     d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
114187                     c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
114188                     b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
114189                     a = safe_add(a, olda);
114190                     b = safe_add(b, oldb);
114191                     c = safe_add(c, oldc);
114192                     d = safe_add(d, oldd);
114193                   }
114194
114195                   return Array(a, b, c, d);
114196                 }
114197                 /**
114198                  * These functions implement the four basic operations the algorithm uses.
114199                  */
114200
114201
114202                 function md5_cmn(q, a, b, x, s, t) {
114203                   return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
114204                 }
114205
114206                 function md5_ff(a, b, c, d, x, s, t) {
114207                   return md5_cmn(b & c | ~b & d, a, b, x, s, t);
114208                 }
114209
114210                 function md5_gg(a, b, c, d, x, s, t) {
114211                   return md5_cmn(b & d | c & ~d, a, b, x, s, t);
114212                 }
114213
114214                 function md5_hh(a, b, c, d, x, s, t) {
114215                   return md5_cmn(b ^ c ^ d, a, b, x, s, t);
114216                 }
114217
114218                 function md5_ii(a, b, c, d, x, s, t) {
114219                   return md5_cmn(c ^ (b | ~d), a, b, x, s, t);
114220                 }
114221               },
114222
114223               /**
114224                * @member Hashes
114225                * @class Hashes.SHA1
114226                * @param {Object} [config]
114227                * @constructor
114228                *
114229                * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
114230                * Version 2.2 Copyright Paul Johnston 2000 - 2009.
114231                * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
114232                * See http://pajhome.org.uk/crypt/md5 for details.
114233                */
114234               SHA1: function SHA1(options) {
114235                 /**
114236                  * Private config properties. You may need to tweak these to be compatible with
114237                  * the server-side, but the defaults work in most cases.
114238                  * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
114239                  */
114240                 var hexcase = options && typeof options.uppercase === 'boolean' ? options.uppercase : false,
114241                     // hexadecimal output case format. false - lowercase; true - uppercase
114242                 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
114243                     // base-64 pad character. Defaults to '=' for strict RFC compliance
114244                 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true; // enable/disable utf8 encoding
114245                 // public methods
114246
114247                 this.hex = function (s) {
114248                   return rstr2hex(rstr(s), hexcase);
114249                 };
114250
114251                 this.b64 = function (s) {
114252                   return rstr2b64(rstr(s), b64pad);
114253                 };
114254
114255                 this.any = function (s, e) {
114256                   return rstr2any(rstr(s), e);
114257                 };
114258
114259                 this.raw = function (s) {
114260                   return rstr(s);
114261                 };
114262
114263                 this.hex_hmac = function (k, d) {
114264                   return rstr2hex(rstr_hmac(k, d));
114265                 };
114266
114267                 this.b64_hmac = function (k, d) {
114268                   return rstr2b64(rstr_hmac(k, d), b64pad);
114269                 };
114270
114271                 this.any_hmac = function (k, d, e) {
114272                   return rstr2any(rstr_hmac(k, d), e);
114273                 };
114274                 /**
114275                  * Perform a simple self-test to see if the VM is working
114276                  * @return {String} Hexadecimal hash sample
114277                  * @public
114278                  */
114279
114280
114281                 this.vm_test = function () {
114282                   return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
114283                 };
114284                 /**
114285                  * @description Enable/disable uppercase hexadecimal returned string
114286                  * @param {boolean}
114287                  * @return {Object} this
114288                  * @public
114289                  */
114290
114291
114292                 this.setUpperCase = function (a) {
114293                   if (typeof a === 'boolean') {
114294                     hexcase = a;
114295                   }
114296
114297                   return this;
114298                 };
114299                 /**
114300                  * @description Defines a base64 pad string
114301                  * @param {string} Pad
114302                  * @return {Object} this
114303                  * @public
114304                  */
114305
114306
114307                 this.setPad = function (a) {
114308                   b64pad = a || b64pad;
114309                   return this;
114310                 };
114311                 /**
114312                  * @description Defines a base64 pad string
114313                  * @param {boolean}
114314                  * @return {Object} this
114315                  * @public
114316                  */
114317
114318
114319                 this.setUTF8 = function (a) {
114320                   if (typeof a === 'boolean') {
114321                     utf8 = a;
114322                   }
114323
114324                   return this;
114325                 }; // private methods
114326
114327                 /**
114328                  * Calculate the SHA-512 of a raw string
114329                  */
114330
114331
114332                 function rstr(s) {
114333                   s = utf8 ? utf8Encode(s) : s;
114334                   return binb2rstr(binb(rstr2binb(s), s.length * 8));
114335                 }
114336                 /**
114337                  * Calculate the HMAC-SHA1 of a key and some data (raw strings)
114338                  */
114339
114340
114341                 function rstr_hmac(key, data) {
114342                   var bkey, ipad, opad, i, hash;
114343                   key = utf8 ? utf8Encode(key) : key;
114344                   data = utf8 ? utf8Encode(data) : data;
114345                   bkey = rstr2binb(key);
114346
114347                   if (bkey.length > 16) {
114348                     bkey = binb(bkey, key.length * 8);
114349                   }
114350
114351                   ipad = Array(16), opad = Array(16);
114352
114353                   for (i = 0; i < 16; i += 1) {
114354                     ipad[i] = bkey[i] ^ 0x36363636;
114355                     opad[i] = bkey[i] ^ 0x5C5C5C5C;
114356                   }
114357
114358                   hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
114359                   return binb2rstr(binb(opad.concat(hash), 512 + 160));
114360                 }
114361                 /**
114362                  * Calculate the SHA-1 of an array of big-endian words, and a bit length
114363                  */
114364
114365
114366                 function binb(x, len) {
114367                   var i,
114368                       j,
114369                       t,
114370                       olda,
114371                       oldb,
114372                       oldc,
114373                       oldd,
114374                       olde,
114375                       w = Array(80),
114376                       a = 1732584193,
114377                       b = -271733879,
114378                       c = -1732584194,
114379                       d = 271733878,
114380                       e = -1009589776;
114381                   /* append padding */
114382
114383                   x[len >> 5] |= 0x80 << 24 - len % 32;
114384                   x[(len + 64 >> 9 << 4) + 15] = len;
114385
114386                   for (i = 0; i < x.length; i += 16) {
114387                     olda = a;
114388                     oldb = b;
114389                     oldc = c;
114390                     oldd = d;
114391                     olde = e;
114392
114393                     for (j = 0; j < 80; j += 1) {
114394                       if (j < 16) {
114395                         w[j] = x[i + j];
114396                       } else {
114397                         w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
114398                       }
114399
114400                       t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j)));
114401                       e = d;
114402                       d = c;
114403                       c = bit_rol(b, 30);
114404                       b = a;
114405                       a = t;
114406                     }
114407
114408                     a = safe_add(a, olda);
114409                     b = safe_add(b, oldb);
114410                     c = safe_add(c, oldc);
114411                     d = safe_add(d, oldd);
114412                     e = safe_add(e, olde);
114413                   }
114414
114415                   return Array(a, b, c, d, e);
114416                 }
114417                 /**
114418                  * Perform the appropriate triplet combination function for the current
114419                  * iteration
114420                  */
114421
114422
114423                 function sha1_ft(t, b, c, d) {
114424                   if (t < 20) {
114425                     return b & c | ~b & d;
114426                   }
114427
114428                   if (t < 40) {
114429                     return b ^ c ^ d;
114430                   }
114431
114432                   if (t < 60) {
114433                     return b & c | b & d | c & d;
114434                   }
114435
114436                   return b ^ c ^ d;
114437                 }
114438                 /**
114439                  * Determine the appropriate additive constant for the current iteration
114440                  */
114441
114442
114443                 function sha1_kt(t) {
114444                   return t < 20 ? 1518500249 : t < 40 ? 1859775393 : t < 60 ? -1894007588 : -899497514;
114445                 }
114446               },
114447
114448               /**
114449                * @class Hashes.SHA256
114450                * @param {config}
114451                *
114452                * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
114453                * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
114454                * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
114455                * See http://pajhome.org.uk/crypt/md5 for details.
114456                * Also http://anmar.eu.org/projects/jssha2/
114457                */
114458               SHA256: function SHA256(options) {
114459                 /**
114460                  * Private properties configuration variables. You may need to tweak these to be compatible with
114461                  * the server-side, but the defaults work in most cases.
114462                  * @see this.setUpperCase() method
114463                  * @see this.setPad() method
114464                  */
114465                 options && typeof options.uppercase === 'boolean' ? options.uppercase : false;
114466                     var // hexadecimal output case format. false - lowercase; true - uppercase  */
114467                 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
114468
114469                 /* base-64 pad character. Default '=' for strict RFC compliance   */
114470                 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true,
114471
114472                 /* enable/disable utf8 encoding */
114473                 sha256_K;
114474                 /* privileged (public) methods */
114475
114476                 this.hex = function (s) {
114477                   return rstr2hex(rstr(s, utf8));
114478                 };
114479
114480                 this.b64 = function (s) {
114481                   return rstr2b64(rstr(s, utf8), b64pad);
114482                 };
114483
114484                 this.any = function (s, e) {
114485                   return rstr2any(rstr(s, utf8), e);
114486                 };
114487
114488                 this.raw = function (s) {
114489                   return rstr(s, utf8);
114490                 };
114491
114492                 this.hex_hmac = function (k, d) {
114493                   return rstr2hex(rstr_hmac(k, d));
114494                 };
114495
114496                 this.b64_hmac = function (k, d) {
114497                   return rstr2b64(rstr_hmac(k, d), b64pad);
114498                 };
114499
114500                 this.any_hmac = function (k, d, e) {
114501                   return rstr2any(rstr_hmac(k, d), e);
114502                 };
114503                 /**
114504                  * Perform a simple self-test to see if the VM is working
114505                  * @return {String} Hexadecimal hash sample
114506                  * @public
114507                  */
114508
114509
114510                 this.vm_test = function () {
114511                   return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
114512                 };
114513                 /**
114514                  * Enable/disable uppercase hexadecimal returned string
114515                  * @param {boolean}
114516                  * @return {Object} this
114517                  * @public
114518                  */
114519
114520
114521                 this.setUpperCase = function (a) {
114522
114523                   return this;
114524                 };
114525                 /**
114526                  * @description Defines a base64 pad string
114527                  * @param {string} Pad
114528                  * @return {Object} this
114529                  * @public
114530                  */
114531
114532
114533                 this.setPad = function (a) {
114534                   b64pad = a || b64pad;
114535                   return this;
114536                 };
114537                 /**
114538                  * Defines a base64 pad string
114539                  * @param {boolean}
114540                  * @return {Object} this
114541                  * @public
114542                  */
114543
114544
114545                 this.setUTF8 = function (a) {
114546                   if (typeof a === 'boolean') {
114547                     utf8 = a;
114548                   }
114549
114550                   return this;
114551                 }; // private methods
114552
114553                 /**
114554                  * Calculate the SHA-512 of a raw string
114555                  */
114556
114557
114558                 function rstr(s, utf8) {
114559                   s = utf8 ? utf8Encode(s) : s;
114560                   return binb2rstr(binb(rstr2binb(s), s.length * 8));
114561                 }
114562                 /**
114563                  * Calculate the HMAC-sha256 of a key and some data (raw strings)
114564                  */
114565
114566
114567                 function rstr_hmac(key, data) {
114568                   key = utf8 ? utf8Encode(key) : key;
114569                   data = utf8 ? utf8Encode(data) : data;
114570                   var hash,
114571                       i = 0,
114572                       bkey = rstr2binb(key),
114573                       ipad = Array(16),
114574                       opad = Array(16);
114575
114576                   if (bkey.length > 16) {
114577                     bkey = binb(bkey, key.length * 8);
114578                   }
114579
114580                   for (; i < 16; i += 1) {
114581                     ipad[i] = bkey[i] ^ 0x36363636;
114582                     opad[i] = bkey[i] ^ 0x5C5C5C5C;
114583                   }
114584
114585                   hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
114586                   return binb2rstr(binb(opad.concat(hash), 512 + 256));
114587                 }
114588                 /*
114589                  * Main sha256 function, with its support functions
114590                  */
114591
114592
114593                 function sha256_S(X, n) {
114594                   return X >>> n | X << 32 - n;
114595                 }
114596
114597                 function sha256_R(X, n) {
114598                   return X >>> n;
114599                 }
114600
114601                 function sha256_Ch(x, y, z) {
114602                   return x & y ^ ~x & z;
114603                 }
114604
114605                 function sha256_Maj(x, y, z) {
114606                   return x & y ^ x & z ^ y & z;
114607                 }
114608
114609                 function sha256_Sigma0256(x) {
114610                   return sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22);
114611                 }
114612
114613                 function sha256_Sigma1256(x) {
114614                   return sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25);
114615                 }
114616
114617                 function sha256_Gamma0256(x) {
114618                   return sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3);
114619                 }
114620
114621                 function sha256_Gamma1256(x) {
114622                   return sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10);
114623                 }
114624
114625                 sha256_K = [1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998];
114626
114627                 function binb(m, l) {
114628                   var HASH = [1779033703, -1150833019, 1013904242, -1521486534, 1359893119, -1694144372, 528734635, 1541459225];
114629                   var W = new Array(64);
114630                   var a, b, c, d, e, f, g, h;
114631                   var i, j, T1, T2;
114632                   /* append padding */
114633
114634                   m[l >> 5] |= 0x80 << 24 - l % 32;
114635                   m[(l + 64 >> 9 << 4) + 15] = l;
114636
114637                   for (i = 0; i < m.length; i += 16) {
114638                     a = HASH[0];
114639                     b = HASH[1];
114640                     c = HASH[2];
114641                     d = HASH[3];
114642                     e = HASH[4];
114643                     f = HASH[5];
114644                     g = HASH[6];
114645                     h = HASH[7];
114646
114647                     for (j = 0; j < 64; j += 1) {
114648                       if (j < 16) {
114649                         W[j] = m[j + i];
114650                       } else {
114651                         W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]), sha256_Gamma0256(W[j - 15])), W[j - 16]);
114652                       }
114653
114654                       T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)), sha256_K[j]), W[j]);
114655                       T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
114656                       h = g;
114657                       g = f;
114658                       f = e;
114659                       e = safe_add(d, T1);
114660                       d = c;
114661                       c = b;
114662                       b = a;
114663                       a = safe_add(T1, T2);
114664                     }
114665
114666                     HASH[0] = safe_add(a, HASH[0]);
114667                     HASH[1] = safe_add(b, HASH[1]);
114668                     HASH[2] = safe_add(c, HASH[2]);
114669                     HASH[3] = safe_add(d, HASH[3]);
114670                     HASH[4] = safe_add(e, HASH[4]);
114671                     HASH[5] = safe_add(f, HASH[5]);
114672                     HASH[6] = safe_add(g, HASH[6]);
114673                     HASH[7] = safe_add(h, HASH[7]);
114674                   }
114675
114676                   return HASH;
114677                 }
114678               },
114679
114680               /**
114681                * @class Hashes.SHA512
114682                * @param {config}
114683                *
114684                * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
114685                * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
114686                * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
114687                * See http://pajhome.org.uk/crypt/md5 for details.
114688                */
114689               SHA512: function SHA512(options) {
114690                 /**
114691                  * Private properties configuration variables. You may need to tweak these to be compatible with
114692                  * the server-side, but the defaults work in most cases.
114693                  * @see this.setUpperCase() method
114694                  * @see this.setPad() method
114695                  */
114696                 options && typeof options.uppercase === 'boolean' ? options.uppercase : false;
114697
114698                 var /* hexadecimal output case format. false - lowercase; true - uppercase  */
114699                 b64pad = options && typeof options.pad === 'string' ? options.pad : '=',
114700
114701                 /* base-64 pad character. Default '=' for strict RFC compliance   */
114702                 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true,
114703
114704                 /* enable/disable utf8 encoding */
114705                 sha512_k;
114706                 /* privileged (public) methods */
114707
114708                 this.hex = function (s) {
114709                   return rstr2hex(rstr(s));
114710                 };
114711
114712                 this.b64 = function (s) {
114713                   return rstr2b64(rstr(s), b64pad);
114714                 };
114715
114716                 this.any = function (s, e) {
114717                   return rstr2any(rstr(s), e);
114718                 };
114719
114720                 this.raw = function (s) {
114721                   return rstr(s);
114722                 };
114723
114724                 this.hex_hmac = function (k, d) {
114725                   return rstr2hex(rstr_hmac(k, d));
114726                 };
114727
114728                 this.b64_hmac = function (k, d) {
114729                   return rstr2b64(rstr_hmac(k, d), b64pad);
114730                 };
114731
114732                 this.any_hmac = function (k, d, e) {
114733                   return rstr2any(rstr_hmac(k, d), e);
114734                 };
114735                 /**
114736                  * Perform a simple self-test to see if the VM is working
114737                  * @return {String} Hexadecimal hash sample
114738                  * @public
114739                  */
114740
114741
114742                 this.vm_test = function () {
114743                   return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
114744                 };
114745                 /**
114746                  * @description Enable/disable uppercase hexadecimal returned string
114747                  * @param {boolean}
114748                  * @return {Object} this
114749                  * @public
114750                  */
114751
114752
114753                 this.setUpperCase = function (a) {
114754
114755                   return this;
114756                 };
114757                 /**
114758                  * @description Defines a base64 pad string
114759                  * @param {string} Pad
114760                  * @return {Object} this
114761                  * @public
114762                  */
114763
114764
114765                 this.setPad = function (a) {
114766                   b64pad = a || b64pad;
114767                   return this;
114768                 };
114769                 /**
114770                  * @description Defines a base64 pad string
114771                  * @param {boolean}
114772                  * @return {Object} this
114773                  * @public
114774                  */
114775
114776
114777                 this.setUTF8 = function (a) {
114778                   if (typeof a === 'boolean') {
114779                     utf8 = a;
114780                   }
114781
114782                   return this;
114783                 };
114784                 /* private methods */
114785
114786                 /**
114787                  * Calculate the SHA-512 of a raw string
114788                  */
114789
114790
114791                 function rstr(s) {
114792                   s = utf8 ? utf8Encode(s) : s;
114793                   return binb2rstr(binb(rstr2binb(s), s.length * 8));
114794                 }
114795                 /*
114796                  * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
114797                  */
114798
114799
114800                 function rstr_hmac(key, data) {
114801                   key = utf8 ? utf8Encode(key) : key;
114802                   data = utf8 ? utf8Encode(data) : data;
114803                   var hash,
114804                       i = 0,
114805                       bkey = rstr2binb(key),
114806                       ipad = Array(32),
114807                       opad = Array(32);
114808
114809                   if (bkey.length > 32) {
114810                     bkey = binb(bkey, key.length * 8);
114811                   }
114812
114813                   for (; i < 32; i += 1) {
114814                     ipad[i] = bkey[i] ^ 0x36363636;
114815                     opad[i] = bkey[i] ^ 0x5C5C5C5C;
114816                   }
114817
114818                   hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
114819                   return binb2rstr(binb(opad.concat(hash), 1024 + 512));
114820                 }
114821                 /**
114822                  * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
114823                  */
114824
114825
114826                 function binb(x, len) {
114827                   var j,
114828                       i,
114829                       l,
114830                       W = new Array(80),
114831                       hash = new Array(16),
114832                       //Initial hash values
114833                   H = [new int64(0x6a09e667, -205731576), new int64(-1150833019, -2067093701), new int64(0x3c6ef372, -23791573), new int64(-1521486534, 0x5f1d36f1), new int64(0x510e527f, -1377402159), new int64(-1694144372, 0x2b3e6c1f), new int64(0x1f83d9ab, -79577749), new int64(0x5be0cd19, 0x137e2179)],
114834                       T1 = new int64(0, 0),
114835                       T2 = new int64(0, 0),
114836                       a = new int64(0, 0),
114837                       b = new int64(0, 0),
114838                       c = new int64(0, 0),
114839                       d = new int64(0, 0),
114840                       e = new int64(0, 0),
114841                       f = new int64(0, 0),
114842                       g = new int64(0, 0),
114843                       h = new int64(0, 0),
114844                       //Temporary variables not specified by the document
114845                   s0 = new int64(0, 0),
114846                       s1 = new int64(0, 0),
114847                       Ch = new int64(0, 0),
114848                       Maj = new int64(0, 0),
114849                       r1 = new int64(0, 0),
114850                       r2 = new int64(0, 0),
114851                       r3 = new int64(0, 0);
114852
114853                   if (sha512_k === undefined) {
114854                     //SHA512 constants
114855                     sha512_k = [new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd), new int64(-1245643825, -330482897), new int64(-373957723, -2121671748), new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031), new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736), new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe), new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302), new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1), new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428), new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3), new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65), new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483), new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459), new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210), new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340), new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395), new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70), new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926), new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473), new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8), new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b), new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023), new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30), new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910), new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8), new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53), new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016), new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893), new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397), new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60), new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec), new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047), new int64(-1090935817, -1295615723), new int64(-965641998, -479046869), new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207), new int64(-354779690, -840897762), new int64(-176337025, -294727304), new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026), new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b), new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493), new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620), new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430), new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)];
114856                   }
114857
114858                   for (i = 0; i < 80; i += 1) {
114859                     W[i] = new int64(0, 0);
114860                   } // append padding to the source string. The format is described in the FIPS.
114861
114862
114863                   x[len >> 5] |= 0x80 << 24 - (len & 0x1f);
114864                   x[(len + 128 >> 10 << 5) + 31] = len;
114865                   l = x.length;
114866
114867                   for (i = 0; i < l; i += 32) {
114868                     //32 dwords is the block size
114869                     int64copy(a, H[0]);
114870                     int64copy(b, H[1]);
114871                     int64copy(c, H[2]);
114872                     int64copy(d, H[3]);
114873                     int64copy(e, H[4]);
114874                     int64copy(f, H[5]);
114875                     int64copy(g, H[6]);
114876                     int64copy(h, H[7]);
114877
114878                     for (j = 0; j < 16; j += 1) {
114879                       W[j].h = x[i + 2 * j];
114880                       W[j].l = x[i + 2 * j + 1];
114881                     }
114882
114883                     for (j = 16; j < 80; j += 1) {
114884                       //sigma1
114885                       int64rrot(r1, W[j - 2], 19);
114886                       int64revrrot(r2, W[j - 2], 29);
114887                       int64shr(r3, W[j - 2], 6);
114888                       s1.l = r1.l ^ r2.l ^ r3.l;
114889                       s1.h = r1.h ^ r2.h ^ r3.h; //sigma0
114890
114891                       int64rrot(r1, W[j - 15], 1);
114892                       int64rrot(r2, W[j - 15], 8);
114893                       int64shr(r3, W[j - 15], 7);
114894                       s0.l = r1.l ^ r2.l ^ r3.l;
114895                       s0.h = r1.h ^ r2.h ^ r3.h;
114896                       int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
114897                     }
114898
114899                     for (j = 0; j < 80; j += 1) {
114900                       //Ch
114901                       Ch.l = e.l & f.l ^ ~e.l & g.l;
114902                       Ch.h = e.h & f.h ^ ~e.h & g.h; //Sigma1
114903
114904                       int64rrot(r1, e, 14);
114905                       int64rrot(r2, e, 18);
114906                       int64revrrot(r3, e, 9);
114907                       s1.l = r1.l ^ r2.l ^ r3.l;
114908                       s1.h = r1.h ^ r2.h ^ r3.h; //Sigma0
114909
114910                       int64rrot(r1, a, 28);
114911                       int64revrrot(r2, a, 2);
114912                       int64revrrot(r3, a, 7);
114913                       s0.l = r1.l ^ r2.l ^ r3.l;
114914                       s0.h = r1.h ^ r2.h ^ r3.h; //Maj
114915
114916                       Maj.l = a.l & b.l ^ a.l & c.l ^ b.l & c.l;
114917                       Maj.h = a.h & b.h ^ a.h & c.h ^ b.h & c.h;
114918                       int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
114919                       int64add(T2, s0, Maj);
114920                       int64copy(h, g);
114921                       int64copy(g, f);
114922                       int64copy(f, e);
114923                       int64add(e, d, T1);
114924                       int64copy(d, c);
114925                       int64copy(c, b);
114926                       int64copy(b, a);
114927                       int64add(a, T1, T2);
114928                     }
114929
114930                     int64add(H[0], H[0], a);
114931                     int64add(H[1], H[1], b);
114932                     int64add(H[2], H[2], c);
114933                     int64add(H[3], H[3], d);
114934                     int64add(H[4], H[4], e);
114935                     int64add(H[5], H[5], f);
114936                     int64add(H[6], H[6], g);
114937                     int64add(H[7], H[7], h);
114938                   } //represent the hash as an array of 32-bit dwords
114939
114940
114941                   for (i = 0; i < 8; i += 1) {
114942                     hash[2 * i] = H[i].h;
114943                     hash[2 * i + 1] = H[i].l;
114944                   }
114945
114946                   return hash;
114947                 } //A constructor for 64-bit numbers
114948
114949
114950                 function int64(h, l) {
114951                   this.h = h;
114952                   this.l = l; //this.toString = int64toString;
114953                 } //Copies src into dst, assuming both are 64-bit numbers
114954
114955
114956                 function int64copy(dst, src) {
114957                   dst.h = src.h;
114958                   dst.l = src.l;
114959                 } //Right-rotates a 64-bit number by shift
114960                 //Won't handle cases of shift>=32
114961                 //The function revrrot() is for that
114962
114963
114964                 function int64rrot(dst, x, shift) {
114965                   dst.l = x.l >>> shift | x.h << 32 - shift;
114966                   dst.h = x.h >>> shift | x.l << 32 - shift;
114967                 } //Reverses the dwords of the source and then rotates right by shift.
114968                 //This is equivalent to rotation by 32+shift
114969
114970
114971                 function int64revrrot(dst, x, shift) {
114972                   dst.l = x.h >>> shift | x.l << 32 - shift;
114973                   dst.h = x.l >>> shift | x.h << 32 - shift;
114974                 } //Bitwise-shifts right a 64-bit number by shift
114975                 //Won't handle shift>=32, but it's never needed in SHA512
114976
114977
114978                 function int64shr(dst, x, shift) {
114979                   dst.l = x.l >>> shift | x.h << 32 - shift;
114980                   dst.h = x.h >>> shift;
114981                 } //Adds two 64-bit numbers
114982                 //Like the original implementation, does not rely on 32-bit operations
114983
114984
114985                 function int64add(dst, x, y) {
114986                   var w0 = (x.l & 0xffff) + (y.l & 0xffff);
114987                   var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
114988                   var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
114989                   var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
114990                   dst.l = w0 & 0xffff | w1 << 16;
114991                   dst.h = w2 & 0xffff | w3 << 16;
114992                 } //Same, except with 4 addends. Works faster than adding them one by one.
114993
114994
114995                 function int64add4(dst, a, b, c, d) {
114996                   var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
114997                   var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
114998                   var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
114999                   var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
115000                   dst.l = w0 & 0xffff | w1 << 16;
115001                   dst.h = w2 & 0xffff | w3 << 16;
115002                 } //Same, except with 5 addends
115003
115004
115005                 function int64add5(dst, a, b, c, d, e) {
115006                   var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
115007                       w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
115008                       w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
115009                       w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
115010                   dst.l = w0 & 0xffff | w1 << 16;
115011                   dst.h = w2 & 0xffff | w3 << 16;
115012                 }
115013               },
115014
115015               /**
115016                * @class Hashes.RMD160
115017                * @constructor
115018                * @param {Object} [config]
115019                *
115020                * A JavaScript implementation of the RIPEMD-160 Algorithm
115021                * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
115022                * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
115023                * See http://pajhome.org.uk/crypt/md5 for details.
115024                * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
115025                */
115026               RMD160: function RMD160(options) {
115027                 /**
115028                  * Private properties configuration variables. You may need to tweak these to be compatible with
115029                  * the server-side, but the defaults work in most cases.
115030                  * @see this.setUpperCase() method
115031                  * @see this.setPad() method
115032                  */
115033                 options && typeof options.uppercase === 'boolean' ? options.uppercase : false;
115034
115035                 var /* hexadecimal output case format. false - lowercase; true - uppercase  */
115036                 b64pad = options && typeof options.pad === 'string' ? options.pa : '=',
115037
115038                 /* base-64 pad character. Default '=' for strict RFC compliance   */
115039                 utf8 = options && typeof options.utf8 === 'boolean' ? options.utf8 : true,
115040
115041                 /* enable/disable utf8 encoding */
115042                 rmd160_r1 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13],
115043                     rmd160_r2 = [5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11],
115044                     rmd160_s1 = [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6],
115045                     rmd160_s2 = [8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11];
115046                 /* privileged (public) methods */
115047
115048                 this.hex = function (s) {
115049                   return rstr2hex(rstr(s));
115050                 };
115051
115052                 this.b64 = function (s) {
115053                   return rstr2b64(rstr(s), b64pad);
115054                 };
115055
115056                 this.any = function (s, e) {
115057                   return rstr2any(rstr(s), e);
115058                 };
115059
115060                 this.raw = function (s) {
115061                   return rstr(s);
115062                 };
115063
115064                 this.hex_hmac = function (k, d) {
115065                   return rstr2hex(rstr_hmac(k, d));
115066                 };
115067
115068                 this.b64_hmac = function (k, d) {
115069                   return rstr2b64(rstr_hmac(k, d), b64pad);
115070                 };
115071
115072                 this.any_hmac = function (k, d, e) {
115073                   return rstr2any(rstr_hmac(k, d), e);
115074                 };
115075                 /**
115076                  * Perform a simple self-test to see if the VM is working
115077                  * @return {String} Hexadecimal hash sample
115078                  * @public
115079                  */
115080
115081
115082                 this.vm_test = function () {
115083                   return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
115084                 };
115085                 /**
115086                  * @description Enable/disable uppercase hexadecimal returned string
115087                  * @param {boolean}
115088                  * @return {Object} this
115089                  * @public
115090                  */
115091
115092
115093                 this.setUpperCase = function (a) {
115094
115095                   return this;
115096                 };
115097                 /**
115098                  * @description Defines a base64 pad string
115099                  * @param {string} Pad
115100                  * @return {Object} this
115101                  * @public
115102                  */
115103
115104
115105                 this.setPad = function (a) {
115106                   if (typeof a !== 'undefined') {
115107                     b64pad = a;
115108                   }
115109
115110                   return this;
115111                 };
115112                 /**
115113                  * @description Defines a base64 pad string
115114                  * @param {boolean}
115115                  * @return {Object} this
115116                  * @public
115117                  */
115118
115119
115120                 this.setUTF8 = function (a) {
115121                   if (typeof a === 'boolean') {
115122                     utf8 = a;
115123                   }
115124
115125                   return this;
115126                 };
115127                 /* private methods */
115128
115129                 /**
115130                  * Calculate the rmd160 of a raw string
115131                  */
115132
115133
115134                 function rstr(s) {
115135                   s = utf8 ? utf8Encode(s) : s;
115136                   return binl2rstr(binl(rstr2binl(s), s.length * 8));
115137                 }
115138                 /**
115139                  * Calculate the HMAC-rmd160 of a key and some data (raw strings)
115140                  */
115141
115142
115143                 function rstr_hmac(key, data) {
115144                   key = utf8 ? utf8Encode(key) : key;
115145                   data = utf8 ? utf8Encode(data) : data;
115146                   var i,
115147                       hash,
115148                       bkey = rstr2binl(key),
115149                       ipad = Array(16),
115150                       opad = Array(16);
115151
115152                   if (bkey.length > 16) {
115153                     bkey = binl(bkey, key.length * 8);
115154                   }
115155
115156                   for (i = 0; i < 16; i += 1) {
115157                     ipad[i] = bkey[i] ^ 0x36363636;
115158                     opad[i] = bkey[i] ^ 0x5C5C5C5C;
115159                   }
115160
115161                   hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
115162                   return binl2rstr(binl(opad.concat(hash), 512 + 160));
115163                 }
115164                 /**
115165                  * Convert an array of little-endian words to a string
115166                  */
115167
115168
115169                 function binl2rstr(input) {
115170                   var i,
115171                       output = '',
115172                       l = input.length * 32;
115173
115174                   for (i = 0; i < l; i += 8) {
115175                     output += String.fromCharCode(input[i >> 5] >>> i % 32 & 0xFF);
115176                   }
115177
115178                   return output;
115179                 }
115180                 /**
115181                  * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
115182                  */
115183
115184
115185                 function binl(x, len) {
115186                   var T,
115187                       j,
115188                       i,
115189                       l,
115190                       h0 = 0x67452301,
115191                       h1 = 0xefcdab89,
115192                       h2 = 0x98badcfe,
115193                       h3 = 0x10325476,
115194                       h4 = 0xc3d2e1f0,
115195                       A1,
115196                       B1,
115197                       C1,
115198                       D1,
115199                       E1,
115200                       A2,
115201                       B2,
115202                       C2,
115203                       D2,
115204                       E2;
115205                   /* append padding */
115206
115207                   x[len >> 5] |= 0x80 << len % 32;
115208                   x[(len + 64 >>> 9 << 4) + 14] = len;
115209                   l = x.length;
115210
115211                   for (i = 0; i < l; i += 16) {
115212                     A1 = A2 = h0;
115213                     B1 = B2 = h1;
115214                     C1 = C2 = h2;
115215                     D1 = D2 = h3;
115216                     E1 = E2 = h4;
115217
115218                     for (j = 0; j <= 79; j += 1) {
115219                       T = safe_add(A1, rmd160_f(j, B1, C1, D1));
115220                       T = safe_add(T, x[i + rmd160_r1[j]]);
115221                       T = safe_add(T, rmd160_K1(j));
115222                       T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
115223                       A1 = E1;
115224                       E1 = D1;
115225                       D1 = bit_rol(C1, 10);
115226                       C1 = B1;
115227                       B1 = T;
115228                       T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
115229                       T = safe_add(T, x[i + rmd160_r2[j]]);
115230                       T = safe_add(T, rmd160_K2(j));
115231                       T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
115232                       A2 = E2;
115233                       E2 = D2;
115234                       D2 = bit_rol(C2, 10);
115235                       C2 = B2;
115236                       B2 = T;
115237                     }
115238
115239                     T = safe_add(h1, safe_add(C1, D2));
115240                     h1 = safe_add(h2, safe_add(D1, E2));
115241                     h2 = safe_add(h3, safe_add(E1, A2));
115242                     h3 = safe_add(h4, safe_add(A1, B2));
115243                     h4 = safe_add(h0, safe_add(B1, C2));
115244                     h0 = T;
115245                   }
115246
115247                   return [h0, h1, h2, h3, h4];
115248                 } // specific algorithm methods
115249
115250
115251                 function rmd160_f(j, x, y, z) {
115252                   return 0 <= j && j <= 15 ? x ^ y ^ z : 16 <= j && j <= 31 ? x & y | ~x & z : 32 <= j && j <= 47 ? (x | ~y) ^ z : 48 <= j && j <= 63 ? x & z | y & ~z : 64 <= j && j <= 79 ? x ^ (y | ~z) : 'rmd160_f: j out of range';
115253                 }
115254
115255                 function rmd160_K1(j) {
115256                   return 0 <= j && j <= 15 ? 0x00000000 : 16 <= j && j <= 31 ? 0x5a827999 : 32 <= j && j <= 47 ? 0x6ed9eba1 : 48 <= j && j <= 63 ? 0x8f1bbcdc : 64 <= j && j <= 79 ? 0xa953fd4e : 'rmd160_K1: j out of range';
115257                 }
115258
115259                 function rmd160_K2(j) {
115260                   return 0 <= j && j <= 15 ? 0x50a28be6 : 16 <= j && j <= 31 ? 0x5c4dd124 : 32 <= j && j <= 47 ? 0x6d703ef3 : 48 <= j && j <= 63 ? 0x7a6d76e9 : 64 <= j && j <= 79 ? 0x00000000 : 'rmd160_K2: j out of range';
115261                 }
115262               }
115263             }; // exposes Hashes
115264
115265             (function (window, undefined$1) {
115266               var freeExports = false;
115267
115268               {
115269                 freeExports = exports;
115270
115271                 if (exports && _typeof(commonjsGlobal) === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
115272                   window = commonjsGlobal;
115273                 }
115274               }
115275
115276               if (typeof undefined$1 === 'function' && _typeof(undefined$1.amd) === 'object' && undefined$1.amd) {
115277                 // define as an anonymous module, so, through path mapping, it can be aliased
115278                 undefined$1(function () {
115279                   return Hashes;
115280                 });
115281               } else if (freeExports) {
115282                 // in Node.js or RingoJS v0.8.0+
115283                 if (module && module.exports === freeExports) {
115284                   module.exports = Hashes;
115285                 } // in Narwhal or RingoJS v0.7.0-
115286                 else {
115287                   freeExports.Hashes = Hashes;
115288                 }
115289               } else {
115290                 // in a browser or Rhino
115291                 window.Hashes = Hashes;
115292               }
115293             })(this);
115294           })(); // IIFE
115295
115296         })(hashes$1, hashes$1.exports);
115297
115298         var hashes = hashes$1.exports,
115299             sha1 = new hashes.SHA1(); // # xtend
115300
115301         var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
115302
115303         function xtend$1() {
115304           var target = {};
115305
115306           for (var i = 0; i < arguments.length; i++) {
115307             var source = arguments[i];
115308
115309             for (var key in source) {
115310               if (hasOwnProperty$1.call(source, key)) {
115311                 target[key] = source[key];
115312               }
115313             }
115314           }
115315
115316           return target;
115317         }
115318
115319         var ohauth$1 = {};
115320
115321         ohauth$1.qsString = function (obj) {
115322           return Object.keys(obj).sort().map(function (key) {
115323             return ohauth$1.percentEncode(key) + '=' + ohauth$1.percentEncode(obj[key]);
115324           }).join('&');
115325         };
115326
115327         ohauth$1.stringQs = function (str) {
115328           return str.split('&').filter(function (pair) {
115329             return pair !== '';
115330           }).reduce(function (obj, pair) {
115331             var parts = pair.split('=');
115332             obj[decodeURIComponent(parts[0])] = null === parts[1] ? '' : decodeURIComponent(parts[1]);
115333             return obj;
115334           }, {});
115335         };
115336
115337         ohauth$1.rawxhr = function (method, url, data, headers, callback) {
115338           var xhr = new XMLHttpRequest(),
115339               twoHundred = /^20\d$/;
115340
115341           xhr.onreadystatechange = function () {
115342             if (4 === xhr.readyState && 0 !== xhr.status) {
115343               if (twoHundred.test(xhr.status)) callback(null, xhr);else return callback(xhr, null);
115344             }
115345           };
115346
115347           xhr.onerror = function (e) {
115348             return callback(e, null);
115349           };
115350
115351           xhr.open(method, url, true);
115352
115353           for (var h in headers) {
115354             xhr.setRequestHeader(h, headers[h]);
115355           }
115356
115357           xhr.send(data);
115358           return xhr;
115359         };
115360
115361         ohauth$1.xhr = function (method, url, auth, data, options, callback) {
115362           var headers = options && options.header || {
115363             'Content-Type': 'application/x-www-form-urlencoded'
115364           };
115365           headers.Authorization = 'OAuth ' + ohauth$1.authHeader(auth);
115366           return ohauth$1.rawxhr(method, url, data, headers, callback);
115367         };
115368
115369         ohauth$1.nonce = function () {
115370           for (var o = ''; o.length < 6;) {
115371             o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
115372           }
115373
115374           return o;
115375         };
115376
115377         ohauth$1.authHeader = function (obj) {
115378           return Object.keys(obj).sort().map(function (key) {
115379             return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
115380           }).join(', ');
115381         };
115382
115383         ohauth$1.timestamp = function () {
115384           return ~~(+new Date() / 1000);
115385         };
115386
115387         ohauth$1.percentEncode = function (s) {
115388           return encodeURIComponent(s).replace(/\!/g, '%21').replace(/\'/g, '%27').replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
115389         };
115390
115391         ohauth$1.baseString = function (method, url, params) {
115392           if (params.oauth_signature) delete params.oauth_signature;
115393           return [method, ohauth$1.percentEncode(url), ohauth$1.percentEncode(ohauth$1.qsString(params))].join('&');
115394         };
115395
115396         ohauth$1.signature = function (oauth_secret, token_secret, baseString) {
115397           return sha1.b64_hmac(ohauth$1.percentEncode(oauth_secret) + '&' + ohauth$1.percentEncode(token_secret), baseString);
115398         };
115399         /**
115400          * Takes an options object for configuration (consumer_key,
115401          * consumer_secret, version, signature_method, token, token_secret)
115402          * and returns a function that generates the Authorization header
115403          * for given data.
115404          *
115405          * The returned function takes these parameters:
115406          * - method: GET/POST/...
115407          * - uri: full URI with protocol, port, path and query string
115408          * - extra_params: any extra parameters (that are passed in the POST data),
115409          *   can be an object or a from-urlencoded string.
115410          *
115411          * Returned function returns full OAuth header with "OAuth" string in it.
115412          */
115413
115414
115415         ohauth$1.headerGenerator = function (options) {
115416           options = options || {};
115417           var consumer_key = options.consumer_key || '',
115418               consumer_secret = options.consumer_secret || '',
115419               signature_method = options.signature_method || 'HMAC-SHA1',
115420               version = options.version || '1.0',
115421               token = options.token || '',
115422               token_secret = options.token_secret || '';
115423           return function (method, uri, extra_params) {
115424             method = method.toUpperCase();
115425
115426             if (typeof extra_params === 'string' && extra_params.length > 0) {
115427               extra_params = ohauth$1.stringQs(extra_params);
115428             }
115429
115430             var uri_parts = uri.split('?', 2),
115431                 base_uri = uri_parts[0];
115432             var query_params = uri_parts.length === 2 ? ohauth$1.stringQs(uri_parts[1]) : {};
115433             var oauth_params = {
115434               oauth_consumer_key: consumer_key,
115435               oauth_signature_method: signature_method,
115436               oauth_version: version,
115437               oauth_timestamp: ohauth$1.timestamp(),
115438               oauth_nonce: ohauth$1.nonce()
115439             };
115440             if (token) oauth_params.oauth_token = token;
115441             var all_params = xtend$1({}, oauth_params, query_params, extra_params),
115442                 base_str = ohauth$1.baseString(method, base_uri, all_params);
115443             oauth_params.oauth_signature = ohauth$1.signature(consumer_secret, token_secret, base_str);
115444             return 'OAuth ' + ohauth$1.authHeader(oauth_params);
115445           };
115446         };
115447
115448         var ohauth_1 = ohauth$1;
115449
115450         var resolveUrl$1 = {exports: {}};
115451
115452         (function (module, exports) {
115453           // Copyright 2014 Simon Lydell
115454           // X11 (“MIT”) Licensed. (See LICENSE.)
115455           void function (root, factory) {
115456             {
115457               module.exports = factory();
115458             }
115459           }(commonjsGlobal, function () {
115460             function
115461               /* ...urls */
115462             resolveUrl() {
115463               var numUrls = arguments.length;
115464
115465               if (numUrls === 0) {
115466                 throw new Error("resolveUrl requires at least one argument; got none.");
115467               }
115468
115469               var base = document.createElement("base");
115470               base.href = arguments[0];
115471
115472               if (numUrls === 1) {
115473                 return base.href;
115474               }
115475
115476               var head = document.getElementsByTagName("head")[0];
115477               head.insertBefore(base, head.firstChild);
115478               var a = document.createElement("a");
115479               var resolved;
115480
115481               for (var index = 1; index < numUrls; index++) {
115482                 a.href = arguments[index];
115483                 resolved = a.href;
115484                 base.href = resolved;
115485               }
115486
115487               head.removeChild(base);
115488               return resolved;
115489             }
115490
115491             return resolveUrl;
115492           });
115493         })(resolveUrl$1);
115494
115495         var assign = make_assign();
115496         var create$1 = make_create();
115497         var trim$1 = make_trim();
115498         var Global$5 = typeof window !== 'undefined' ? window : commonjsGlobal;
115499         var util$6 = {
115500           assign: assign,
115501           create: create$1,
115502           trim: trim$1,
115503           bind: bind$1,
115504           slice: slice$1,
115505           each: each$7,
115506           map: map,
115507           pluck: pluck$1,
115508           isList: isList$1,
115509           isFunction: isFunction$1,
115510           isObject: isObject$1,
115511           Global: Global$5
115512         };
115513
115514         function make_assign() {
115515           if (Object.assign) {
115516             return Object.assign;
115517           } else {
115518             return function shimAssign(obj, props1, props2, etc) {
115519               for (var i = 1; i < arguments.length; i++) {
115520                 each$7(Object(arguments[i]), function (val, key) {
115521                   obj[key] = val;
115522                 });
115523               }
115524
115525               return obj;
115526             };
115527           }
115528         }
115529
115530         function make_create() {
115531           if (Object.create) {
115532             return function create(obj, assignProps1, assignProps2, etc) {
115533               var assignArgsList = slice$1(arguments, 1);
115534               return assign.apply(this, [Object.create(obj)].concat(assignArgsList));
115535             };
115536           } else {
115537             var F = function F() {}; // eslint-disable-line no-inner-declarations
115538
115539
115540             return function create(obj, assignProps1, assignProps2, etc) {
115541               var assignArgsList = slice$1(arguments, 1);
115542               F.prototype = obj;
115543               return assign.apply(this, [new F()].concat(assignArgsList));
115544             };
115545           }
115546         }
115547
115548         function make_trim() {
115549           if (String.prototype.trim) {
115550             return function trim(str) {
115551               return String.prototype.trim.call(str);
115552             };
115553           } else {
115554             return function trim(str) {
115555               return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
115556             };
115557           }
115558         }
115559
115560         function bind$1(obj, fn) {
115561           return function () {
115562             return fn.apply(obj, Array.prototype.slice.call(arguments, 0));
115563           };
115564         }
115565
115566         function slice$1(arr, index) {
115567           return Array.prototype.slice.call(arr, index || 0);
115568         }
115569
115570         function each$7(obj, fn) {
115571           pluck$1(obj, function (val, key) {
115572             fn(val, key);
115573             return false;
115574           });
115575         }
115576
115577         function map(obj, fn) {
115578           var res = isList$1(obj) ? [] : {};
115579           pluck$1(obj, function (v, k) {
115580             res[k] = fn(v, k);
115581             return false;
115582           });
115583           return res;
115584         }
115585
115586         function pluck$1(obj, fn) {
115587           if (isList$1(obj)) {
115588             for (var i = 0; i < obj.length; i++) {
115589               if (fn(obj[i], i)) {
115590                 return obj[i];
115591               }
115592             }
115593           } else {
115594             for (var key in obj) {
115595               if (obj.hasOwnProperty(key)) {
115596                 if (fn(obj[key], key)) {
115597                   return obj[key];
115598                 }
115599               }
115600             }
115601           }
115602         }
115603
115604         function isList$1(val) {
115605           return val != null && typeof val != 'function' && typeof val.length == 'number';
115606         }
115607
115608         function isFunction$1(val) {
115609           return val && {}.toString.call(val) === '[object Function]';
115610         }
115611
115612         function isObject$1(val) {
115613           return val && {}.toString.call(val) === '[object Object]';
115614         }
115615
115616         var util$5 = util$6;
115617         var slice = util$5.slice;
115618         var pluck = util$5.pluck;
115619         var each$6 = util$5.each;
115620         var bind = util$5.bind;
115621         var create = util$5.create;
115622         var isList = util$5.isList;
115623         var isFunction = util$5.isFunction;
115624         var isObject = util$5.isObject;
115625         var storeEngine = {
115626           createStore: _createStore
115627         };
115628         var storeAPI = {
115629           version: '2.0.12',
115630           enabled: false,
115631           // get returns the value of the given key. If that value
115632           // is undefined, it returns optionalDefaultValue instead.
115633           get: function get(key, optionalDefaultValue) {
115634             var data = this.storage.read(this._namespacePrefix + key);
115635             return this._deserialize(data, optionalDefaultValue);
115636           },
115637           // set will store the given value at key and returns value.
115638           // Calling set with value === undefined is equivalent to calling remove.
115639           set: function set(key, value) {
115640             if (value === undefined) {
115641               return this.remove(key);
115642             }
115643
115644             this.storage.write(this._namespacePrefix + key, this._serialize(value));
115645             return value;
115646           },
115647           // remove deletes the key and value stored at the given key.
115648           remove: function remove(key) {
115649             this.storage.remove(this._namespacePrefix + key);
115650           },
115651           // each will call the given callback once for each key-value pair
115652           // in this store.
115653           each: function each(callback) {
115654             var self = this;
115655             this.storage.each(function (val, namespacedKey) {
115656               callback.call(self, self._deserialize(val), (namespacedKey || '').replace(self._namespaceRegexp, ''));
115657             });
115658           },
115659           // clearAll will remove all the stored key-value pairs in this store.
115660           clearAll: function clearAll() {
115661             this.storage.clearAll();
115662           },
115663           // additional functionality that can't live in plugins
115664           // ---------------------------------------------------
115665           // hasNamespace returns true if this store instance has the given namespace.
115666           hasNamespace: function hasNamespace(namespace) {
115667             return this._namespacePrefix == '__storejs_' + namespace + '_';
115668           },
115669           // createStore creates a store.js instance with the first
115670           // functioning storage in the list of storage candidates,
115671           // and applies the the given mixins to the instance.
115672           createStore: function createStore() {
115673             return _createStore.apply(this, arguments);
115674           },
115675           addPlugin: function addPlugin(plugin) {
115676             this._addPlugin(plugin);
115677           },
115678           namespace: function namespace(_namespace) {
115679             return _createStore(this.storage, this.plugins, _namespace);
115680           }
115681         };
115682
115683         function _warn() {
115684           var _console = typeof console == 'undefined' ? null : console;
115685
115686           if (!_console) {
115687             return;
115688           }
115689
115690           var fn = _console.warn ? _console.warn : _console.log;
115691           fn.apply(_console, arguments);
115692         }
115693
115694         function _createStore(storages, plugins, namespace) {
115695           if (!namespace) {
115696             namespace = '';
115697           }
115698
115699           if (storages && !isList(storages)) {
115700             storages = [storages];
115701           }
115702
115703           if (plugins && !isList(plugins)) {
115704             plugins = [plugins];
115705           }
115706
115707           var namespacePrefix = namespace ? '__storejs_' + namespace + '_' : '';
115708           var namespaceRegexp = namespace ? new RegExp('^' + namespacePrefix) : null;
115709           var legalNamespaces = /^[a-zA-Z0-9_\-]*$/; // alpha-numeric + underscore and dash
115710
115711           if (!legalNamespaces.test(namespace)) {
115712             throw new Error('store.js namespaces can only have alphanumerics + underscores and dashes');
115713           }
115714
115715           var _privateStoreProps = {
115716             _namespacePrefix: namespacePrefix,
115717             _namespaceRegexp: namespaceRegexp,
115718             _testStorage: function _testStorage(storage) {
115719               try {
115720                 var testStr = '__storejs__test__';
115721                 storage.write(testStr, testStr);
115722                 var ok = storage.read(testStr) === testStr;
115723                 storage.remove(testStr);
115724                 return ok;
115725               } catch (e) {
115726                 return false;
115727               }
115728             },
115729             _assignPluginFnProp: function _assignPluginFnProp(pluginFnProp, propName) {
115730               var oldFn = this[propName];
115731
115732               this[propName] = function pluginFn() {
115733                 var args = slice(arguments, 0);
115734                 var self = this; // super_fn calls the old function which was overwritten by
115735                 // this mixin.
115736
115737                 function super_fn() {
115738                   if (!oldFn) {
115739                     return;
115740                   }
115741
115742                   each$6(arguments, function (arg, i) {
115743                     args[i] = arg;
115744                   });
115745                   return oldFn.apply(self, args);
115746                 } // Give mixing function access to super_fn by prefixing all mixin function
115747                 // arguments with super_fn.
115748
115749
115750                 var newFnArgs = [super_fn].concat(args);
115751                 return pluginFnProp.apply(self, newFnArgs);
115752               };
115753             },
115754             _serialize: function _serialize(obj) {
115755               return JSON.stringify(obj);
115756             },
115757             _deserialize: function _deserialize(strVal, defaultVal) {
115758               if (!strVal) {
115759                 return defaultVal;
115760               } // It is possible that a raw string value has been previously stored
115761               // in a storage without using store.js, meaning it will be a raw
115762               // string value instead of a JSON serialized string. By defaulting
115763               // to the raw string value in case of a JSON parse error, we allow
115764               // for past stored values to be forwards-compatible with store.js
115765
115766
115767               var val = '';
115768
115769               try {
115770                 val = JSON.parse(strVal);
115771               } catch (e) {
115772                 val = strVal;
115773               }
115774
115775               return val !== undefined ? val : defaultVal;
115776             },
115777             _addStorage: function _addStorage(storage) {
115778               if (this.enabled) {
115779                 return;
115780               }
115781
115782               if (this._testStorage(storage)) {
115783                 this.storage = storage;
115784                 this.enabled = true;
115785               }
115786             },
115787             _addPlugin: function _addPlugin(plugin) {
115788               var self = this; // If the plugin is an array, then add all plugins in the array.
115789               // This allows for a plugin to depend on other plugins.
115790
115791               if (isList(plugin)) {
115792                 each$6(plugin, function (plugin) {
115793                   self._addPlugin(plugin);
115794                 });
115795                 return;
115796               } // Keep track of all plugins we've seen so far, so that we
115797               // don't add any of them twice.
115798
115799
115800               var seenPlugin = pluck(this.plugins, function (seenPlugin) {
115801                 return plugin === seenPlugin;
115802               });
115803
115804               if (seenPlugin) {
115805                 return;
115806               }
115807
115808               this.plugins.push(plugin); // Check that the plugin is properly formed
115809
115810               if (!isFunction(plugin)) {
115811                 throw new Error('Plugins must be function values that return objects');
115812               }
115813
115814               var pluginProperties = plugin.call(this);
115815
115816               if (!isObject(pluginProperties)) {
115817                 throw new Error('Plugins must return an object of function properties');
115818               } // Add the plugin function properties to this store instance.
115819
115820
115821               each$6(pluginProperties, function (pluginFnProp, propName) {
115822                 if (!isFunction(pluginFnProp)) {
115823                   throw new Error('Bad plugin property: ' + propName + ' from plugin ' + plugin.name + '. Plugins should only return functions.');
115824                 }
115825
115826                 self._assignPluginFnProp(pluginFnProp, propName);
115827               });
115828             },
115829             // Put deprecated properties in the private API, so as to not expose it to accidential
115830             // discovery through inspection of the store object.
115831             // Deprecated: addStorage
115832             addStorage: function addStorage(storage) {
115833               _warn('store.addStorage(storage) is deprecated. Use createStore([storages])');
115834
115835               this._addStorage(storage);
115836             }
115837           };
115838           var store = create(_privateStoreProps, storeAPI, {
115839             plugins: []
115840           });
115841           store.raw = {};
115842           each$6(store, function (prop, propName) {
115843             if (isFunction(prop)) {
115844               store.raw[propName] = bind(store, prop);
115845             }
115846           });
115847           each$6(storages, function (storage) {
115848             store._addStorage(storage);
115849           });
115850           each$6(plugins, function (plugin) {
115851             store._addPlugin(plugin);
115852           });
115853           return store;
115854         }
115855
115856         var util$4 = util$6;
115857         var Global$4 = util$4.Global;
115858         var localStorage_1 = {
115859           name: 'localStorage',
115860           read: read$5,
115861           write: write$5,
115862           each: each$5,
115863           remove: remove$5,
115864           clearAll: clearAll$5
115865         };
115866
115867         function localStorage$1() {
115868           return Global$4.localStorage;
115869         }
115870
115871         function read$5(key) {
115872           return localStorage$1().getItem(key);
115873         }
115874
115875         function write$5(key, data) {
115876           return localStorage$1().setItem(key, data);
115877         }
115878
115879         function each$5(fn) {
115880           for (var i = localStorage$1().length - 1; i >= 0; i--) {
115881             var key = localStorage$1().key(i);
115882             fn(read$5(key), key);
115883           }
115884         }
115885
115886         function remove$5(key) {
115887           return localStorage$1().removeItem(key);
115888         }
115889
115890         function clearAll$5() {
115891           return localStorage$1().clear();
115892         }
115893
115894         // versions 6 and 7, where no localStorage, etc
115895         // is available.
115896
115897         var util$3 = util$6;
115898         var Global$3 = util$3.Global;
115899         var oldFFGlobalStorage = {
115900           name: 'oldFF-globalStorage',
115901           read: read$4,
115902           write: write$4,
115903           each: each$4,
115904           remove: remove$4,
115905           clearAll: clearAll$4
115906         };
115907         var globalStorage = Global$3.globalStorage;
115908
115909         function read$4(key) {
115910           return globalStorage[key];
115911         }
115912
115913         function write$4(key, data) {
115914           globalStorage[key] = data;
115915         }
115916
115917         function each$4(fn) {
115918           for (var i = globalStorage.length - 1; i >= 0; i--) {
115919             var key = globalStorage.key(i);
115920             fn(globalStorage[key], key);
115921           }
115922         }
115923
115924         function remove$4(key) {
115925           return globalStorage.removeItem(key);
115926         }
115927
115928         function clearAll$4() {
115929           each$4(function (key, _) {
115930             delete globalStorage[key];
115931           });
115932         }
115933
115934         // versions 6 and 7, where no localStorage, sessionStorage, etc
115935         // is available.
115936
115937         var util$2 = util$6;
115938         var Global$2 = util$2.Global;
115939         var oldIEUserDataStorage = {
115940           name: 'oldIE-userDataStorage',
115941           write: write$3,
115942           read: read$3,
115943           each: each$3,
115944           remove: remove$3,
115945           clearAll: clearAll$3
115946         };
115947         var storageName = 'storejs';
115948         var doc$1 = Global$2.document;
115949
115950         var _withStorageEl = _makeIEStorageElFunction();
115951
115952         var disable = (Global$2.navigator ? Global$2.navigator.userAgent : '').match(/ (MSIE 8|MSIE 9|MSIE 10)\./); // MSIE 9.x, MSIE 10.x
115953
115954         function write$3(unfixedKey, data) {
115955           if (disable) {
115956             return;
115957           }
115958
115959           var fixedKey = fixKey(unfixedKey);
115960
115961           _withStorageEl(function (storageEl) {
115962             storageEl.setAttribute(fixedKey, data);
115963             storageEl.save(storageName);
115964           });
115965         }
115966
115967         function read$3(unfixedKey) {
115968           if (disable) {
115969             return;
115970           }
115971
115972           var fixedKey = fixKey(unfixedKey);
115973           var res = null;
115974
115975           _withStorageEl(function (storageEl) {
115976             res = storageEl.getAttribute(fixedKey);
115977           });
115978
115979           return res;
115980         }
115981
115982         function each$3(callback) {
115983           _withStorageEl(function (storageEl) {
115984             var attributes = storageEl.XMLDocument.documentElement.attributes;
115985
115986             for (var i = attributes.length - 1; i >= 0; i--) {
115987               var attr = attributes[i];
115988               callback(storageEl.getAttribute(attr.name), attr.name);
115989             }
115990           });
115991         }
115992
115993         function remove$3(unfixedKey) {
115994           var fixedKey = fixKey(unfixedKey);
115995
115996           _withStorageEl(function (storageEl) {
115997             storageEl.removeAttribute(fixedKey);
115998             storageEl.save(storageName);
115999           });
116000         }
116001
116002         function clearAll$3() {
116003           _withStorageEl(function (storageEl) {
116004             var attributes = storageEl.XMLDocument.documentElement.attributes;
116005             storageEl.load(storageName);
116006
116007             for (var i = attributes.length - 1; i >= 0; i--) {
116008               storageEl.removeAttribute(attributes[i].name);
116009             }
116010
116011             storageEl.save(storageName);
116012           });
116013         } // Helpers
116014         //////////
116015         // In IE7, keys cannot start with a digit or contain certain chars.
116016         // See https://github.com/marcuswestin/store.js/issues/40
116017         // See https://github.com/marcuswestin/store.js/issues/83
116018
116019
116020         var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
116021
116022         function fixKey(key) {
116023           return key.replace(/^\d/, '___$&').replace(forbiddenCharsRegex, '___');
116024         }
116025
116026         function _makeIEStorageElFunction() {
116027           if (!doc$1 || !doc$1.documentElement || !doc$1.documentElement.addBehavior) {
116028             return null;
116029           }
116030
116031           var scriptTag = 'script',
116032               storageOwner,
116033               storageContainer,
116034               storageEl; // Since #userData storage applies only to specific paths, we need to
116035           // somehow link our data to a specific path.  We choose /favicon.ico
116036           // as a pretty safe option, since all browsers already make a request to
116037           // this URL anyway and being a 404 will not hurt us here.  We wrap an
116038           // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
116039           // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
116040           // since the iframe access rules appear to allow direct access and
116041           // manipulation of the document element, even for a 404 page.  This
116042           // document can be used instead of the current document (which would
116043           // have been limited to the current path) to perform #userData storage.
116044
116045           try {
116046             /* global ActiveXObject */
116047             storageContainer = new ActiveXObject('htmlfile');
116048             storageContainer.open();
116049             storageContainer.write('<' + scriptTag + '>document.w=window</' + scriptTag + '><iframe src="/favicon.ico"></iframe>');
116050             storageContainer.close();
116051             storageOwner = storageContainer.w.frames[0].document;
116052             storageEl = storageOwner.createElement('div');
116053           } catch (e) {
116054             // somehow ActiveXObject instantiation failed (perhaps some special
116055             // security settings or otherwse), fall back to per-path storage
116056             storageEl = doc$1.createElement('div');
116057             storageOwner = doc$1.body;
116058           }
116059
116060           return function (storeFunction) {
116061             var args = [].slice.call(arguments, 0);
116062             args.unshift(storageEl); // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
116063             // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
116064
116065             storageOwner.appendChild(storageEl);
116066             storageEl.addBehavior('#default#userData');
116067             storageEl.load(storageName);
116068             storeFunction.apply(this, args);
116069             storageOwner.removeChild(storageEl);
116070             return;
116071           };
116072         }
116073
116074         // doesn't work but cookies do. This implementation is adopted from
116075         // https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage
116076
116077         var util$1 = util$6;
116078         var Global$1 = util$1.Global;
116079         var trim = util$1.trim;
116080         var cookieStorage = {
116081           name: 'cookieStorage',
116082           read: read$2,
116083           write: write$2,
116084           each: each$2,
116085           remove: remove$2,
116086           clearAll: clearAll$2
116087         };
116088         var doc = Global$1.document;
116089
116090         function read$2(key) {
116091           if (!key || !_has(key)) {
116092             return null;
116093           }
116094
116095           var regexpStr = "(?:^|.*;\\s*)" + escape(key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*";
116096           return unescape(doc.cookie.replace(new RegExp(regexpStr), "$1"));
116097         }
116098
116099         function each$2(callback) {
116100           var cookies = doc.cookie.split(/; ?/g);
116101
116102           for (var i = cookies.length - 1; i >= 0; i--) {
116103             if (!trim(cookies[i])) {
116104               continue;
116105             }
116106
116107             var kvp = cookies[i].split('=');
116108             var key = unescape(kvp[0]);
116109             var val = unescape(kvp[1]);
116110             callback(val, key);
116111           }
116112         }
116113
116114         function write$2(key, data) {
116115           if (!key) {
116116             return;
116117           }
116118
116119           doc.cookie = escape(key) + "=" + escape(data) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/";
116120         }
116121
116122         function remove$2(key) {
116123           if (!key || !_has(key)) {
116124             return;
116125           }
116126
116127           doc.cookie = escape(key) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
116128         }
116129
116130         function clearAll$2() {
116131           each$2(function (_, key) {
116132             remove$2(key);
116133           });
116134         }
116135
116136         function _has(key) {
116137           return new RegExp("(?:^|;\\s*)" + escape(key).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=").test(doc.cookie);
116138         }
116139
116140         var util = util$6;
116141         var Global = util.Global;
116142         var sessionStorage_1 = {
116143           name: 'sessionStorage',
116144           read: read$1,
116145           write: write$1,
116146           each: each$1,
116147           remove: remove$1,
116148           clearAll: clearAll$1
116149         };
116150
116151         function sessionStorage() {
116152           return Global.sessionStorage;
116153         }
116154
116155         function read$1(key) {
116156           return sessionStorage().getItem(key);
116157         }
116158
116159         function write$1(key, data) {
116160           return sessionStorage().setItem(key, data);
116161         }
116162
116163         function each$1(fn) {
116164           for (var i = sessionStorage().length - 1; i >= 0; i--) {
116165             var key = sessionStorage().key(i);
116166             fn(read$1(key), key);
116167           }
116168         }
116169
116170         function remove$1(key) {
116171           return sessionStorage().removeItem(key);
116172         }
116173
116174         function clearAll$1() {
116175           return sessionStorage().clear();
116176         }
116177
116178         // is functions (meaning store.get(), store.set(), etc will all function).
116179         // However, stored values will not persist when the browser navigates to
116180         // a new page or reloads the current page.
116181
116182         var memoryStorage_1 = {
116183           name: 'memoryStorage',
116184           read: read,
116185           write: write,
116186           each: each,
116187           remove: remove,
116188           clearAll: clearAll
116189         };
116190         var memoryStorage = {};
116191
116192         function read(key) {
116193           return memoryStorage[key];
116194         }
116195
116196         function write(key, data) {
116197           memoryStorage[key] = data;
116198         }
116199
116200         function each(callback) {
116201           for (var key in memoryStorage) {
116202             if (memoryStorage.hasOwnProperty(key)) {
116203               callback(memoryStorage[key], key);
116204             }
116205           }
116206         }
116207
116208         function remove(key) {
116209           delete memoryStorage[key];
116210         }
116211
116212         function clearAll(key) {
116213           memoryStorage = {};
116214         }
116215
116216         var all = [// Listed in order of usage preference
116217         localStorage_1, oldFFGlobalStorage, oldIEUserDataStorage, cookieStorage, sessionStorage_1, memoryStorage_1];
116218
116219         /* eslint-disable */
116220         //  json2.js
116221         //  2016-10-28
116222         //  Public Domain.
116223         //  NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
116224         //  See http://www.JSON.org/js.html
116225         //  This code should be minified before deployment.
116226         //  See http://javascript.crockford.com/jsmin.html
116227         //  USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
116228         //  NOT CONTROL.
116229         //  This file creates a global JSON object containing two methods: stringify
116230         //  and parse. This file provides the ES5 JSON capability to ES3 systems.
116231         //  If a project might run on IE8 or earlier, then this file should be included.
116232         //  This file does nothing on ES5 systems.
116233         //      JSON.stringify(value, replacer, space)
116234         //          value       any JavaScript value, usually an object or array.
116235         //          replacer    an optional parameter that determines how object
116236         //                      values are stringified for objects. It can be a
116237         //                      function or an array of strings.
116238         //          space       an optional parameter that specifies the indentation
116239         //                      of nested structures. If it is omitted, the text will
116240         //                      be packed without extra whitespace. If it is a number,
116241         //                      it will specify the number of spaces to indent at each
116242         //                      level. If it is a string (such as "\t" or "&nbsp;"),
116243         //                      it contains the characters used to indent at each level.
116244         //          This method produces a JSON text from a JavaScript value.
116245         //          When an object value is found, if the object contains a toJSON
116246         //          method, its toJSON method will be called and the result will be
116247         //          stringified. A toJSON method does not serialize: it returns the
116248         //          value represented by the name/value pair that should be serialized,
116249         //          or undefined if nothing should be serialized. The toJSON method
116250         //          will be passed the key associated with the value, and this will be
116251         //          bound to the value.
116252         //          For example, this would serialize Dates as ISO strings.
116253         //              Date.prototype.toJSON = function (key) {
116254         //                  function f(n) {
116255         //                      // Format integers to have at least two digits.
116256         //                      return (n < 10)
116257         //                          ? "0" + n
116258         //                          : n;
116259         //                  }
116260         //                  return this.getUTCFullYear()   + "-" +
116261         //                       f(this.getUTCMonth() + 1) + "-" +
116262         //                       f(this.getUTCDate())      + "T" +
116263         //                       f(this.getUTCHours())     + ":" +
116264         //                       f(this.getUTCMinutes())   + ":" +
116265         //                       f(this.getUTCSeconds())   + "Z";
116266         //              };
116267         //          You can provide an optional replacer method. It will be passed the
116268         //          key and value of each member, with this bound to the containing
116269         //          object. The value that is returned from your method will be
116270         //          serialized. If your method returns undefined, then the member will
116271         //          be excluded from the serialization.
116272         //          If the replacer parameter is an array of strings, then it will be
116273         //          used to select the members to be serialized. It filters the results
116274         //          such that only members with keys listed in the replacer array are
116275         //          stringified.
116276         //          Values that do not have JSON representations, such as undefined or
116277         //          functions, will not be serialized. Such values in objects will be
116278         //          dropped; in arrays they will be replaced with null. You can use
116279         //          a replacer function to replace those with JSON values.
116280         //          JSON.stringify(undefined) returns undefined.
116281         //          The optional space parameter produces a stringification of the
116282         //          value that is filled with line breaks and indentation to make it
116283         //          easier to read.
116284         //          If the space parameter is a non-empty string, then that string will
116285         //          be used for indentation. If the space parameter is a number, then
116286         //          the indentation will be that many spaces.
116287         //          Example:
116288         //          text = JSON.stringify(["e", {pluribus: "unum"}]);
116289         //          // text is '["e",{"pluribus":"unum"}]'
116290         //          text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t");
116291         //          // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
116292         //          text = JSON.stringify([new Date()], function (key, value) {
116293         //              return this[key] instanceof Date
116294         //                  ? "Date(" + this[key] + ")"
116295         //                  : value;
116296         //          });
116297         //          // text is '["Date(---current time---)"]'
116298         //      JSON.parse(text, reviver)
116299         //          This method parses a JSON text to produce an object or array.
116300         //          It can throw a SyntaxError exception.
116301         //          The optional reviver parameter is a function that can filter and
116302         //          transform the results. It receives each of the keys and values,
116303         //          and its return value is used instead of the original value.
116304         //          If it returns what it received, then the structure is not modified.
116305         //          If it returns undefined then the member is deleted.
116306         //          Example:
116307         //          // Parse the text. Values that look like ISO date strings will
116308         //          // be converted to Date objects.
116309         //          myData = JSON.parse(text, function (key, value) {
116310         //              var a;
116311         //              if (typeof value === "string") {
116312         //                  a =
116313         //   /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
116314         //                  if (a) {
116315         //                      return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
116316         //                          +a[5], +a[6]));
116317         //                  }
116318         //              }
116319         //              return value;
116320         //          });
116321         //          myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
116322         //              var d;
116323         //              if (typeof value === "string" &&
116324         //                      value.slice(0, 5) === "Date(" &&
116325         //                      value.slice(-1) === ")") {
116326         //                  d = new Date(value.slice(5, -1));
116327         //                  if (d) {
116328         //                      return d;
116329         //                  }
116330         //              }
116331         //              return value;
116332         //          });
116333         //  This is a reference implementation. You are free to copy, modify, or
116334         //  redistribute.
116335
116336         /*jslint
116337             eval, for, this
116338         */
116339
116340         /*property
116341             JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
116342             getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
116343             lastIndex, length, parse, prototype, push, replace, slice, stringify,
116344             test, toJSON, toString, valueOf
116345         */
116346         // Create a JSON object only if one does not already exist. We create the
116347         // methods in a closure to avoid creating global variables.
116348         if ((typeof JSON === "undefined" ? "undefined" : _typeof(JSON)) !== "object") {
116349           JSON = {};
116350         }
116351
116352         (function () {
116353
116354           var rx_one = /^[\],:{}\s]*$/;
116355           var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
116356           var rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
116357           var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
116358           var rx_escapable = /[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
116359           var rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
116360
116361           function f(n) {
116362             // Format integers to have at least two digits.
116363             return n < 10 ? "0" + n : n;
116364           }
116365
116366           function this_value() {
116367             return this.valueOf();
116368           }
116369
116370           if (typeof Date.prototype.toJSON !== "function") {
116371             Date.prototype.toJSON = function () {
116372               return isFinite(this.valueOf()) ? this.getUTCFullYear() + "-" + f(this.getUTCMonth() + 1) + "-" + f(this.getUTCDate()) + "T" + f(this.getUTCHours()) + ":" + f(this.getUTCMinutes()) + ":" + f(this.getUTCSeconds()) + "Z" : null;
116373             };
116374
116375             Boolean.prototype.toJSON = this_value;
116376             Number.prototype.toJSON = this_value;
116377             String.prototype.toJSON = this_value;
116378           }
116379
116380           var gap;
116381           var indent;
116382           var meta;
116383           var rep;
116384
116385           function quote(string) {
116386             // If the string contains no control characters, no quote characters, and no
116387             // backslash characters, then we can safely slap some quotes around it.
116388             // Otherwise we must also replace the offending characters with safe escape
116389             // sequences.
116390             rx_escapable.lastIndex = 0;
116391             return rx_escapable.test(string) ? "\"" + string.replace(rx_escapable, function (a) {
116392               var c = meta[a];
116393               return typeof c === "string" ? c : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
116394             }) + "\"" : "\"" + string + "\"";
116395           }
116396
116397           function str(key, holder) {
116398             // Produce a string from holder[key].
116399             var i; // The loop counter.
116400
116401             var k; // The member key.
116402
116403             var v; // The member value.
116404
116405             var length;
116406             var mind = gap;
116407             var partial;
116408             var value = holder[key]; // If the value has a toJSON method, call it to obtain a replacement value.
116409
116410             if (value && _typeof(value) === "object" && typeof value.toJSON === "function") {
116411               value = value.toJSON(key);
116412             } // If we were called with a replacer function, then call the replacer to
116413             // obtain a replacement value.
116414
116415
116416             if (typeof rep === "function") {
116417               value = rep.call(holder, key, value);
116418             } // What happens next depends on the value's type.
116419
116420
116421             switch (_typeof(value)) {
116422               case "string":
116423                 return quote(value);
116424
116425               case "number":
116426                 // JSON numbers must be finite. Encode non-finite numbers as null.
116427                 return isFinite(value) ? String(value) : "null";
116428
116429               case "boolean":
116430               case "null":
116431                 // If the value is a boolean or null, convert it to a string. Note:
116432                 // typeof null does not produce "null". The case is included here in
116433                 // the remote chance that this gets fixed someday.
116434                 return String(value);
116435               // If the type is "object", we might be dealing with an object or an array or
116436               // null.
116437
116438               case "object":
116439                 // Due to a specification blunder in ECMAScript, typeof null is "object",
116440                 // so watch out for that case.
116441                 if (!value) {
116442                   return "null";
116443                 } // Make an array to hold the partial results of stringifying this object value.
116444
116445
116446                 gap += indent;
116447                 partial = []; // Is the value an array?
116448
116449                 if (Object.prototype.toString.apply(value) === "[object Array]") {
116450                   // The value is an array. Stringify every element. Use null as a placeholder
116451                   // for non-JSON values.
116452                   length = value.length;
116453
116454                   for (i = 0; i < length; i += 1) {
116455                     partial[i] = str(i, value) || "null";
116456                   } // Join all of the elements together, separated with commas, and wrap them in
116457                   // brackets.
116458
116459
116460                   v = partial.length === 0 ? "[]" : gap ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]" : "[" + partial.join(",") + "]";
116461                   gap = mind;
116462                   return v;
116463                 } // If the replacer is an array, use it to select the members to be stringified.
116464
116465
116466                 if (rep && _typeof(rep) === "object") {
116467                   length = rep.length;
116468
116469                   for (i = 0; i < length; i += 1) {
116470                     if (typeof rep[i] === "string") {
116471                       k = rep[i];
116472                       v = str(k, value);
116473
116474                       if (v) {
116475                         partial.push(quote(k) + (gap ? ": " : ":") + v);
116476                       }
116477                     }
116478                   }
116479                 } else {
116480                   // Otherwise, iterate through all of the keys in the object.
116481                   for (k in value) {
116482                     if (Object.prototype.hasOwnProperty.call(value, k)) {
116483                       v = str(k, value);
116484
116485                       if (v) {
116486                         partial.push(quote(k) + (gap ? ": " : ":") + v);
116487                       }
116488                     }
116489                   }
116490                 } // Join all of the member texts together, separated with commas,
116491                 // and wrap them in braces.
116492
116493
116494                 v = partial.length === 0 ? "{}" : gap ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}" : "{" + partial.join(",") + "}";
116495                 gap = mind;
116496                 return v;
116497             }
116498           } // If the JSON object does not yet have a stringify method, give it one.
116499
116500
116501           if (typeof JSON.stringify !== "function") {
116502             meta = {
116503               // table of character substitutions
116504               "\b": "\\b",
116505               "\t": "\\t",
116506               "\n": "\\n",
116507               "\f": "\\f",
116508               "\r": "\\r",
116509               "\"": "\\\"",
116510               "\\": "\\\\"
116511             };
116512
116513             JSON.stringify = function (value, replacer, space) {
116514               // The stringify method takes a value and an optional replacer, and an optional
116515               // space parameter, and returns a JSON text. The replacer can be a function
116516               // that can replace values, or an array of strings that will select the keys.
116517               // A default replacer method can be provided. Use of the space parameter can
116518               // produce text that is more easily readable.
116519               var i;
116520               gap = "";
116521               indent = ""; // If the space parameter is a number, make an indent string containing that
116522               // many spaces.
116523
116524               if (typeof space === "number") {
116525                 for (i = 0; i < space; i += 1) {
116526                   indent += " ";
116527                 } // If the space parameter is a string, it will be used as the indent string.
116528
116529               } else if (typeof space === "string") {
116530                 indent = space;
116531               } // If there is a replacer, it must be a function or an array.
116532               // Otherwise, throw an error.
116533
116534
116535               rep = replacer;
116536
116537               if (replacer && typeof replacer !== "function" && (_typeof(replacer) !== "object" || typeof replacer.length !== "number")) {
116538                 throw new Error("JSON.stringify");
116539               } // Make a fake root object containing our value under the key of "".
116540               // Return the result of stringifying the value.
116541
116542
116543               return str("", {
116544                 "": value
116545               });
116546             };
116547           } // If the JSON object does not yet have a parse method, give it one.
116548
116549
116550           if (typeof JSON.parse !== "function") {
116551             JSON.parse = function (text, reviver) {
116552               // The parse method takes a text and an optional reviver function, and returns
116553               // a JavaScript value if the text is a valid JSON text.
116554               var j;
116555
116556               function walk(holder, key) {
116557                 // The walk method is used to recursively walk the resulting structure so
116558                 // that modifications can be made.
116559                 var k;
116560                 var v;
116561                 var value = holder[key];
116562
116563                 if (value && _typeof(value) === "object") {
116564                   for (k in value) {
116565                     if (Object.prototype.hasOwnProperty.call(value, k)) {
116566                       v = walk(value, k);
116567
116568                       if (v !== undefined) {
116569                         value[k] = v;
116570                       } else {
116571                         delete value[k];
116572                       }
116573                     }
116574                   }
116575                 }
116576
116577                 return reviver.call(holder, key, value);
116578               } // Parsing happens in four stages. In the first stage, we replace certain
116579               // Unicode characters with escape sequences. JavaScript handles many characters
116580               // incorrectly, either silently deleting them, or treating them as line endings.
116581
116582
116583               text = String(text);
116584               rx_dangerous.lastIndex = 0;
116585
116586               if (rx_dangerous.test(text)) {
116587                 text = text.replace(rx_dangerous, function (a) {
116588                   return "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
116589                 });
116590               } // In the second stage, we run the text against regular expressions that look
116591               // for non-JSON patterns. We are especially concerned with "()" and "new"
116592               // because they can cause invocation, and "=" because it can cause mutation.
116593               // But just to be safe, we want to reject all unexpected forms.
116594               // We split the second stage into 4 regexp operations in order to work around
116595               // crippling inefficiencies in IE's and Safari's regexp engines. First we
116596               // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
116597               // replace all simple value tokens with "]" characters. Third, we delete all
116598               // open brackets that follow a colon or comma or that begin the text. Finally,
116599               // we look to see that the remaining characters are only whitespace or "]" or
116600               // "," or ":" or "{" or "}". If that is so, then the text is safe for eval.
116601
116602
116603               if (rx_one.test(text.replace(rx_two, "@").replace(rx_three, "]").replace(rx_four, ""))) {
116604                 // In the third stage we use the eval function to compile the text into a
116605                 // JavaScript structure. The "{" operator is subject to a syntactic ambiguity
116606                 // in JavaScript: it can begin a block or an object literal. We wrap the text
116607                 // in parens to eliminate the ambiguity.
116608                 j = eval("(" + text + ")"); // In the optional fourth stage, we recursively walk the new structure, passing
116609                 // each name/value pair to a reviver function for possible transformation.
116610
116611                 return typeof reviver === "function" ? walk({
116612                   "": j
116613                 }, "") : j;
116614               } // If the text is not JSON parseable, then a SyntaxError is thrown.
116615
116616
116617               throw new SyntaxError("JSON.parse");
116618             };
116619           }
116620         })();
116621
116622         var json2 = json2Plugin;
116623
116624         function json2Plugin() {
116625           return {};
116626         }
116627
116628         var engine = storeEngine;
116629         var storages = all;
116630         var plugins = [json2];
116631         var store_legacy = engine.createStore(storages, plugins);
116632
116633         var immutable = extend;
116634         var hasOwnProperty = Object.prototype.hasOwnProperty;
116635
116636         function extend() {
116637           var target = {};
116638
116639           for (var i = 0; i < arguments.length; i++) {
116640             var source = arguments[i];
116641
116642             for (var key in source) {
116643               if (hasOwnProperty.call(source, key)) {
116644                 target[key] = source[key];
116645               }
116646             }
116647           }
116648
116649           return target;
116650         }
116651
116652         var ohauth = ohauth_1;
116653         var resolveUrl = resolveUrl$1.exports;
116654         var store = store_legacy;
116655         var xtend = immutable; // # osm-auth
116656         //
116657         // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
116658         // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
116659         // does not support custom headers, which this uses everywhere.
116660
116661         var osmAuth = function osmAuth(o) {
116662           var oauth = {}; // authenticated users will also have a request token secret, but it's
116663           // not used in transactions with the server
116664
116665           oauth.authenticated = function () {
116666             return !!(token('oauth_token') && token('oauth_token_secret'));
116667           };
116668
116669           oauth.logout = function () {
116670             token('oauth_token', '');
116671             token('oauth_token_secret', '');
116672             token('oauth_request_token_secret', '');
116673             return oauth;
116674           }; // TODO: detect lack of click event
116675
116676
116677           oauth.authenticate = function (callback) {
116678             if (oauth.authenticated()) return callback();
116679             oauth.logout(); // ## Getting a request token
116680
116681             var params = timenonce(getAuth(o)),
116682                 url = o.url + '/oauth/request_token';
116683             params.oauth_signature = ohauth.signature(o.oauth_secret, '', ohauth.baseString('POST', url, params));
116684
116685             if (!o.singlepage) {
116686               // Create a 600x550 popup window in the center of the screen
116687               var w = 600,
116688                   h = 550,
116689                   settings = [['width', w], ['height', h], ['left', screen.width / 2 - w / 2], ['top', screen.height / 2 - h / 2]].map(function (x) {
116690                 return x.join('=');
116691               }).join(','),
116692                   popup = window.open('about:blank', 'oauth_window', settings);
116693               oauth.popupWindow = popup;
116694
116695               if (!popup) {
116696                 var error = new Error('Popup was blocked');
116697                 error.status = 'popup-blocked';
116698                 throw error;
116699               }
116700             } // Request a request token. When this is complete, the popup
116701             // window is redirected to OSM's authorization page.
116702
116703
116704             ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
116705             o.loading();
116706
116707             function reqTokenDone(err, xhr) {
116708               o.done();
116709               if (err) return callback(err);
116710               var resp = ohauth.stringQs(xhr.response);
116711               token('oauth_request_token_secret', resp.oauth_token_secret);
116712               var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
116713                 oauth_token: resp.oauth_token,
116714                 oauth_callback: resolveUrl(o.landing)
116715               });
116716
116717               if (o.singlepage) {
116718                 location.href = authorize_url;
116719               } else {
116720                 popup.location = authorize_url;
116721               }
116722             } // Called by a function in a landing page, in the popup window. The
116723             // window closes itself.
116724
116725
116726             window.authComplete = function (token) {
116727               var oauth_token = ohauth.stringQs(token.split('?')[1]);
116728               get_access_token(oauth_token.oauth_token);
116729               delete window.authComplete;
116730             }; // ## Getting an request token
116731             //
116732             // At this point we have an `oauth_token`, brought in from a function
116733             // call on a landing page popup.
116734
116735
116736             function get_access_token(oauth_token) {
116737               var url = o.url + '/oauth/access_token',
116738                   params = timenonce(getAuth(o)),
116739                   request_token_secret = token('oauth_request_token_secret');
116740               params.oauth_token = oauth_token;
116741               params.oauth_signature = ohauth.signature(o.oauth_secret, request_token_secret, ohauth.baseString('POST', url, params)); // ## Getting an access token
116742               //
116743               // The final token required for authentication. At this point
116744               // we have a `request token secret`
116745
116746               ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
116747               o.loading();
116748             }
116749
116750             function accessTokenDone(err, xhr) {
116751               o.done();
116752               if (err) return callback(err);
116753               var access_token = ohauth.stringQs(xhr.response);
116754               token('oauth_token', access_token.oauth_token);
116755               token('oauth_token_secret', access_token.oauth_token_secret);
116756               callback(null, oauth);
116757             }
116758           };
116759
116760           oauth.bringPopupWindowToFront = function () {
116761             var brougtPopupToFront = false;
116762
116763             try {
116764               // This may cause a cross-origin error:
116765               // `DOMException: Blocked a frame with origin "..." from accessing a cross-origin frame.`
116766               if (oauth.popupWindow && !oauth.popupWindow.closed) {
116767                 oauth.popupWindow.focus();
116768                 brougtPopupToFront = true;
116769               }
116770             } catch (err) {// Bringing popup window to front failed (probably because of the cross-origin error mentioned above)
116771             }
116772
116773             return brougtPopupToFront;
116774           };
116775
116776           oauth.bootstrapToken = function (oauth_token, callback) {
116777             // ## Getting an request token
116778             // At this point we have an `oauth_token`, brought in from a function
116779             // call on a landing page popup.
116780             function get_access_token(oauth_token) {
116781               var url = o.url + '/oauth/access_token',
116782                   params = timenonce(getAuth(o)),
116783                   request_token_secret = token('oauth_request_token_secret');
116784               params.oauth_token = oauth_token;
116785               params.oauth_signature = ohauth.signature(o.oauth_secret, request_token_secret, ohauth.baseString('POST', url, params)); // ## Getting an access token
116786               // The final token required for authentication. At this point
116787               // we have a `request token secret`
116788
116789               ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
116790               o.loading();
116791             }
116792
116793             function accessTokenDone(err, xhr) {
116794               o.done();
116795               if (err) return callback(err);
116796               var access_token = ohauth.stringQs(xhr.response);
116797               token('oauth_token', access_token.oauth_token);
116798               token('oauth_token_secret', access_token.oauth_token_secret);
116799               callback(null, oauth);
116800             }
116801
116802             get_access_token(oauth_token);
116803           }; // # xhr
116804           //
116805           // A single XMLHttpRequest wrapper that does authenticated calls if the
116806           // user has logged in.
116807
116808
116809           oauth.xhr = function (options, callback) {
116810             if (!oauth.authenticated()) {
116811               if (o.auto) {
116812                 return oauth.authenticate(run);
116813               } else {
116814                 callback('not authenticated', null);
116815                 return;
116816               }
116817             } else {
116818               return run();
116819             }
116820
116821             function run() {
116822               var params = timenonce(getAuth(o)),
116823                   oauth_token_secret = token('oauth_token_secret'),
116824                   url = options.prefix !== false ? o.url + options.path : options.path,
116825                   url_parts = url.replace(/#.*$/, '').split('?', 2),
116826                   base_url = url_parts[0],
116827                   query = url_parts.length === 2 ? url_parts[1] : ''; // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
116828
116829               if ((!options.options || !options.options.header || options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') && options.content) {
116830                 params = xtend(params, ohauth.stringQs(options.content));
116831               }
116832
116833               params.oauth_token = token('oauth_token');
116834               params.oauth_signature = ohauth.signature(o.oauth_secret, oauth_token_secret, ohauth.baseString(options.method, base_url, xtend(params, ohauth.stringQs(query))));
116835               return ohauth.xhr(options.method, url, params, options.content, options.options, done);
116836             }
116837
116838             function done(err, xhr) {
116839               if (err) return callback(err);else if (xhr.responseXML) return callback(err, xhr.responseXML);else return callback(err, xhr.response);
116840             }
116841           }; // pre-authorize this object, if we can just get a token and token_secret
116842           // from the start
116843
116844
116845           oauth.preauth = function (c) {
116846             if (!c) return;
116847             if (c.oauth_token) token('oauth_token', c.oauth_token);
116848             if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
116849             return oauth;
116850           };
116851
116852           oauth.options = function (_) {
116853             if (!arguments.length) return o;
116854             o = _;
116855             o.url = o.url || 'https://www.openstreetmap.org';
116856             o.landing = o.landing || 'land.html';
116857             o.singlepage = o.singlepage || false; // Optional loading and loading-done functions for nice UI feedback.
116858             // by default, no-ops
116859
116860             o.loading = o.loading || function () {};
116861
116862             o.done = o.done || function () {};
116863
116864             return oauth.preauth(o);
116865           }; // 'stamp' an authentication object from `getAuth()`
116866           // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
116867           // and timestamp
116868
116869
116870           function timenonce(o) {
116871             o.oauth_timestamp = ohauth.timestamp();
116872             o.oauth_nonce = ohauth.nonce();
116873             return o;
116874           } // get/set tokens. These are prefixed with the base URL so that `osm-auth`
116875           // can be used with multiple APIs and the keys in `localStorage`
116876           // will not clash
116877
116878
116879           var token;
116880
116881           if (store.enabled) {
116882             token = function token(x, y) {
116883               if (arguments.length === 1) return store.get(o.url + x);else if (arguments.length === 2) return store.set(o.url + x, y);
116884             };
116885           } else {
116886             var storage = {};
116887
116888             token = function token(x, y) {
116889               if (arguments.length === 1) return storage[o.url + x];else if (arguments.length === 2) return storage[o.url + x] = y;
116890             };
116891           } // Get an authentication object. If you just add and remove properties
116892           // from a single object, you'll need to use `delete` to make sure that
116893           // it doesn't contain undesired properties for authentication
116894
116895
116896           function getAuth(o) {
116897             return {
116898               oauth_consumer_key: o.oauth_consumer_key,
116899               oauth_signature_method: 'HMAC-SHA1'
116900             };
116901           } // potentially pre-authorize
116902
116903
116904           oauth.options(o);
116905           return oauth;
116906         };
116907
116908         var tiler$2 = utilTiler();
116909         var dispatch$2 = dispatch$8('apiStatusChange', 'authLoading', 'authDone', 'change', 'loading', 'loaded', 'loadedNotes');
116910         var urlroot = 'https://www.openstreetmap.org';
116911         var oauth = osmAuth({
116912           url: urlroot,
116913           oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
116914           oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
116915           loading: authLoading,
116916           done: authDone
116917         }); // hardcode default block of Google Maps
116918
116919         var _imageryBlocklists = [/.*\.google(apis)?\..*\/(vt|kh)[\?\/].*([xyz]=.*){3}.*/];
116920         var _tileCache = {
116921           toLoad: {},
116922           loaded: {},
116923           inflight: {},
116924           seen: {},
116925           rtree: new RBush()
116926         };
116927         var _noteCache = {
116928           toLoad: {},
116929           loaded: {},
116930           inflight: {},
116931           inflightPost: {},
116932           note: {},
116933           closed: {},
116934           rtree: new RBush()
116935         };
116936         var _userCache = {
116937           toLoad: {},
116938           user: {}
116939         };
116940
116941         var _cachedApiStatus;
116942
116943         var _changeset = {};
116944
116945         var _deferred = new Set();
116946
116947         var _connectionID = 1;
116948         var _tileZoom = 16;
116949         var _noteZoom = 12;
116950
116951         var _rateLimitError;
116952
116953         var _userChangesets;
116954
116955         var _userDetails;
116956
116957         var _off; // set a default but also load this from the API status
116958
116959
116960         var _maxWayNodes = 2000;
116961
116962         function authLoading() {
116963           dispatch$2.call('authLoading');
116964         }
116965
116966         function authDone() {
116967           dispatch$2.call('authDone');
116968         }
116969
116970         function abortRequest$2(controllerOrXHR) {
116971           if (controllerOrXHR) {
116972             controllerOrXHR.abort();
116973           }
116974         }
116975
116976         function hasInflightRequests(cache) {
116977           return Object.keys(cache.inflight).length;
116978         }
116979
116980         function abortUnwantedRequests(cache, visibleTiles) {
116981           Object.keys(cache.inflight).forEach(function (k) {
116982             if (cache.toLoad[k]) return;
116983             if (visibleTiles.find(function (tile) {
116984               return k === tile.id;
116985             })) return;
116986             abortRequest$2(cache.inflight[k]);
116987             delete cache.inflight[k];
116988           });
116989         }
116990
116991         function getLoc(attrs) {
116992           var lon = attrs.lon && attrs.lon.value;
116993           var lat = attrs.lat && attrs.lat.value;
116994           return [parseFloat(lon), parseFloat(lat)];
116995         }
116996
116997         function getNodes(obj) {
116998           var elems = obj.getElementsByTagName('nd');
116999           var nodes = new Array(elems.length);
117000
117001           for (var i = 0, l = elems.length; i < l; i++) {
117002             nodes[i] = 'n' + elems[i].attributes.ref.value;
117003           }
117004
117005           return nodes;
117006         }
117007
117008         function getNodesJSON(obj) {
117009           var elems = obj.nodes;
117010           var nodes = new Array(elems.length);
117011
117012           for (var i = 0, l = elems.length; i < l; i++) {
117013             nodes[i] = 'n' + elems[i];
117014           }
117015
117016           return nodes;
117017         }
117018
117019         function getTags(obj) {
117020           var elems = obj.getElementsByTagName('tag');
117021           var tags = {};
117022
117023           for (var i = 0, l = elems.length; i < l; i++) {
117024             var attrs = elems[i].attributes;
117025             tags[attrs.k.value] = attrs.v.value;
117026           }
117027
117028           return tags;
117029         }
117030
117031         function getMembers(obj) {
117032           var elems = obj.getElementsByTagName('member');
117033           var members = new Array(elems.length);
117034
117035           for (var i = 0, l = elems.length; i < l; i++) {
117036             var attrs = elems[i].attributes;
117037             members[i] = {
117038               id: attrs.type.value[0] + attrs.ref.value,
117039               type: attrs.type.value,
117040               role: attrs.role.value
117041             };
117042           }
117043
117044           return members;
117045         }
117046
117047         function getMembersJSON(obj) {
117048           var elems = obj.members;
117049           var members = new Array(elems.length);
117050
117051           for (var i = 0, l = elems.length; i < l; i++) {
117052             var attrs = elems[i];
117053             members[i] = {
117054               id: attrs.type[0] + attrs.ref,
117055               type: attrs.type,
117056               role: attrs.role
117057             };
117058           }
117059
117060           return members;
117061         }
117062
117063         function getVisible(attrs) {
117064           return !attrs.visible || attrs.visible.value !== 'false';
117065         }
117066
117067         function parseComments(comments) {
117068           var parsedComments = []; // for each comment
117069
117070           for (var i = 0; i < comments.length; i++) {
117071             var comment = comments[i];
117072
117073             if (comment.nodeName === 'comment') {
117074               var childNodes = comment.childNodes;
117075               var parsedComment = {};
117076
117077               for (var j = 0; j < childNodes.length; j++) {
117078                 var node = childNodes[j];
117079                 var nodeName = node.nodeName;
117080                 if (nodeName === '#text') continue;
117081                 parsedComment[nodeName] = node.textContent;
117082
117083                 if (nodeName === 'uid') {
117084                   var uid = node.textContent;
117085
117086                   if (uid && !_userCache.user[uid]) {
117087                     _userCache.toLoad[uid] = true;
117088                   }
117089                 }
117090               }
117091
117092               if (parsedComment) {
117093                 parsedComments.push(parsedComment);
117094               }
117095             }
117096           }
117097
117098           return parsedComments;
117099         }
117100
117101         function encodeNoteRtree(note) {
117102           return {
117103             minX: note.loc[0],
117104             minY: note.loc[1],
117105             maxX: note.loc[0],
117106             maxY: note.loc[1],
117107             data: note
117108           };
117109         }
117110
117111         var jsonparsers = {
117112           node: function nodeData(obj, uid) {
117113             return new osmNode({
117114               id: uid,
117115               visible: typeof obj.visible === 'boolean' ? obj.visible : true,
117116               version: obj.version && obj.version.toString(),
117117               changeset: obj.changeset && obj.changeset.toString(),
117118               timestamp: obj.timestamp,
117119               user: obj.user,
117120               uid: obj.uid && obj.uid.toString(),
117121               loc: [parseFloat(obj.lon), parseFloat(obj.lat)],
117122               tags: obj.tags
117123             });
117124           },
117125           way: function wayData(obj, uid) {
117126             return new osmWay({
117127               id: uid,
117128               visible: typeof obj.visible === 'boolean' ? obj.visible : true,
117129               version: obj.version && obj.version.toString(),
117130               changeset: obj.changeset && obj.changeset.toString(),
117131               timestamp: obj.timestamp,
117132               user: obj.user,
117133               uid: obj.uid && obj.uid.toString(),
117134               tags: obj.tags,
117135               nodes: getNodesJSON(obj)
117136             });
117137           },
117138           relation: function relationData(obj, uid) {
117139             return new osmRelation({
117140               id: uid,
117141               visible: typeof obj.visible === 'boolean' ? obj.visible : true,
117142               version: obj.version && obj.version.toString(),
117143               changeset: obj.changeset && obj.changeset.toString(),
117144               timestamp: obj.timestamp,
117145               user: obj.user,
117146               uid: obj.uid && obj.uid.toString(),
117147               tags: obj.tags,
117148               members: getMembersJSON(obj)
117149             });
117150           },
117151           user: function parseUser(obj, uid) {
117152             return {
117153               id: uid,
117154               display_name: obj.display_name,
117155               account_created: obj.account_created,
117156               image_url: obj.img && obj.img.href,
117157               changesets_count: obj.changesets && obj.changesets.count && obj.changesets.count.toString() || '0',
117158               active_blocks: obj.blocks && obj.blocks.received && obj.blocks.received.active && obj.blocks.received.active.toString() || '0'
117159             };
117160           }
117161         };
117162
117163         function parseJSON(payload, callback, options) {
117164           options = Object.assign({
117165             skipSeen: true
117166           }, options);
117167
117168           if (!payload) {
117169             return callback({
117170               message: 'No JSON',
117171               status: -1
117172             });
117173           }
117174
117175           var json = payload;
117176           if (_typeof(json) !== 'object') json = JSON.parse(payload);
117177           if (!json.elements) return callback({
117178             message: 'No JSON',
117179             status: -1
117180           });
117181           var children = json.elements;
117182           var handle = window.requestIdleCallback(function () {
117183             _deferred["delete"](handle);
117184
117185             var results = [];
117186             var result;
117187
117188             for (var i = 0; i < children.length; i++) {
117189               result = parseChild(children[i]);
117190               if (result) results.push(result);
117191             }
117192
117193             callback(null, results);
117194           });
117195
117196           _deferred.add(handle);
117197
117198           function parseChild(child) {
117199             var parser = jsonparsers[child.type];
117200             if (!parser) return null;
117201             var uid;
117202             uid = osmEntity.id.fromOSM(child.type, child.id);
117203
117204             if (options.skipSeen) {
117205               if (_tileCache.seen[uid]) return null; // avoid reparsing a "seen" entity
117206
117207               _tileCache.seen[uid] = true;
117208             }
117209
117210             return parser(child, uid);
117211           }
117212         }
117213
117214         function parseUserJSON(payload, callback, options) {
117215           options = Object.assign({
117216             skipSeen: true
117217           }, options);
117218
117219           if (!payload) {
117220             return callback({
117221               message: 'No JSON',
117222               status: -1
117223             });
117224           }
117225
117226           var json = payload;
117227           if (_typeof(json) !== 'object') json = JSON.parse(payload);
117228           if (!json.users && !json.user) return callback({
117229             message: 'No JSON',
117230             status: -1
117231           });
117232           var objs = json.users || [json];
117233           var handle = window.requestIdleCallback(function () {
117234             _deferred["delete"](handle);
117235
117236             var results = [];
117237             var result;
117238
117239             for (var i = 0; i < objs.length; i++) {
117240               result = parseObj(objs[i]);
117241               if (result) results.push(result);
117242             }
117243
117244             callback(null, results);
117245           });
117246
117247           _deferred.add(handle);
117248
117249           function parseObj(obj) {
117250             var uid = obj.user.id && obj.user.id.toString();
117251
117252             if (options.skipSeen && _userCache.user[uid]) {
117253               delete _userCache.toLoad[uid];
117254               return null;
117255             }
117256
117257             var user = jsonparsers.user(obj.user, uid);
117258             _userCache.user[uid] = user;
117259             delete _userCache.toLoad[uid];
117260             return user;
117261           }
117262         }
117263
117264         var parsers = {
117265           node: function nodeData(obj, uid) {
117266             var attrs = obj.attributes;
117267             return new osmNode({
117268               id: uid,
117269               visible: getVisible(attrs),
117270               version: attrs.version.value,
117271               changeset: attrs.changeset && attrs.changeset.value,
117272               timestamp: attrs.timestamp && attrs.timestamp.value,
117273               user: attrs.user && attrs.user.value,
117274               uid: attrs.uid && attrs.uid.value,
117275               loc: getLoc(attrs),
117276               tags: getTags(obj)
117277             });
117278           },
117279           way: function wayData(obj, uid) {
117280             var attrs = obj.attributes;
117281             return new osmWay({
117282               id: uid,
117283               visible: getVisible(attrs),
117284               version: attrs.version.value,
117285               changeset: attrs.changeset && attrs.changeset.value,
117286               timestamp: attrs.timestamp && attrs.timestamp.value,
117287               user: attrs.user && attrs.user.value,
117288               uid: attrs.uid && attrs.uid.value,
117289               tags: getTags(obj),
117290               nodes: getNodes(obj)
117291             });
117292           },
117293           relation: function relationData(obj, uid) {
117294             var attrs = obj.attributes;
117295             return new osmRelation({
117296               id: uid,
117297               visible: getVisible(attrs),
117298               version: attrs.version.value,
117299               changeset: attrs.changeset && attrs.changeset.value,
117300               timestamp: attrs.timestamp && attrs.timestamp.value,
117301               user: attrs.user && attrs.user.value,
117302               uid: attrs.uid && attrs.uid.value,
117303               tags: getTags(obj),
117304               members: getMembers(obj)
117305             });
117306           },
117307           note: function parseNote(obj, uid) {
117308             var attrs = obj.attributes;
117309             var childNodes = obj.childNodes;
117310             var props = {};
117311             props.id = uid;
117312             props.loc = getLoc(attrs); // if notes are coincident, move them apart slightly
117313
117314             var coincident = false;
117315             var epsilon = 0.00001;
117316
117317             do {
117318               if (coincident) {
117319                 props.loc = geoVecAdd(props.loc, [epsilon, epsilon]);
117320               }
117321
117322               var bbox = geoExtent(props.loc).bbox();
117323               coincident = _noteCache.rtree.search(bbox).length;
117324             } while (coincident); // parse note contents
117325
117326
117327             for (var i = 0; i < childNodes.length; i++) {
117328               var node = childNodes[i];
117329               var nodeName = node.nodeName;
117330               if (nodeName === '#text') continue; // if the element is comments, parse the comments
117331
117332               if (nodeName === 'comments') {
117333                 props[nodeName] = parseComments(node.childNodes);
117334               } else {
117335                 props[nodeName] = node.textContent;
117336               }
117337             }
117338
117339             var note = new osmNote(props);
117340             var item = encodeNoteRtree(note);
117341             _noteCache.note[note.id] = note;
117342
117343             _noteCache.rtree.insert(item);
117344
117345             return note;
117346           },
117347           user: function parseUser(obj, uid) {
117348             var attrs = obj.attributes;
117349             var user = {
117350               id: uid,
117351               display_name: attrs.display_name && attrs.display_name.value,
117352               account_created: attrs.account_created && attrs.account_created.value,
117353               changesets_count: '0',
117354               active_blocks: '0'
117355             };
117356             var img = obj.getElementsByTagName('img');
117357
117358             if (img && img[0] && img[0].getAttribute('href')) {
117359               user.image_url = img[0].getAttribute('href');
117360             }
117361
117362             var changesets = obj.getElementsByTagName('changesets');
117363
117364             if (changesets && changesets[0] && changesets[0].getAttribute('count')) {
117365               user.changesets_count = changesets[0].getAttribute('count');
117366             }
117367
117368             var blocks = obj.getElementsByTagName('blocks');
117369
117370             if (blocks && blocks[0]) {
117371               var received = blocks[0].getElementsByTagName('received');
117372
117373               if (received && received[0] && received[0].getAttribute('active')) {
117374                 user.active_blocks = received[0].getAttribute('active');
117375               }
117376             }
117377
117378             _userCache.user[uid] = user;
117379             delete _userCache.toLoad[uid];
117380             return user;
117381           }
117382         };
117383
117384         function parseXML(xml, callback, options) {
117385           options = Object.assign({
117386             skipSeen: true
117387           }, options);
117388
117389           if (!xml || !xml.childNodes) {
117390             return callback({
117391               message: 'No XML',
117392               status: -1
117393             });
117394           }
117395
117396           var root = xml.childNodes[0];
117397           var children = root.childNodes;
117398           var handle = window.requestIdleCallback(function () {
117399             _deferred["delete"](handle);
117400
117401             var results = [];
117402             var result;
117403
117404             for (var i = 0; i < children.length; i++) {
117405               result = parseChild(children[i]);
117406               if (result) results.push(result);
117407             }
117408
117409             callback(null, results);
117410           });
117411
117412           _deferred.add(handle);
117413
117414           function parseChild(child) {
117415             var parser = parsers[child.nodeName];
117416             if (!parser) return null;
117417             var uid;
117418
117419             if (child.nodeName === 'user') {
117420               uid = child.attributes.id.value;
117421
117422               if (options.skipSeen && _userCache.user[uid]) {
117423                 delete _userCache.toLoad[uid];
117424                 return null;
117425               }
117426             } else if (child.nodeName === 'note') {
117427               uid = child.getElementsByTagName('id')[0].textContent;
117428             } else {
117429               uid = osmEntity.id.fromOSM(child.nodeName, child.attributes.id.value);
117430
117431               if (options.skipSeen) {
117432                 if (_tileCache.seen[uid]) return null; // avoid reparsing a "seen" entity
117433
117434                 _tileCache.seen[uid] = true;
117435               }
117436             }
117437
117438             return parser(child, uid);
117439           }
117440         } // replace or remove note from rtree
117441
117442
117443         function updateRtree(item, replace) {
117444           _noteCache.rtree.remove(item, function isEql(a, b) {
117445             return a.data.id === b.data.id;
117446           });
117447
117448           if (replace) {
117449             _noteCache.rtree.insert(item);
117450           }
117451         }
117452
117453         function wrapcb(thisArg, callback, cid) {
117454           return function (err, result) {
117455             if (err) {
117456               // 400 Bad Request, 401 Unauthorized, 403 Forbidden..
117457               if (err.status === 400 || err.status === 401 || err.status === 403) {
117458                 thisArg.logout();
117459               }
117460
117461               return callback.call(thisArg, err);
117462             } else if (thisArg.getConnectionId() !== cid) {
117463               return callback.call(thisArg, {
117464                 message: 'Connection Switched',
117465                 status: -1
117466               });
117467             } else {
117468               return callback.call(thisArg, err, result);
117469             }
117470           };
117471         }
117472
117473         var serviceOsm = {
117474           init: function init() {
117475             utilRebind(this, dispatch$2, 'on');
117476           },
117477           reset: function reset() {
117478             Array.from(_deferred).forEach(function (handle) {
117479               window.cancelIdleCallback(handle);
117480
117481               _deferred["delete"](handle);
117482             });
117483             _connectionID++;
117484             _userChangesets = undefined;
117485             _userDetails = undefined;
117486             _rateLimitError = undefined;
117487             Object.values(_tileCache.inflight).forEach(abortRequest$2);
117488             Object.values(_noteCache.inflight).forEach(abortRequest$2);
117489             Object.values(_noteCache.inflightPost).forEach(abortRequest$2);
117490             if (_changeset.inflight) abortRequest$2(_changeset.inflight);
117491             _tileCache = {
117492               toLoad: {},
117493               loaded: {},
117494               inflight: {},
117495               seen: {},
117496               rtree: new RBush()
117497             };
117498             _noteCache = {
117499               toLoad: {},
117500               loaded: {},
117501               inflight: {},
117502               inflightPost: {},
117503               note: {},
117504               closed: {},
117505               rtree: new RBush()
117506             };
117507             _userCache = {
117508               toLoad: {},
117509               user: {}
117510             };
117511             _cachedApiStatus = undefined;
117512             _changeset = {};
117513             return this;
117514           },
117515           getConnectionId: function getConnectionId() {
117516             return _connectionID;
117517           },
117518           changesetURL: function changesetURL(changesetID) {
117519             return urlroot + '/changeset/' + changesetID;
117520           },
117521           changesetsURL: function changesetsURL(center, zoom) {
117522             var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
117523             return urlroot + '/history#map=' + Math.floor(zoom) + '/' + center[1].toFixed(precision) + '/' + center[0].toFixed(precision);
117524           },
117525           entityURL: function entityURL(entity) {
117526             return urlroot + '/' + entity.type + '/' + entity.osmId();
117527           },
117528           historyURL: function historyURL(entity) {
117529             return urlroot + '/' + entity.type + '/' + entity.osmId() + '/history';
117530           },
117531           userURL: function userURL(username) {
117532             return urlroot + '/user/' + encodeURIComponent(username);
117533           },
117534           noteURL: function noteURL(note) {
117535             return urlroot + '/note/' + note.id;
117536           },
117537           noteReportURL: function noteReportURL(note) {
117538             return urlroot + '/reports/new?reportable_type=Note&reportable_id=' + note.id;
117539           },
117540           // Generic method to load data from the OSM API
117541           // Can handle either auth or unauth calls.
117542           loadFromAPI: function loadFromAPI(path, callback, options) {
117543             options = Object.assign({
117544               skipSeen: true
117545             }, options);
117546             var that = this;
117547             var cid = _connectionID;
117548
117549             function done(err, payload) {
117550               if (that.getConnectionId() !== cid) {
117551                 if (callback) callback({
117552                   message: 'Connection Switched',
117553                   status: -1
117554                 });
117555                 return;
117556               }
117557
117558               var isAuthenticated = that.authenticated(); // 400 Bad Request, 401 Unauthorized, 403 Forbidden
117559               // Logout and retry the request..
117560
117561               if (isAuthenticated && err && err.status && (err.status === 400 || err.status === 401 || err.status === 403)) {
117562                 that.logout();
117563                 that.loadFromAPI(path, callback, options); // else, no retry..
117564               } else {
117565                 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
117566                 // Set the rateLimitError flag and trigger a warning..
117567                 if (!isAuthenticated && !_rateLimitError && err && err.status && (err.status === 509 || err.status === 429)) {
117568                   _rateLimitError = err;
117569                   dispatch$2.call('change');
117570                   that.reloadApiStatus();
117571                 } else if (err && _cachedApiStatus === 'online' || !err && _cachedApiStatus !== 'online') {
117572                   // If the response's error state doesn't match the status,
117573                   // it's likely we lost or gained the connection so reload the status
117574                   that.reloadApiStatus();
117575                 }
117576
117577                 if (callback) {
117578                   if (err) {
117579                     return callback(err);
117580                   } else {
117581                     if (path.indexOf('.json') !== -1) {
117582                       return parseJSON(payload, callback, options);
117583                     } else {
117584                       return parseXML(payload, callback, options);
117585                     }
117586                   }
117587                 }
117588               }
117589             }
117590
117591             if (this.authenticated()) {
117592               return oauth.xhr({
117593                 method: 'GET',
117594                 path: path
117595               }, done);
117596             } else {
117597               var url = urlroot + path;
117598               var controller = new AbortController();
117599               var fn;
117600
117601               if (path.indexOf('.json') !== -1) {
117602                 fn = d3_json;
117603               } else {
117604                 fn = d3_xml;
117605               }
117606
117607               fn(url, {
117608                 signal: controller.signal
117609               }).then(function (data) {
117610                 done(null, data);
117611               })["catch"](function (err) {
117612                 if (err.name === 'AbortError') return; // d3-fetch includes status in the error message,
117613                 // but we can't access the response itself
117614                 // https://github.com/d3/d3-fetch/issues/27
117615
117616                 var match = err.message.match(/^\d{3}/);
117617
117618                 if (match) {
117619                   done({
117620                     status: +match[0],
117621                     statusText: err.message
117622                   });
117623                 } else {
117624                   done(err.message);
117625                 }
117626               });
117627               return controller;
117628             }
117629           },
117630           // Load a single entity by id (ways and relations use the `/full` call to include
117631           // nodes and members). Parent relations are not included, see `loadEntityRelations`.
117632           // GET /api/0.6/node/#id
117633           // GET /api/0.6/[way|relation]/#id/full
117634           loadEntity: function loadEntity(id, callback) {
117635             var type = osmEntity.id.type(id);
117636             var osmID = osmEntity.id.toOSM(id);
117637             var options = {
117638               skipSeen: false
117639             };
117640             this.loadFromAPI('/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : '') + '.json', function (err, entities) {
117641               if (callback) callback(err, {
117642                 data: entities
117643               });
117644             }, options);
117645           },
117646           // Load a single entity with a specific version
117647           // GET /api/0.6/[node|way|relation]/#id/#version
117648           loadEntityVersion: function loadEntityVersion(id, version, callback) {
117649             var type = osmEntity.id.type(id);
117650             var osmID = osmEntity.id.toOSM(id);
117651             var options = {
117652               skipSeen: false
117653             };
117654             this.loadFromAPI('/api/0.6/' + type + '/' + osmID + '/' + version + '.json', function (err, entities) {
117655               if (callback) callback(err, {
117656                 data: entities
117657               });
117658             }, options);
117659           },
117660           // Load the relations of a single entity with the given.
117661           // GET /api/0.6/[node|way|relation]/#id/relations
117662           loadEntityRelations: function loadEntityRelations(id, callback) {
117663             var type = osmEntity.id.type(id);
117664             var osmID = osmEntity.id.toOSM(id);
117665             var options = {
117666               skipSeen: false
117667             };
117668             this.loadFromAPI('/api/0.6/' + type + '/' + osmID + '/relations.json', function (err, entities) {
117669               if (callback) callback(err, {
117670                 data: entities
117671               });
117672             }, options);
117673           },
117674           // Load multiple entities in chunks
117675           // (note: callback may be called multiple times)
117676           // Unlike `loadEntity`, child nodes and members are not fetched
117677           // GET /api/0.6/[nodes|ways|relations]?#parameters
117678           loadMultiple: function loadMultiple(ids, callback) {
117679             var that = this;
117680             var groups = utilArrayGroupBy(utilArrayUniq(ids), osmEntity.id.type);
117681             Object.keys(groups).forEach(function (k) {
117682               var type = k + 's'; // nodes, ways, relations
117683
117684               var osmIDs = groups[k].map(function (id) {
117685                 return osmEntity.id.toOSM(id);
117686               });
117687               var options = {
117688                 skipSeen: false
117689               };
117690               utilArrayChunk(osmIDs, 150).forEach(function (arr) {
117691                 that.loadFromAPI('/api/0.6/' + type + '.json?' + type + '=' + arr.join(), function (err, entities) {
117692                   if (callback) callback(err, {
117693                     data: entities
117694                   });
117695                 }, options);
117696               });
117697             });
117698           },
117699           // Create, upload, and close a changeset
117700           // PUT /api/0.6/changeset/create
117701           // POST /api/0.6/changeset/#id/upload
117702           // PUT /api/0.6/changeset/#id/close
117703           putChangeset: function putChangeset(changeset, changes, callback) {
117704             var cid = _connectionID;
117705
117706             if (_changeset.inflight) {
117707               return callback({
117708                 message: 'Changeset already inflight',
117709                 status: -2
117710               }, changeset);
117711             } else if (_changeset.open) {
117712               // reuse existing open changeset..
117713               return createdChangeset.call(this, null, _changeset.open);
117714             } else {
117715               // Open a new changeset..
117716               var options = {
117717                 method: 'PUT',
117718                 path: '/api/0.6/changeset/create',
117719                 options: {
117720                   header: {
117721                     'Content-Type': 'text/xml'
117722                   }
117723                 },
117724                 content: JXON.stringify(changeset.asJXON())
117725               };
117726               _changeset.inflight = oauth.xhr(options, wrapcb(this, createdChangeset, cid));
117727             }
117728
117729             function createdChangeset(err, changesetID) {
117730               _changeset.inflight = null;
117731
117732               if (err) {
117733                 return callback(err, changeset);
117734               }
117735
117736               _changeset.open = changesetID;
117737               changeset = changeset.update({
117738                 id: changesetID
117739               }); // Upload the changeset..
117740
117741               var options = {
117742                 method: 'POST',
117743                 path: '/api/0.6/changeset/' + changesetID + '/upload',
117744                 options: {
117745                   header: {
117746                     'Content-Type': 'text/xml'
117747                   }
117748                 },
117749                 content: JXON.stringify(changeset.osmChangeJXON(changes))
117750               };
117751               _changeset.inflight = oauth.xhr(options, wrapcb(this, uploadedChangeset, cid));
117752             }
117753
117754             function uploadedChangeset(err) {
117755               _changeset.inflight = null;
117756               if (err) return callback(err, changeset); // Upload was successful, safe to call the callback.
117757               // Add delay to allow for postgres replication #1646 #2678
117758
117759               window.setTimeout(function () {
117760                 callback(null, changeset);
117761               }, 2500);
117762               _changeset.open = null; // At this point, we don't really care if the connection was switched..
117763               // Only try to close the changeset if we're still talking to the same server.
117764
117765               if (this.getConnectionId() === cid) {
117766                 // Still attempt to close changeset, but ignore response because #2667
117767                 oauth.xhr({
117768                   method: 'PUT',
117769                   path: '/api/0.6/changeset/' + changeset.id + '/close',
117770                   options: {
117771                     header: {
117772                       'Content-Type': 'text/xml'
117773                     }
117774                   }
117775                 }, function () {
117776                   return true;
117777                 });
117778               }
117779             }
117780           },
117781           // Load multiple users in chunks
117782           // (note: callback may be called multiple times)
117783           // GET /api/0.6/users?users=#id1,#id2,...,#idn
117784           loadUsers: function loadUsers(uids, callback) {
117785             var toLoad = [];
117786             var cached = [];
117787             utilArrayUniq(uids).forEach(function (uid) {
117788               if (_userCache.user[uid]) {
117789                 delete _userCache.toLoad[uid];
117790                 cached.push(_userCache.user[uid]);
117791               } else {
117792                 toLoad.push(uid);
117793               }
117794             });
117795
117796             if (cached.length || !this.authenticated()) {
117797               callback(undefined, cached);
117798               if (!this.authenticated()) return; // require auth
117799             }
117800
117801             utilArrayChunk(toLoad, 150).forEach(function (arr) {
117802               oauth.xhr({
117803                 method: 'GET',
117804                 path: '/api/0.6/users.json?users=' + arr.join()
117805               }, wrapcb(this, done, _connectionID));
117806             }.bind(this));
117807
117808             function done(err, payload) {
117809               if (err) return callback(err);
117810               var options = {
117811                 skipSeen: true
117812               };
117813               return parseUserJSON(payload, function (err, results) {
117814                 if (err) return callback(err);
117815                 return callback(undefined, results);
117816               }, options);
117817             }
117818           },
117819           // Load a given user by id
117820           // GET /api/0.6/user/#id
117821           loadUser: function loadUser(uid, callback) {
117822             if (_userCache.user[uid] || !this.authenticated()) {
117823               // require auth
117824               delete _userCache.toLoad[uid];
117825               return callback(undefined, _userCache.user[uid]);
117826             }
117827
117828             oauth.xhr({
117829               method: 'GET',
117830               path: '/api/0.6/user/' + uid + '.json'
117831             }, wrapcb(this, done, _connectionID));
117832
117833             function done(err, payload) {
117834               if (err) return callback(err);
117835               var options = {
117836                 skipSeen: true
117837               };
117838               return parseUserJSON(payload, function (err, results) {
117839                 if (err) return callback(err);
117840                 return callback(undefined, results[0]);
117841               }, options);
117842             }
117843           },
117844           // Load the details of the logged-in user
117845           // GET /api/0.6/user/details
117846           userDetails: function userDetails(callback) {
117847             if (_userDetails) {
117848               // retrieve cached
117849               return callback(undefined, _userDetails);
117850             }
117851
117852             oauth.xhr({
117853               method: 'GET',
117854               path: '/api/0.6/user/details.json'
117855             }, wrapcb(this, done, _connectionID));
117856
117857             function done(err, payload) {
117858               if (err) return callback(err);
117859               var options = {
117860                 skipSeen: false
117861               };
117862               return parseUserJSON(payload, function (err, results) {
117863                 if (err) return callback(err);
117864                 _userDetails = results[0];
117865                 return callback(undefined, _userDetails);
117866               }, options);
117867             }
117868           },
117869           // Load previous changesets for the logged in user
117870           // GET /api/0.6/changesets?user=#id
117871           userChangesets: function userChangesets(callback) {
117872             if (_userChangesets) {
117873               // retrieve cached
117874               return callback(undefined, _userChangesets);
117875             }
117876
117877             this.userDetails(wrapcb(this, gotDetails, _connectionID));
117878
117879             function gotDetails(err, user) {
117880               if (err) {
117881                 return callback(err);
117882               }
117883
117884               oauth.xhr({
117885                 method: 'GET',
117886                 path: '/api/0.6/changesets?user=' + user.id
117887               }, wrapcb(this, done, _connectionID));
117888             }
117889
117890             function done(err, xml) {
117891               if (err) {
117892                 return callback(err);
117893               }
117894
117895               _userChangesets = Array.prototype.map.call(xml.getElementsByTagName('changeset'), function (changeset) {
117896                 return {
117897                   tags: getTags(changeset)
117898                 };
117899               }).filter(function (changeset) {
117900                 var comment = changeset.tags.comment;
117901                 return comment && comment !== '';
117902               });
117903               return callback(undefined, _userChangesets);
117904             }
117905           },
117906           // Fetch the status of the OSM API
117907           // GET /api/capabilities
117908           status: function status(callback) {
117909             var url = urlroot + '/api/capabilities';
117910             var errback = wrapcb(this, done, _connectionID);
117911             d3_xml(url).then(function (data) {
117912               errback(null, data);
117913             })["catch"](function (err) {
117914               errback(err.message);
117915             });
117916
117917             function done(err, xml) {
117918               if (err) {
117919                 // the status is null if no response could be retrieved
117920                 return callback(err, null);
117921               } // update blocklists
117922
117923
117924               var elements = xml.getElementsByTagName('blacklist');
117925               var regexes = [];
117926
117927               for (var i = 0; i < elements.length; i++) {
117928                 var regexString = elements[i].getAttribute('regex'); // needs unencode?
117929
117930                 if (regexString) {
117931                   try {
117932                     var regex = new RegExp(regexString);
117933                     regexes.push(regex);
117934                   } catch (e) {
117935                     /* noop */
117936                   }
117937                 }
117938               }
117939
117940               if (regexes.length) {
117941                 _imageryBlocklists = regexes;
117942               }
117943
117944               if (_rateLimitError) {
117945                 return callback(_rateLimitError, 'rateLimited');
117946               } else {
117947                 var waynodes = xml.getElementsByTagName('waynodes');
117948                 var maxWayNodes = waynodes.length && parseInt(waynodes[0].getAttribute('maximum'), 10);
117949                 if (maxWayNodes && isFinite(maxWayNodes)) _maxWayNodes = maxWayNodes;
117950                 var apiStatus = xml.getElementsByTagName('status');
117951                 var val = apiStatus[0].getAttribute('api');
117952                 return callback(undefined, val);
117953               }
117954             }
117955           },
117956           // Calls `status` and dispatches an `apiStatusChange` event if the returned
117957           // status differs from the cached status.
117958           reloadApiStatus: function reloadApiStatus() {
117959             // throttle to avoid unnecessary API calls
117960             if (!this.throttledReloadApiStatus) {
117961               var that = this;
117962               this.throttledReloadApiStatus = throttle(function () {
117963                 that.status(function (err, status) {
117964                   if (status !== _cachedApiStatus) {
117965                     _cachedApiStatus = status;
117966                     dispatch$2.call('apiStatusChange', that, err, status);
117967                   }
117968                 });
117969               }, 500);
117970             }
117971
117972             this.throttledReloadApiStatus();
117973           },
117974           // Returns the maximum number of nodes a single way can have
117975           maxWayNodes: function maxWayNodes() {
117976             return _maxWayNodes;
117977           },
117978           // Load data (entities) from the API in tiles
117979           // GET /api/0.6/map?bbox=
117980           loadTiles: function loadTiles(projection, callback) {
117981             if (_off) return; // determine the needed tiles to cover the view
117982
117983             var tiles = tiler$2.zoomExtent([_tileZoom, _tileZoom]).getTiles(projection); // abort inflight requests that are no longer needed
117984
117985             var hadRequests = hasInflightRequests(_tileCache);
117986             abortUnwantedRequests(_tileCache, tiles);
117987
117988             if (hadRequests && !hasInflightRequests(_tileCache)) {
117989               dispatch$2.call('loaded'); // stop the spinner
117990             } // issue new requests..
117991
117992
117993             tiles.forEach(function (tile) {
117994               this.loadTile(tile, callback);
117995             }, this);
117996           },
117997           // Load a single data tile
117998           // GET /api/0.6/map?bbox=
117999           loadTile: function loadTile(tile, callback) {
118000             if (_off) return;
118001             if (_tileCache.loaded[tile.id] || _tileCache.inflight[tile.id]) return;
118002
118003             if (!hasInflightRequests(_tileCache)) {
118004               dispatch$2.call('loading'); // start the spinner
118005             }
118006
118007             var path = '/api/0.6/map.json?bbox=';
118008             var options = {
118009               skipSeen: true
118010             };
118011             _tileCache.inflight[tile.id] = this.loadFromAPI(path + tile.extent.toParam(), tileCallback, options);
118012
118013             function tileCallback(err, parsed) {
118014               delete _tileCache.inflight[tile.id];
118015
118016               if (!err) {
118017                 delete _tileCache.toLoad[tile.id];
118018                 _tileCache.loaded[tile.id] = true;
118019                 var bbox = tile.extent.bbox();
118020                 bbox.id = tile.id;
118021
118022                 _tileCache.rtree.insert(bbox);
118023               }
118024
118025               if (callback) {
118026                 callback(err, Object.assign({
118027                   data: parsed
118028                 }, tile));
118029               }
118030
118031               if (!hasInflightRequests(_tileCache)) {
118032                 dispatch$2.call('loaded'); // stop the spinner
118033               }
118034             }
118035           },
118036           isDataLoaded: function isDataLoaded(loc) {
118037             var bbox = {
118038               minX: loc[0],
118039               minY: loc[1],
118040               maxX: loc[0],
118041               maxY: loc[1]
118042             };
118043             return _tileCache.rtree.collides(bbox);
118044           },
118045           // load the tile that covers the given `loc`
118046           loadTileAtLoc: function loadTileAtLoc(loc, callback) {
118047             // Back off if the toLoad queue is filling up.. re #6417
118048             // (Currently `loadTileAtLoc` requests are considered low priority - used by operations to
118049             // let users safely edit geometries which extend to unloaded tiles.  We can drop some.)
118050             if (Object.keys(_tileCache.toLoad).length > 50) return;
118051             var k = geoZoomToScale(_tileZoom + 1);
118052             var offset = geoRawMercator().scale(k)(loc);
118053             var projection = geoRawMercator().transform({
118054               k: k,
118055               x: -offset[0],
118056               y: -offset[1]
118057             });
118058             var tiles = tiler$2.zoomExtent([_tileZoom, _tileZoom]).getTiles(projection);
118059             tiles.forEach(function (tile) {
118060               if (_tileCache.toLoad[tile.id] || _tileCache.loaded[tile.id] || _tileCache.inflight[tile.id]) return;
118061               _tileCache.toLoad[tile.id] = true;
118062               this.loadTile(tile, callback);
118063             }, this);
118064           },
118065           // Load notes from the API in tiles
118066           // GET /api/0.6/notes?bbox=
118067           loadNotes: function loadNotes(projection, noteOptions) {
118068             noteOptions = Object.assign({
118069               limit: 10000,
118070               closed: 7
118071             }, noteOptions);
118072             if (_off) return;
118073             var that = this;
118074             var path = '/api/0.6/notes?limit=' + noteOptions.limit + '&closed=' + noteOptions.closed + '&bbox=';
118075
118076             var throttleLoadUsers = throttle(function () {
118077               var uids = Object.keys(_userCache.toLoad);
118078               if (!uids.length) return;
118079               that.loadUsers(uids, function () {}); // eagerly load user details
118080             }, 750); // determine the needed tiles to cover the view
118081
118082
118083             var tiles = tiler$2.zoomExtent([_noteZoom, _noteZoom]).getTiles(projection); // abort inflight requests that are no longer needed
118084
118085             abortUnwantedRequests(_noteCache, tiles); // issue new requests..
118086
118087             tiles.forEach(function (tile) {
118088               if (_noteCache.loaded[tile.id] || _noteCache.inflight[tile.id]) return;
118089               var options = {
118090                 skipSeen: false
118091               };
118092               _noteCache.inflight[tile.id] = that.loadFromAPI(path + tile.extent.toParam(), function (err) {
118093                 delete _noteCache.inflight[tile.id];
118094
118095                 if (!err) {
118096                   _noteCache.loaded[tile.id] = true;
118097                 }
118098
118099                 throttleLoadUsers();
118100                 dispatch$2.call('loadedNotes');
118101               }, options);
118102             });
118103           },
118104           // Create a note
118105           // POST /api/0.6/notes?params
118106           postNoteCreate: function postNoteCreate(note, callback) {
118107             if (!this.authenticated()) {
118108               return callback({
118109                 message: 'Not Authenticated',
118110                 status: -3
118111               }, note);
118112             }
118113
118114             if (_noteCache.inflightPost[note.id]) {
118115               return callback({
118116                 message: 'Note update already inflight',
118117                 status: -2
118118               }, note);
118119             }
118120
118121             if (!note.loc[0] || !note.loc[1] || !note.newComment) return; // location & description required
118122
118123             var comment = note.newComment;
118124
118125             if (note.newCategory && note.newCategory !== 'None') {
118126               comment += ' #' + note.newCategory;
118127             }
118128
118129             var path = '/api/0.6/notes?' + utilQsString({
118130               lon: note.loc[0],
118131               lat: note.loc[1],
118132               text: comment
118133             });
118134             _noteCache.inflightPost[note.id] = oauth.xhr({
118135               method: 'POST',
118136               path: path
118137             }, wrapcb(this, done, _connectionID));
118138
118139             function done(err, xml) {
118140               delete _noteCache.inflightPost[note.id];
118141
118142               if (err) {
118143                 return callback(err);
118144               } // we get the updated note back, remove from caches and reparse..
118145
118146
118147               this.removeNote(note);
118148               var options = {
118149                 skipSeen: false
118150               };
118151               return parseXML(xml, function (err, results) {
118152                 if (err) {
118153                   return callback(err);
118154                 } else {
118155                   return callback(undefined, results[0]);
118156                 }
118157               }, options);
118158             }
118159           },
118160           // Update a note
118161           // POST /api/0.6/notes/#id/comment?text=comment
118162           // POST /api/0.6/notes/#id/close?text=comment
118163           // POST /api/0.6/notes/#id/reopen?text=comment
118164           postNoteUpdate: function postNoteUpdate(note, newStatus, callback) {
118165             if (!this.authenticated()) {
118166               return callback({
118167                 message: 'Not Authenticated',
118168                 status: -3
118169               }, note);
118170             }
118171
118172             if (_noteCache.inflightPost[note.id]) {
118173               return callback({
118174                 message: 'Note update already inflight',
118175                 status: -2
118176               }, note);
118177             }
118178
118179             var action;
118180
118181             if (note.status !== 'closed' && newStatus === 'closed') {
118182               action = 'close';
118183             } else if (note.status !== 'open' && newStatus === 'open') {
118184               action = 'reopen';
118185             } else {
118186               action = 'comment';
118187               if (!note.newComment) return; // when commenting, comment required
118188             }
118189
118190             var path = '/api/0.6/notes/' + note.id + '/' + action;
118191
118192             if (note.newComment) {
118193               path += '?' + utilQsString({
118194                 text: note.newComment
118195               });
118196             }
118197
118198             _noteCache.inflightPost[note.id] = oauth.xhr({
118199               method: 'POST',
118200               path: path
118201             }, wrapcb(this, done, _connectionID));
118202
118203             function done(err, xml) {
118204               delete _noteCache.inflightPost[note.id];
118205
118206               if (err) {
118207                 return callback(err);
118208               } // we get the updated note back, remove from caches and reparse..
118209
118210
118211               this.removeNote(note); // update closed note cache - used to populate `closed:note` changeset tag
118212
118213               if (action === 'close') {
118214                 _noteCache.closed[note.id] = true;
118215               } else if (action === 'reopen') {
118216                 delete _noteCache.closed[note.id];
118217               }
118218
118219               var options = {
118220                 skipSeen: false
118221               };
118222               return parseXML(xml, function (err, results) {
118223                 if (err) {
118224                   return callback(err);
118225                 } else {
118226                   return callback(undefined, results[0]);
118227                 }
118228               }, options);
118229             }
118230           },
118231           "switch": function _switch(options) {
118232             urlroot = options.urlroot;
118233             oauth.options(Object.assign({
118234               url: urlroot,
118235               loading: authLoading,
118236               done: authDone
118237             }, options));
118238             this.reset();
118239             this.userChangesets(function () {}); // eagerly load user details/changesets
118240
118241             dispatch$2.call('change');
118242             return this;
118243           },
118244           toggle: function toggle(val) {
118245             _off = !val;
118246             return this;
118247           },
118248           isChangesetInflight: function isChangesetInflight() {
118249             return !!_changeset.inflight;
118250           },
118251           // get/set cached data
118252           // This is used to save/restore the state when entering/exiting the walkthrough
118253           // Also used for testing purposes.
118254           caches: function caches(obj) {
118255             function cloneCache(source) {
118256               var target = {};
118257               Object.keys(source).forEach(function (k) {
118258                 if (k === 'rtree') {
118259                   target.rtree = new RBush().fromJSON(source.rtree.toJSON()); // clone rbush
118260                 } else if (k === 'note') {
118261                   target.note = {};
118262                   Object.keys(source.note).forEach(function (id) {
118263                     target.note[id] = osmNote(source.note[id]); // copy notes
118264                   });
118265                 } else {
118266                   target[k] = JSON.parse(JSON.stringify(source[k])); // clone deep
118267                 }
118268               });
118269               return target;
118270             }
118271
118272             if (!arguments.length) {
118273               return {
118274                 tile: cloneCache(_tileCache),
118275                 note: cloneCache(_noteCache),
118276                 user: cloneCache(_userCache)
118277               };
118278             } // access caches directly for testing (e.g., loading notes rtree)
118279
118280
118281             if (obj === 'get') {
118282               return {
118283                 tile: _tileCache,
118284                 note: _noteCache,
118285                 user: _userCache
118286               };
118287             }
118288
118289             if (obj.tile) {
118290               _tileCache = obj.tile;
118291               _tileCache.inflight = {};
118292             }
118293
118294             if (obj.note) {
118295               _noteCache = obj.note;
118296               _noteCache.inflight = {};
118297               _noteCache.inflightPost = {};
118298             }
118299
118300             if (obj.user) {
118301               _userCache = obj.user;
118302             }
118303
118304             return this;
118305           },
118306           logout: function logout() {
118307             _userChangesets = undefined;
118308             _userDetails = undefined;
118309             oauth.logout();
118310             dispatch$2.call('change');
118311             return this;
118312           },
118313           authenticated: function authenticated() {
118314             return oauth.authenticated();
118315           },
118316           authenticate: function authenticate(callback) {
118317             var that = this;
118318             var cid = _connectionID;
118319             _userChangesets = undefined;
118320             _userDetails = undefined;
118321
118322             function done(err, res) {
118323               if (err) {
118324                 if (callback) callback(err);
118325                 return;
118326               }
118327
118328               if (that.getConnectionId() !== cid) {
118329                 if (callback) callback({
118330                   message: 'Connection Switched',
118331                   status: -1
118332                 });
118333                 return;
118334               }
118335
118336               _rateLimitError = undefined;
118337               dispatch$2.call('change');
118338               if (callback) callback(err, res);
118339               that.userChangesets(function () {}); // eagerly load user details/changesets
118340             }
118341
118342             return oauth.authenticate(done);
118343           },
118344           imageryBlocklists: function imageryBlocklists() {
118345             return _imageryBlocklists;
118346           },
118347           tileZoom: function tileZoom(val) {
118348             if (!arguments.length) return _tileZoom;
118349             _tileZoom = val;
118350             return this;
118351           },
118352           // get all cached notes covering the viewport
118353           notes: function notes(projection) {
118354             var viewport = projection.clipExtent();
118355             var min = [viewport[0][0], viewport[1][1]];
118356             var max = [viewport[1][0], viewport[0][1]];
118357             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
118358             return _noteCache.rtree.search(bbox).map(function (d) {
118359               return d.data;
118360             });
118361           },
118362           // get a single note from the cache
118363           getNote: function getNote(id) {
118364             return _noteCache.note[id];
118365           },
118366           // remove a single note from the cache
118367           removeNote: function removeNote(note) {
118368             if (!(note instanceof osmNote) || !note.id) return;
118369             delete _noteCache.note[note.id];
118370             updateRtree(encodeNoteRtree(note), false); // false = remove
118371           },
118372           // replace a single note in the cache
118373           replaceNote: function replaceNote(note) {
118374             if (!(note instanceof osmNote) || !note.id) return;
118375             _noteCache.note[note.id] = note;
118376             updateRtree(encodeNoteRtree(note), true); // true = replace
118377
118378             return note;
118379           },
118380           // Get an array of note IDs closed during this session.
118381           // Used to populate `closed:note` changeset tag
118382           getClosedIDs: function getClosedIDs() {
118383             return Object.keys(_noteCache.closed).sort();
118384           }
118385         };
118386
118387         var _apibase$1 = 'https://wiki.openstreetmap.org/w/api.php';
118388         var _inflight$1 = {};
118389         var _wikibaseCache = {};
118390         var _localeIDs = {
118391           en: false
118392         };
118393
118394         var debouncedRequest$1 = debounce(request$1, 500, {
118395           leading: false
118396         });
118397
118398         function request$1(url, callback) {
118399           if (_inflight$1[url]) return;
118400           var controller = new AbortController();
118401           _inflight$1[url] = controller;
118402           d3_json(url, {
118403             signal: controller.signal
118404           }).then(function (result) {
118405             delete _inflight$1[url];
118406             if (callback) callback(null, result);
118407           })["catch"](function (err) {
118408             delete _inflight$1[url];
118409             if (err.name === 'AbortError') return;
118410             if (callback) callback(err.message);
118411           });
118412         }
118413
118414         var serviceOsmWikibase = {
118415           init: function init() {
118416             _inflight$1 = {};
118417             _wikibaseCache = {};
118418             _localeIDs = {};
118419           },
118420           reset: function reset() {
118421             Object.values(_inflight$1).forEach(function (controller) {
118422               controller.abort();
118423             });
118424             _inflight$1 = {};
118425           },
118426
118427           /**
118428            * Get the best value for the property, or undefined if not found
118429            * @param entity object from wikibase
118430            * @param property string e.g. 'P4' for image
118431            * @param langCode string e.g. 'fr' for French
118432            */
118433           claimToValue: function claimToValue(entity, property, langCode) {
118434             if (!entity.claims[property]) return undefined;
118435             var locale = _localeIDs[langCode];
118436             var preferredPick, localePick;
118437             entity.claims[property].forEach(function (stmt) {
118438               // If exists, use value limited to the needed language (has a qualifier P26 = locale)
118439               // Or if not found, use the first value with the "preferred" rank
118440               if (!preferredPick && stmt.rank === 'preferred') {
118441                 preferredPick = stmt;
118442               }
118443
118444               if (locale && stmt.qualifiers && stmt.qualifiers.P26 && stmt.qualifiers.P26[0].datavalue.value.id === locale) {
118445                 localePick = stmt;
118446               }
118447             });
118448             var result = localePick || preferredPick;
118449
118450             if (result) {
118451               var datavalue = result.mainsnak.datavalue;
118452               return datavalue.type === 'wikibase-entityid' ? datavalue.value.id : datavalue.value;
118453             } else {
118454               return undefined;
118455             }
118456           },
118457
118458           /**
118459            * Convert monolingual property into a key-value object (language -> value)
118460            * @param entity object from wikibase
118461            * @param property string e.g. 'P31' for monolingual wiki page title
118462            */
118463           monolingualClaimToValueObj: function monolingualClaimToValueObj(entity, property) {
118464             if (!entity || !entity.claims[property]) return undefined;
118465             return entity.claims[property].reduce(function (acc, obj) {
118466               var value = obj.mainsnak.datavalue.value;
118467               acc[value.language] = value.text;
118468               return acc;
118469             }, {});
118470           },
118471           toSitelink: function toSitelink(key, value) {
118472             var result = value ? 'Tag:' + key + '=' + value : 'Key:' + key;
118473             return result.replace(/_/g, ' ').trim();
118474           },
118475           //
118476           // Pass params object of the form:
118477           // {
118478           //   key: 'string',
118479           //   value: 'string',
118480           //   langCode: 'string'
118481           // }
118482           //
118483           getEntity: function getEntity(params, callback) {
118484             var doRequest = params.debounce ? debouncedRequest$1 : request$1;
118485             var that = this;
118486             var titles = [];
118487             var result = {};
118488             var rtypeSitelink = params.key === 'type' && params.value ? ('Relation:' + params.value).replace(/_/g, ' ').trim() : false;
118489             var keySitelink = params.key ? this.toSitelink(params.key) : false;
118490             var tagSitelink = params.key && params.value ? this.toSitelink(params.key, params.value) : false;
118491             var localeSitelink;
118492
118493             if (params.langCodes) {
118494               params.langCodes.forEach(function (langCode) {
118495                 if (_localeIDs[langCode] === undefined) {
118496                   // If this is the first time we are asking about this locale,
118497                   // fetch corresponding entity (if it exists), and cache it.
118498                   // If there is no such entry, cache `false` value to avoid re-requesting it.
118499                   localeSitelink = ('Locale:' + langCode).replace(/_/g, ' ').trim();
118500                   titles.push(localeSitelink);
118501                 }
118502               });
118503             }
118504
118505             if (rtypeSitelink) {
118506               if (_wikibaseCache[rtypeSitelink]) {
118507                 result.rtype = _wikibaseCache[rtypeSitelink];
118508               } else {
118509                 titles.push(rtypeSitelink);
118510               }
118511             }
118512
118513             if (keySitelink) {
118514               if (_wikibaseCache[keySitelink]) {
118515                 result.key = _wikibaseCache[keySitelink];
118516               } else {
118517                 titles.push(keySitelink);
118518               }
118519             }
118520
118521             if (tagSitelink) {
118522               if (_wikibaseCache[tagSitelink]) {
118523                 result.tag = _wikibaseCache[tagSitelink];
118524               } else {
118525                 titles.push(tagSitelink);
118526               }
118527             }
118528
118529             if (!titles.length) {
118530               // Nothing to do, we already had everything in the cache
118531               return callback(null, result);
118532             } // Requesting just the user language code
118533             // If backend recognizes the code, it will perform proper fallbacks,
118534             // and the result will contain the requested code. If not, all values are returned:
118535             // {"zh-tw":{"value":"...","language":"zh-tw","source-language":"zh-hant"}
118536             // {"pt-br":{"value":"...","language":"pt","for-language":"pt-br"}}
118537
118538
118539             var obj = {
118540               action: 'wbgetentities',
118541               sites: 'wiki',
118542               titles: titles.join('|'),
118543               languages: params.langCodes.join('|'),
118544               languagefallback: 1,
118545               origin: '*',
118546               format: 'json' // There is an MW Wikibase API bug https://phabricator.wikimedia.org/T212069
118547               // We shouldn't use v1 until it gets fixed, but should switch to it afterwards
118548               // formatversion: 2,
118549
118550             };
118551             var url = _apibase$1 + '?' + utilQsString(obj);
118552             doRequest(url, function (err, d) {
118553               if (err) {
118554                 callback(err);
118555               } else if (!d.success || d.error) {
118556                 callback(d.error.messages.map(function (v) {
118557                   return v.html['*'];
118558                 }).join('<br>'));
118559               } else {
118560                 var localeID = false;
118561                 Object.values(d.entities).forEach(function (res) {
118562                   if (res.missing !== '') {
118563                     var title = res.sitelinks.wiki.title;
118564
118565                     if (title === rtypeSitelink) {
118566                       _wikibaseCache[rtypeSitelink] = res;
118567                       result.rtype = res;
118568                     } else if (title === keySitelink) {
118569                       _wikibaseCache[keySitelink] = res;
118570                       result.key = res;
118571                     } else if (title === tagSitelink) {
118572                       _wikibaseCache[tagSitelink] = res;
118573                       result.tag = res;
118574                     } else if (title === localeSitelink) {
118575                       localeID = res.id;
118576                     } else {
118577                       console.log('Unexpected title ' + title); // eslint-disable-line no-console
118578                     }
118579                   }
118580                 });
118581
118582                 if (localeSitelink) {
118583                   // If locale ID is not found, store false to prevent repeated queries
118584                   that.addLocale(params.langCodes[0], localeID);
118585                 }
118586
118587                 callback(null, result);
118588               }
118589             });
118590           },
118591           //
118592           // Pass params object of the form:
118593           // {
118594           //   key: 'string',     // required
118595           //   value: 'string'    // optional
118596           // }
118597           //
118598           // Get an result object used to display tag documentation
118599           // {
118600           //   title:        'string',
118601           //   description:  'string',
118602           //   editURL:      'string',
118603           //   imageURL:     'string',
118604           //   wiki:         { title: 'string', text: 'string', url: 'string' }
118605           // }
118606           //
118607           getDocs: function getDocs(params, callback) {
118608             var that = this;
118609             var langCodes = _mainLocalizer.localeCodes().map(function (code) {
118610               return code.toLowerCase();
118611             });
118612             params.langCodes = langCodes;
118613             this.getEntity(params, function (err, data) {
118614               if (err) {
118615                 callback(err);
118616                 return;
118617               }
118618
118619               var entity = data.rtype || data.tag || data.key;
118620
118621               if (!entity) {
118622                 callback('No entity');
118623                 return;
118624               }
118625
118626               var i;
118627               var description;
118628
118629               for (i in langCodes) {
118630                 var _code = langCodes[i];
118631
118632                 if (entity.descriptions[_code] && entity.descriptions[_code].language === _code) {
118633                   description = entity.descriptions[_code];
118634                   break;
118635                 }
118636               }
118637
118638               if (!description && Object.values(entity.descriptions).length) description = Object.values(entity.descriptions)[0]; // prepare result
118639
118640               var result = {
118641                 title: entity.title,
118642                 description: description ? description.value : '',
118643                 descriptionLocaleCode: description ? description.language : '',
118644                 editURL: 'https://wiki.openstreetmap.org/wiki/' + entity.title
118645               }; // add image
118646
118647               if (entity.claims) {
118648                 var imageroot;
118649                 var image = that.claimToValue(entity, 'P4', langCodes[0]);
118650
118651                 if (image) {
118652                   imageroot = 'https://commons.wikimedia.org/w/index.php';
118653                 } else {
118654                   image = that.claimToValue(entity, 'P28', langCodes[0]);
118655
118656                   if (image) {
118657                     imageroot = 'https://wiki.openstreetmap.org/w/index.php';
118658                   }
118659                 }
118660
118661                 if (imageroot && image) {
118662                   result.imageURL = imageroot + '?' + utilQsString({
118663                     title: 'Special:Redirect/file/' + image,
118664                     width: 400
118665                   });
118666                 }
118667               } // Try to get a wiki page from tag data item first, followed by the corresponding key data item.
118668               // If neither tag nor key data item contain a wiki page in the needed language nor English,
118669               // get the first found wiki page from either the tag or the key item.
118670
118671
118672               var rtypeWiki = that.monolingualClaimToValueObj(data.rtype, 'P31');
118673               var tagWiki = that.monolingualClaimToValueObj(data.tag, 'P31');
118674               var keyWiki = that.monolingualClaimToValueObj(data.key, 'P31');
118675               var wikis = [rtypeWiki, tagWiki, keyWiki];
118676
118677               for (i in wikis) {
118678                 var wiki = wikis[i];
118679
118680                 for (var j in langCodes) {
118681                   var code = langCodes[j];
118682                   var referenceId = langCodes[0].split('-')[0] !== 'en' && code.split('-')[0] === 'en' ? 'inspector.wiki_en_reference' : 'inspector.wiki_reference';
118683                   var info = getWikiInfo(wiki, code, referenceId);
118684
118685                   if (info) {
118686                     result.wiki = info;
118687                     break;
118688                   }
118689                 }
118690
118691                 if (result.wiki) break;
118692               }
118693
118694               callback(null, result); // Helper method to get wiki info if a given language exists
118695
118696               function getWikiInfo(wiki, langCode, tKey) {
118697                 if (wiki && wiki[langCode]) {
118698                   return {
118699                     title: wiki[langCode],
118700                     text: tKey,
118701                     url: 'https://wiki.openstreetmap.org/wiki/' + wiki[langCode]
118702                   };
118703                 }
118704               }
118705             });
118706           },
118707           addLocale: function addLocale(langCode, qid) {
118708             // Makes it easier to unit test
118709             _localeIDs[langCode] = qid;
118710           },
118711           apibase: function apibase(val) {
118712             if (!arguments.length) return _apibase$1;
118713             _apibase$1 = val;
118714             return this;
118715           }
118716         };
118717
118718         var jsonpCache = {};
118719         window.jsonpCache = jsonpCache;
118720         function jsonpRequest(url, callback) {
118721           var request = {
118722             abort: function abort() {}
118723           };
118724
118725           if (window.JSONP_FIX) {
118726             if (window.JSONP_DELAY === 0) {
118727               callback(window.JSONP_FIX);
118728             } else {
118729               var t = window.setTimeout(function () {
118730                 callback(window.JSONP_FIX);
118731               }, window.JSONP_DELAY || 0);
118732
118733               request.abort = function () {
118734                 window.clearTimeout(t);
118735               };
118736             }
118737
118738             return request;
118739           }
118740
118741           function rand() {
118742             var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
118743             var c = '';
118744             var i = -1;
118745
118746             while (++i < 15) {
118747               c += chars.charAt(Math.floor(Math.random() * 52));
118748             }
118749
118750             return c;
118751           }
118752
118753           function create(url) {
118754             var e = url.match(/callback=(\w+)/);
118755             var c = e ? e[1] : rand();
118756
118757             jsonpCache[c] = function (data) {
118758               if (jsonpCache[c]) {
118759                 callback(data);
118760               }
118761
118762               finalize();
118763             };
118764
118765             function finalize() {
118766               delete jsonpCache[c];
118767               script.remove();
118768             }
118769
118770             request.abort = finalize;
118771             return 'jsonpCache.' + c;
118772           }
118773
118774           var cb = create(url);
118775           var script = select('head').append('script').attr('type', 'text/javascript').attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
118776           return request;
118777         }
118778
118779         var bubbleApi = 'https://dev.virtualearth.net/mapcontrol/HumanScaleServices/GetBubbles.ashx?';
118780         var streetsideImagesApi = 'https://t.ssl.ak.tiles.virtualearth.net/tiles/';
118781         var bubbleAppKey = 'AuftgJsO0Xs8Ts4M1xZUQJQXJNsvmh3IV8DkNieCiy3tCwCUMq76-WpkrBtNAuEm';
118782         var pannellumViewerCSS = 'pannellum-streetside/pannellum.css';
118783         var pannellumViewerJS = 'pannellum-streetside/pannellum.js';
118784         var maxResults = 2000;
118785         var tileZoom = 16.5;
118786         var tiler$1 = utilTiler().zoomExtent([tileZoom, tileZoom]).skipNullIsland(true);
118787         var dispatch$1 = dispatch$8('loadedImages', 'viewerChanged');
118788         var minHfov = 10; // zoom in degrees:  20, 10, 5
118789
118790         var maxHfov = 90; // zoom out degrees
118791
118792         var defaultHfov = 45;
118793         var _hires = false;
118794         var _resolution = 512; // higher numbers are slower - 512, 1024, 2048, 4096
118795
118796         var _currScene = 0;
118797
118798         var _ssCache;
118799
118800         var _pannellumViewer;
118801
118802         var _sceneOptions = {
118803           showFullscreenCtrl: false,
118804           autoLoad: true,
118805           compass: true,
118806           yaw: 0,
118807           minHfov: minHfov,
118808           maxHfov: maxHfov,
118809           hfov: defaultHfov,
118810           type: 'cubemap',
118811           cubeMap: []
118812         };
118813
118814         var _loadViewerPromise;
118815         /**
118816          * abortRequest().
118817          */
118818
118819
118820         function abortRequest$1(i) {
118821           i.abort();
118822         }
118823         /**
118824          * localeTimeStamp().
118825          */
118826
118827
118828         function localeTimestamp(s) {
118829           if (!s) return null;
118830           var options = {
118831             day: 'numeric',
118832             month: 'short',
118833             year: 'numeric'
118834           };
118835           var d = new Date(s);
118836           if (isNaN(d.getTime())) return null;
118837           return d.toLocaleString(_mainLocalizer.localeCode(), options);
118838         }
118839         /**
118840          * loadTiles() wraps the process of generating tiles and then fetching image points for each tile.
118841          */
118842
118843
118844         function loadTiles(which, url, projection, margin) {
118845           var tiles = tiler$1.margin(margin).getTiles(projection); // abort inflight requests that are no longer needed
118846
118847           var cache = _ssCache[which];
118848           Object.keys(cache.inflight).forEach(function (k) {
118849             var wanted = tiles.find(function (tile) {
118850               return k.indexOf(tile.id + ',') === 0;
118851             });
118852
118853             if (!wanted) {
118854               abortRequest$1(cache.inflight[k]);
118855               delete cache.inflight[k];
118856             }
118857           });
118858           tiles.forEach(function (tile) {
118859             return loadNextTilePage(which, url, tile);
118860           });
118861         }
118862         /**
118863          * loadNextTilePage() load data for the next tile page in line.
118864          */
118865
118866
118867         function loadNextTilePage(which, url, tile) {
118868           var cache = _ssCache[which];
118869           var nextPage = cache.nextPage[tile.id] || 0;
118870           var id = tile.id + ',' + String(nextPage);
118871           if (cache.loaded[id] || cache.inflight[id]) return;
118872           cache.inflight[id] = getBubbles(url, tile, function (bubbles) {
118873             cache.loaded[id] = true;
118874             delete cache.inflight[id];
118875             if (!bubbles) return; // [].shift() removes the first element, some statistics info, not a bubble point
118876
118877             bubbles.shift();
118878             var features = bubbles.map(function (bubble) {
118879               if (cache.points[bubble.id]) return null; // skip duplicates
118880
118881               var loc = [bubble.lo, bubble.la];
118882               var d = {
118883                 loc: loc,
118884                 key: bubble.id,
118885                 ca: bubble.he,
118886                 captured_at: bubble.cd,
118887                 captured_by: 'microsoft',
118888                 // nbn: bubble.nbn,
118889                 // pbn: bubble.pbn,
118890                 // ad: bubble.ad,
118891                 // rn: bubble.rn,
118892                 pr: bubble.pr,
118893                 // previous
118894                 ne: bubble.ne,
118895                 // next
118896                 pano: true,
118897                 sequenceKey: null
118898               };
118899               cache.points[bubble.id] = d; // a sequence starts here
118900
118901               if (bubble.pr === undefined) {
118902                 cache.leaders.push(bubble.id);
118903               }
118904
118905               return {
118906                 minX: loc[0],
118907                 minY: loc[1],
118908                 maxX: loc[0],
118909                 maxY: loc[1],
118910                 data: d
118911               };
118912             }).filter(Boolean);
118913             cache.rtree.load(features);
118914             connectSequences();
118915
118916             if (which === 'bubbles') {
118917               dispatch$1.call('loadedImages');
118918             }
118919           });
118920         } // call this sometimes to connect the bubbles into sequences
118921
118922
118923         function connectSequences() {
118924           var cache = _ssCache.bubbles;
118925           var keepLeaders = [];
118926
118927           for (var i = 0; i < cache.leaders.length; i++) {
118928             var bubble = cache.points[cache.leaders[i]];
118929             var seen = {}; // try to make a sequence.. use the key of the leader bubble.
118930
118931             var sequence = {
118932               key: bubble.key,
118933               bubbles: []
118934             };
118935             var complete = false;
118936
118937             do {
118938               sequence.bubbles.push(bubble);
118939               seen[bubble.key] = true;
118940
118941               if (bubble.ne === undefined) {
118942                 complete = true;
118943               } else {
118944                 bubble = cache.points[bubble.ne]; // advance to next
118945               }
118946             } while (bubble && !seen[bubble.key] && !complete);
118947
118948             if (complete) {
118949               _ssCache.sequences[sequence.key] = sequence; // assign bubbles to the sequence
118950
118951               for (var j = 0; j < sequence.bubbles.length; j++) {
118952                 sequence.bubbles[j].sequenceKey = sequence.key;
118953               } // create a GeoJSON LineString
118954
118955
118956               sequence.geojson = {
118957                 type: 'LineString',
118958                 properties: {
118959                   captured_at: sequence.bubbles[0] ? sequence.bubbles[0].captured_at : null,
118960                   captured_by: sequence.bubbles[0] ? sequence.bubbles[0].captured_by : null,
118961                   key: sequence.key
118962                 },
118963                 coordinates: sequence.bubbles.map(function (d) {
118964                   return d.loc;
118965                 })
118966               };
118967             } else {
118968               keepLeaders.push(cache.leaders[i]);
118969             }
118970           } // couldn't complete these, save for later
118971
118972
118973           cache.leaders = keepLeaders;
118974         }
118975         /**
118976          * getBubbles() handles the request to the server for a tile extent of 'bubbles' (streetside image locations).
118977          */
118978
118979
118980         function getBubbles(url, tile, callback) {
118981           var rect = tile.extent.rectangle();
118982           var urlForRequest = url + utilQsString({
118983             n: rect[3],
118984             s: rect[1],
118985             e: rect[2],
118986             w: rect[0],
118987             c: maxResults,
118988             appkey: bubbleAppKey,
118989             jsCallback: '{callback}'
118990           });
118991           return jsonpRequest(urlForRequest, function (data) {
118992             if (!data || data.error) {
118993               callback(null);
118994             } else {
118995               callback(data);
118996             }
118997           });
118998         } // partition viewport into higher zoom tiles
118999
119000
119001         function partitionViewport(projection) {
119002           var z = geoScaleToZoom(projection.scale());
119003           var z2 = Math.ceil(z * 2) / 2 + 2.5; // round to next 0.5 and add 2.5
119004
119005           var tiler = utilTiler().zoomExtent([z2, z2]);
119006           return tiler.getTiles(projection).map(function (tile) {
119007             return tile.extent;
119008           });
119009         } // no more than `limit` results per partition.
119010
119011
119012         function searchLimited(limit, projection, rtree) {
119013           limit = limit || 5;
119014           return partitionViewport(projection).reduce(function (result, extent) {
119015             var found = rtree.search(extent.bbox()).slice(0, limit).map(function (d) {
119016               return d.data;
119017             });
119018             return found.length ? result.concat(found) : result;
119019           }, []);
119020         }
119021         /**
119022          * loadImage()
119023          */
119024
119025
119026         function loadImage(imgInfo) {
119027           return new Promise(function (resolve) {
119028             var img = new Image();
119029
119030             img.onload = function () {
119031               var canvas = document.getElementById('ideditor-canvas' + imgInfo.face);
119032               var ctx = canvas.getContext('2d');
119033               ctx.drawImage(img, imgInfo.x, imgInfo.y);
119034               resolve({
119035                 imgInfo: imgInfo,
119036                 status: 'ok'
119037               });
119038             };
119039
119040             img.onerror = function () {
119041               resolve({
119042                 data: imgInfo,
119043                 status: 'error'
119044               });
119045             };
119046
119047             img.setAttribute('crossorigin', '');
119048             img.src = imgInfo.url;
119049           });
119050         }
119051         /**
119052          * loadCanvas()
119053          */
119054
119055
119056         function loadCanvas(imageGroup) {
119057           return Promise.all(imageGroup.map(loadImage)).then(function (data) {
119058             var canvas = document.getElementById('ideditor-canvas' + data[0].imgInfo.face);
119059             var which = {
119060               '01': 0,
119061               '02': 1,
119062               '03': 2,
119063               '10': 3,
119064               '11': 4,
119065               '12': 5
119066             };
119067             var face = data[0].imgInfo.face;
119068             _sceneOptions.cubeMap[which[face]] = canvas.toDataURL('image/jpeg', 1.0);
119069             return {
119070               status: 'loadCanvas for face ' + data[0].imgInfo.face + 'ok'
119071             };
119072           });
119073         }
119074         /**
119075          * loadFaces()
119076          */
119077
119078
119079         function loadFaces(faceGroup) {
119080           return Promise.all(faceGroup.map(loadCanvas)).then(function () {
119081             return {
119082               status: 'loadFaces done'
119083             };
119084           });
119085         }
119086
119087         function setupCanvas(selection, reset) {
119088           if (reset) {
119089             selection.selectAll('#ideditor-stitcher-canvases').remove();
119090           } // Add the Streetside working canvases. These are used for 'stitching', or combining,
119091           // multiple images for each of the six faces, before passing to the Pannellum control as DataUrls
119092
119093
119094           selection.selectAll('#ideditor-stitcher-canvases').data([0]).enter().append('div').attr('id', 'ideditor-stitcher-canvases').attr('display', 'none').selectAll('canvas').data(['canvas01', 'canvas02', 'canvas03', 'canvas10', 'canvas11', 'canvas12']).enter().append('canvas').attr('id', function (d) {
119095             return 'ideditor-' + d;
119096           }).attr('width', _resolution).attr('height', _resolution);
119097         }
119098
119099         function qkToXY(qk) {
119100           var x = 0;
119101           var y = 0;
119102           var scale = 256;
119103
119104           for (var i = qk.length; i > 0; i--) {
119105             var key = qk[i - 1];
119106             x += +(key === '1' || key === '3') * scale;
119107             y += +(key === '2' || key === '3') * scale;
119108             scale *= 2;
119109           }
119110
119111           return [x, y];
119112         }
119113
119114         function getQuadKeys() {
119115           var dim = _resolution / 256;
119116           var quadKeys;
119117
119118           if (dim === 16) {
119119             quadKeys = ['0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111', '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111', '0002', '0003', '0012', '0013', '0102', '0103', '0112', '0113', '1002', '1003', '1012', '1013', '1102', '1103', '1112', '1113', '0020', '0021', '0030', '0031', '0120', '0121', '0130', '0131', '1020', '1021', '1030', '1031', '1120', '1121', '1130', '1131', '0022', '0023', '0032', '0033', '0122', '0123', '0132', '0133', '1022', '1023', '1032', '1033', '1122', '1123', '1132', '1133', '0200', '0201', '0210', '0211', '0300', '0301', '0310', '0311', '1200', '1201', '1210', '1211', '1300', '1301', '1310', '1311', '0202', '0203', '0212', '0213', '0302', '0303', '0312', '0313', '1202', '1203', '1212', '1213', '1302', '1303', '1312', '1313', '0220', '0221', '0230', '0231', '0320', '0321', '0330', '0331', '1220', '1221', '1230', '1231', '1320', '1321', '1330', '1331', '0222', '0223', '0232', '0233', '0322', '0323', '0332', '0333', '1222', '1223', '1232', '1233', '1322', '1323', '1332', '1333', '2000', '2001', '2010', '2011', '2100', '2101', '2110', '2111', '3000', '3001', '3010', '3011', '3100', '3101', '3110', '3111', '2002', '2003', '2012', '2013', '2102', '2103', '2112', '2113', '3002', '3003', '3012', '3013', '3102', '3103', '3112', '3113', '2020', '2021', '2030', '2031', '2120', '2121', '2130', '2131', '3020', '3021', '3030', '3031', '3120', '3121', '3130', '3131', '2022', '2023', '2032', '2033', '2122', '2123', '2132', '2133', '3022', '3023', '3032', '3033', '3122', '3123', '3132', '3133', '2200', '2201', '2210', '2211', '2300', '2301', '2310', '2311', '3200', '3201', '3210', '3211', '3300', '3301', '3310', '3311', '2202', '2203', '2212', '2213', '2302', '2303', '2312', '2313', '3202', '3203', '3212', '3213', '3302', '3303', '3312', '3313', '2220', '2221', '2230', '2231', '2320', '2321', '2330', '2331', '3220', '3221', '3230', '3231', '3320', '3321', '3330', '3331', '2222', '2223', '2232', '2233', '2322', '2323', '2332', '2333', '3222', '3223', '3232', '3233', '3322', '3323', '3332', '3333'];
119120           } else if (dim === 8) {
119121             quadKeys = ['000', '001', '010', '011', '100', '101', '110', '111', '002', '003', '012', '013', '102', '103', '112', '113', '020', '021', '030', '031', '120', '121', '130', '131', '022', '023', '032', '033', '122', '123', '132', '133', '200', '201', '210', '211', '300', '301', '310', '311', '202', '203', '212', '213', '302', '303', '312', '313', '220', '221', '230', '231', '320', '321', '330', '331', '222', '223', '232', '233', '322', '323', '332', '333'];
119122           } else if (dim === 4) {
119123             quadKeys = ['00', '01', '10', '11', '02', '03', '12', '13', '20', '21', '30', '31', '22', '23', '32', '33'];
119124           } else {
119125             // dim === 2
119126             quadKeys = ['0', '1', '2', '3'];
119127           }
119128
119129           return quadKeys;
119130         }
119131
119132         var serviceStreetside = {
119133           /**
119134            * init() initialize streetside.
119135            */
119136           init: function init() {
119137             if (!_ssCache) {
119138               this.reset();
119139             }
119140
119141             this.event = utilRebind(this, dispatch$1, 'on');
119142           },
119143
119144           /**
119145            * reset() reset the cache.
119146            */
119147           reset: function reset() {
119148             if (_ssCache) {
119149               Object.values(_ssCache.bubbles.inflight).forEach(abortRequest$1);
119150             }
119151
119152             _ssCache = {
119153               bubbles: {
119154                 inflight: {},
119155                 loaded: {},
119156                 nextPage: {},
119157                 rtree: new RBush(),
119158                 points: {},
119159                 leaders: []
119160               },
119161               sequences: {}
119162             };
119163           },
119164
119165           /**
119166            * bubbles()
119167            */
119168           bubbles: function bubbles(projection) {
119169             var limit = 5;
119170             return searchLimited(limit, projection, _ssCache.bubbles.rtree);
119171           },
119172           cachedImage: function cachedImage(imageKey) {
119173             return _ssCache.bubbles.points[imageKey];
119174           },
119175           sequences: function sequences(projection) {
119176             var viewport = projection.clipExtent();
119177             var min = [viewport[0][0], viewport[1][1]];
119178             var max = [viewport[1][0], viewport[0][1]];
119179             var bbox = geoExtent(projection.invert(min), projection.invert(max)).bbox();
119180             var seen = {};
119181             var results = []; // all sequences for bubbles in viewport
119182
119183             _ssCache.bubbles.rtree.search(bbox).forEach(function (d) {
119184               var key = d.data.sequenceKey;
119185
119186               if (key && !seen[key]) {
119187                 seen[key] = true;
119188                 results.push(_ssCache.sequences[key].geojson);
119189               }
119190             });
119191
119192             return results;
119193           },
119194
119195           /**
119196            * loadBubbles()
119197            */
119198           loadBubbles: function loadBubbles(projection, margin) {
119199             // by default: request 2 nearby tiles so we can connect sequences.
119200             if (margin === undefined) margin = 2;
119201             loadTiles('bubbles', bubbleApi, projection, margin);
119202           },
119203           viewer: function viewer() {
119204             return _pannellumViewer;
119205           },
119206           initViewer: function initViewer() {
119207             if (!window.pannellum) return;
119208             if (_pannellumViewer) return;
119209             _currScene += 1;
119210
119211             var sceneID = _currScene.toString();
119212
119213             var options = {
119214               'default': {
119215                 firstScene: sceneID
119216               },
119217               scenes: {}
119218             };
119219             options.scenes[sceneID] = _sceneOptions;
119220             _pannellumViewer = window.pannellum.viewer('ideditor-viewer-streetside', options);
119221           },
119222           ensureViewerLoaded: function ensureViewerLoaded(context) {
119223             if (_loadViewerPromise) return _loadViewerPromise; // create ms-wrapper, a photo wrapper class
119224
119225             var wrap = context.container().select('.photoviewer').selectAll('.ms-wrapper').data([0]); // inject ms-wrapper into the photoviewer div
119226             // (used by all to house each custom photo viewer)
119227
119228             var wrapEnter = wrap.enter().append('div').attr('class', 'photo-wrapper ms-wrapper').classed('hide', true);
119229             var that = this;
119230             var pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse'; // inject div to support streetside viewer (pannellum) and attribution line
119231
119232             wrapEnter.append('div').attr('id', 'ideditor-viewer-streetside').on(pointerPrefix + 'down.streetside', function () {
119233               select(window).on(pointerPrefix + 'move.streetside', function () {
119234                 dispatch$1.call('viewerChanged');
119235               }, true);
119236             }).on(pointerPrefix + 'up.streetside pointercancel.streetside', function () {
119237               select(window).on(pointerPrefix + 'move.streetside', null); // continue dispatching events for a few seconds, in case viewer has inertia.
119238
119239               var t = timer(function (elapsed) {
119240                 dispatch$1.call('viewerChanged');
119241
119242                 if (elapsed > 2000) {
119243                   t.stop();
119244                 }
119245               });
119246             }).append('div').attr('class', 'photo-attribution fillD');
119247             var controlsEnter = wrapEnter.append('div').attr('class', 'photo-controls-wrap').append('div').attr('class', 'photo-controls');
119248             controlsEnter.append('button').on('click.back', step(-1)).text('◄');
119249             controlsEnter.append('button').on('click.forward', step(1)).text('►'); // create working canvas for stitching together images
119250
119251             wrap = wrap.merge(wrapEnter).call(setupCanvas, true); // Register viewer resize handler
119252
119253             context.ui().photoviewer.on('resize.streetside', function () {
119254               if (_pannellumViewer) {
119255                 _pannellumViewer.resize();
119256               }
119257             });
119258             _loadViewerPromise = new Promise(function (resolve, reject) {
119259               var loadedCount = 0;
119260
119261               function loaded() {
119262                 loadedCount += 1; // wait until both files are loaded
119263
119264                 if (loadedCount === 2) resolve();
119265               }
119266
119267               var head = select('head'); // load streetside pannellum viewer css
119268
119269               head.selectAll('#ideditor-streetside-viewercss').data([0]).enter().append('link').attr('id', 'ideditor-streetside-viewercss').attr('rel', 'stylesheet').attr('crossorigin', 'anonymous').attr('href', context.asset(pannellumViewerCSS)).on('load.serviceStreetside', loaded).on('error.serviceStreetside', function () {
119270                 reject();
119271               }); // load streetside pannellum viewer js
119272
119273               head.selectAll('#ideditor-streetside-viewerjs').data([0]).enter().append('script').attr('id', 'ideditor-streetside-viewerjs').attr('crossorigin', 'anonymous').attr('src', context.asset(pannellumViewerJS)).on('load.serviceStreetside', loaded).on('error.serviceStreetside', function () {
119274                 reject();
119275               });
119276             })["catch"](function () {
119277               _loadViewerPromise = null;
119278             });
119279             return _loadViewerPromise;
119280
119281             function step(stepBy) {
119282               return function () {
119283                 var viewer = context.container().select('.photoviewer');
119284                 var selected = viewer.empty() ? undefined : viewer.datum();
119285                 if (!selected) return;
119286                 var nextID = stepBy === 1 ? selected.ne : selected.pr;
119287
119288                 var yaw = _pannellumViewer.getYaw();
119289
119290                 var ca = selected.ca + yaw;
119291                 var origin = selected.loc; // construct a search trapezoid pointing out from current bubble
119292
119293                 var meters = 35;
119294                 var p1 = [origin[0] + geoMetersToLon(meters / 5, origin[1]), origin[1]];
119295                 var p2 = [origin[0] + geoMetersToLon(meters / 2, origin[1]), origin[1] + geoMetersToLat(meters)];
119296                 var p3 = [origin[0] - geoMetersToLon(meters / 2, origin[1]), origin[1] + geoMetersToLat(meters)];
119297                 var p4 = [origin[0] - geoMetersToLon(meters / 5, origin[1]), origin[1]];
119298                 var poly = [p1, p2, p3, p4, p1]; // rotate it to face forward/backward
119299
119300                 var angle = (stepBy === 1 ? ca : ca + 180) * (Math.PI / 180);
119301                 poly = geoRotate(poly, -angle, origin);
119302                 var extent = poly.reduce(function (extent, point) {
119303                   return extent.extend(geoExtent(point));
119304                 }, geoExtent()); // find nearest other bubble in the search polygon
119305
119306                 var minDist = Infinity;
119307
119308                 _ssCache.bubbles.rtree.search(extent.bbox()).forEach(function (d) {
119309                   if (d.data.key === selected.key) return;
119310                   if (!geoPointInPolygon(d.data.loc, poly)) return;
119311                   var dist = geoVecLength(d.data.loc, selected.loc);
119312                   var theta = selected.ca - d.data.ca;
119313                   var minTheta = Math.min(Math.abs(theta), 360 - Math.abs(theta));
119314
119315                   if (minTheta > 20) {
119316                     dist += 5; // penalize distance if camera angles don't match
119317                   }
119318
119319                   if (dist < minDist) {
119320                     nextID = d.data.key;
119321                     minDist = dist;
119322                   }
119323                 });
119324
119325                 var nextBubble = nextID && that.cachedImage(nextID);
119326                 if (!nextBubble) return;
119327                 context.map().centerEase(nextBubble.loc);
119328                 that.selectImage(context, nextBubble.key).yaw(yaw).showViewer(context);
119329               };
119330             }
119331           },
119332           yaw: function yaw(_yaw) {
119333             if (typeof _yaw !== 'number') return _yaw;
119334             _sceneOptions.yaw = _yaw;
119335             return this;
119336           },
119337
119338           /**
119339            * showViewer()
119340            */
119341           showViewer: function showViewer(context) {
119342             var wrap = context.container().select('.photoviewer').classed('hide', false);
119343             var isHidden = wrap.selectAll('.photo-wrapper.ms-wrapper.hide').size();
119344
119345             if (isHidden) {
119346               wrap.selectAll('.photo-wrapper:not(.ms-wrapper)').classed('hide', true);
119347               wrap.selectAll('.photo-wrapper.ms-wrapper').classed('hide', false);
119348             }
119349
119350             return this;
119351           },
119352
119353           /**
119354            * hideViewer()
119355            */
119356           hideViewer: function hideViewer(context) {
119357             var viewer = context.container().select('.photoviewer');
119358             if (!viewer.empty()) viewer.datum(null);
119359             viewer.classed('hide', true).selectAll('.photo-wrapper').classed('hide', true);
119360             context.container().selectAll('.viewfield-group, .sequence, .icon-sign').classed('currentView', false);
119361             this.updateUrlImage(null);
119362             return this.setStyles(context, null, true);
119363           },
119364
119365           /**
119366            * selectImage().
119367            */
119368           selectImage: function selectImage(context, key) {
119369             var that = this;
119370             var d = this.cachedImage(key);
119371             var viewer = context.container().select('.photoviewer');
119372             if (!viewer.empty()) viewer.datum(d);
119373             this.setStyles(context, null, true);
119374             var wrap = context.container().select('.photoviewer .ms-wrapper');
119375             var attribution = wrap.selectAll('.photo-attribution').html('');
119376             wrap.selectAll('.pnlm-load-box') // display "loading.."
119377             .style('display', 'block');
119378             if (!d) return this;
119379             this.updateUrlImage(key);
119380             _sceneOptions.northOffset = d.ca;
119381             var line1 = attribution.append('div').attr('class', 'attribution-row');
119382             var hiresDomId = utilUniqueDomId('streetside-hires'); // Add hires checkbox
119383
119384             var label = line1.append('label').attr('for', hiresDomId).attr('class', 'streetside-hires');
119385             label.append('input').attr('type', 'checkbox').attr('id', hiresDomId).property('checked', _hires).on('click', function (d3_event) {
119386               d3_event.stopPropagation();
119387               _hires = !_hires;
119388               _resolution = _hires ? 1024 : 512;
119389               wrap.call(setupCanvas, true);
119390               var viewstate = {
119391                 yaw: _pannellumViewer.getYaw(),
119392                 pitch: _pannellumViewer.getPitch(),
119393                 hfov: _pannellumViewer.getHfov()
119394               };
119395               _sceneOptions = Object.assign(_sceneOptions, viewstate);
119396               that.selectImage(context, d.key).showViewer(context);
119397             });
119398             label.append('span').call(_t.append('streetside.hires'));
119399             var captureInfo = line1.append('div').attr('class', 'attribution-capture-info'); // Add capture date
119400
119401             if (d.captured_by) {
119402               var yyyy = new Date().getFullYear();
119403               captureInfo.append('a').attr('class', 'captured_by').attr('target', '_blank').attr('href', 'https://www.microsoft.com/en-us/maps/streetside').text('©' + yyyy + ' Microsoft');
119404               captureInfo.append('span').text('|');
119405             }
119406
119407             if (d.captured_at) {
119408               captureInfo.append('span').attr('class', 'captured_at').text(localeTimestamp(d.captured_at));
119409             } // Add image links
119410
119411
119412             var line2 = attribution.append('div').attr('class', 'attribution-row');
119413             line2.append('a').attr('class', 'image-view-link').attr('target', '_blank').attr('href', 'https://www.bing.com/maps?cp=' + d.loc[1] + '~' + d.loc[0] + '&lvl=17&dir=' + d.ca + '&style=x&v=2&sV=1').call(_t.append('streetside.view_on_bing'));
119414             line2.append('a').attr('class', 'image-report-link').attr('target', '_blank').attr('href', 'https://www.bing.com/maps/privacyreport/streetsideprivacyreport?bubbleid=' + encodeURIComponent(d.key) + '&focus=photo&lat=' + d.loc[1] + '&lng=' + d.loc[0] + '&z=17').call(_t.append('streetside.report'));
119415             var bubbleIdQuadKey = d.key.toString(4);
119416             var paddingNeeded = 16 - bubbleIdQuadKey.length;
119417
119418             for (var i = 0; i < paddingNeeded; i++) {
119419               bubbleIdQuadKey = '0' + bubbleIdQuadKey;
119420             }
119421
119422             var imgUrlPrefix = streetsideImagesApi + 'hs' + bubbleIdQuadKey;
119423             var imgUrlSuffix = '.jpg?g=6338&n=z'; // Cubemap face code order matters here: front=01, right=02, back=03, left=10, up=11, down=12
119424
119425             var faceKeys = ['01', '02', '03', '10', '11', '12']; // Map images to cube faces
119426
119427             var quadKeys = getQuadKeys();
119428             var faces = faceKeys.map(function (faceKey) {
119429               return quadKeys.map(function (quadKey) {
119430                 var xy = qkToXY(quadKey);
119431                 return {
119432                   face: faceKey,
119433                   url: imgUrlPrefix + faceKey + quadKey + imgUrlSuffix,
119434                   x: xy[0],
119435                   y: xy[1]
119436                 };
119437               });
119438             });
119439             loadFaces(faces).then(function () {
119440               if (!_pannellumViewer) {
119441                 that.initViewer();
119442               } else {
119443                 // make a new scene
119444                 _currScene += 1;
119445
119446                 var sceneID = _currScene.toString();
119447
119448                 _pannellumViewer.addScene(sceneID, _sceneOptions).loadScene(sceneID); // remove previous scene
119449
119450
119451                 if (_currScene > 2) {
119452                   sceneID = (_currScene - 1).toString();
119453
119454                   _pannellumViewer.removeScene(sceneID);
119455                 }
119456               }
119457             });
119458             return this;
119459           },
119460           getSequenceKeyForBubble: function getSequenceKeyForBubble(d) {
119461             return d && d.sequenceKey;
119462           },
119463           // Updates the currently highlighted sequence and selected bubble.
119464           // Reset is only necessary when interacting with the viewport because
119465           // this implicitly changes the currently selected bubble/sequence
119466           setStyles: function setStyles(context, hovered, reset) {
119467             if (reset) {
119468               // reset all layers
119469               context.container().selectAll('.viewfield-group').classed('highlighted', false).classed('hovered', false).classed('currentView', false);
119470               context.container().selectAll('.sequence').classed('highlighted', false).classed('currentView', false);
119471             }
119472
119473             var hoveredBubbleKey = hovered && hovered.key;
119474             var hoveredSequenceKey = this.getSequenceKeyForBubble(hovered);
119475             var hoveredSequence = hoveredSequenceKey && _ssCache.sequences[hoveredSequenceKey];
119476             var hoveredBubbleKeys = hoveredSequence && hoveredSequence.bubbles.map(function (d) {
119477               return d.key;
119478             }) || [];
119479             var viewer = context.container().select('.photoviewer');
119480             var selected = viewer.empty() ? undefined : viewer.datum();
119481             var selectedBubbleKey = selected && selected.key;
119482             var selectedSequenceKey = this.getSequenceKeyForBubble(selected);
119483             var selectedSequence = selectedSequenceKey && _ssCache.sequences[selectedSequenceKey];
119484             var selectedBubbleKeys = selectedSequence && selectedSequence.bubbles.map(function (d) {
119485               return d.key;
119486             }) || []; // highlight sibling viewfields on either the selected or the hovered sequences
119487
119488             var highlightedBubbleKeys = utilArrayUnion(hoveredBubbleKeys, selectedBubbleKeys);
119489             context.container().selectAll('.layer-streetside-images .viewfield-group').classed('highlighted', function (d) {
119490               return highlightedBubbleKeys.indexOf(d.key) !== -1;
119491             }).classed('hovered', function (d) {
119492               return d.key === hoveredBubbleKey;
119493             }).classed('currentView', function (d) {
119494               return d.key === selectedBubbleKey;
119495             });
119496             context.container().selectAll('.layer-streetside-images .sequence').classed('highlighted', function (d) {
119497               return d.properties.key === hoveredSequenceKey;
119498             }).classed('currentView', function (d) {
119499               return d.properties.key === selectedSequenceKey;
119500             }); // update viewfields if needed
119501
119502             context.container().selectAll('.layer-streetside-images .viewfield-group .viewfield').attr('d', viewfieldPath);
119503
119504             function viewfieldPath() {
119505               var d = this.parentNode.__data__;
119506
119507               if (d.pano && d.key !== selectedBubbleKey) {
119508                 return 'M 8,13 m -10,0 a 10,10 0 1,0 20,0 a 10,10 0 1,0 -20,0';
119509               } else {
119510                 return 'M 6,9 C 8,8.4 8,8.4 10,9 L 16,-2 C 12,-5 4,-5 0,-2 z';
119511               }
119512             }
119513
119514             return this;
119515           },
119516           updateUrlImage: function updateUrlImage(imageKey) {
119517             if (!window.mocha) {
119518               var hash = utilStringQs(window.location.hash);
119519
119520               if (imageKey) {
119521                 hash.photo = 'streetside/' + imageKey;
119522               } else {
119523                 delete hash.photo;
119524               }
119525
119526               window.location.replace('#' + utilQsString(hash, true));
119527             }
119528           },
119529
119530           /**
119531            * cache().
119532            */
119533           cache: function cache() {
119534             return _ssCache;
119535           }
119536         };
119537
119538         var _apibase = 'https://taginfo.openstreetmap.org/api/4/';
119539         var _inflight = {};
119540         var _popularKeys = {};
119541         var _taginfoCache = {};
119542         var tag_sorts = {
119543           point: 'count_nodes',
119544           vertex: 'count_nodes',
119545           area: 'count_ways',
119546           line: 'count_ways'
119547         };
119548         var tag_sort_members = {
119549           point: 'count_node_members',
119550           vertex: 'count_node_members',
119551           area: 'count_way_members',
119552           line: 'count_way_members',
119553           relation: 'count_relation_members'
119554         };
119555         var tag_filters = {
119556           point: 'nodes',
119557           vertex: 'nodes',
119558           area: 'ways',
119559           line: 'ways'
119560         };
119561         var tag_members_fractions = {
119562           point: 'count_node_members_fraction',
119563           vertex: 'count_node_members_fraction',
119564           area: 'count_way_members_fraction',
119565           line: 'count_way_members_fraction',
119566           relation: 'count_relation_members_fraction'
119567         };
119568
119569         function sets(params, n, o) {
119570           if (params.geometry && o[params.geometry]) {
119571             params[n] = o[params.geometry];
119572           }
119573
119574           return params;
119575         }
119576
119577         function setFilter(params) {
119578           return sets(params, 'filter', tag_filters);
119579         }
119580
119581         function setSort(params) {
119582           return sets(params, 'sortname', tag_sorts);
119583         }
119584
119585         function setSortMembers(params) {
119586           return sets(params, 'sortname', tag_sort_members);
119587         }
119588
119589         function clean(params) {
119590           return utilObjectOmit(params, ['geometry', 'debounce']);
119591         }
119592
119593         function filterKeys(type) {
119594           var count_type = type ? 'count_' + type : 'count_all';
119595           return function (d) {
119596             return parseFloat(d[count_type]) > 2500 || d.in_wiki;
119597           };
119598         }
119599
119600         function filterMultikeys(prefix) {
119601           return function (d) {
119602             // d.key begins with prefix, and d.key contains no additional ':'s
119603             var re = new RegExp('^' + prefix + '(.*)$');
119604             var matches = d.key.match(re) || [];
119605             return matches.length === 2 && matches[1].indexOf(':') === -1;
119606           };
119607         }
119608
119609         function filterValues(allowUpperCase) {
119610           return function (d) {
119611             if (d.value.match(/[;,]/) !== null) return false; // exclude some punctuation
119612
119613             if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false; // exclude uppercase letters
119614
119615             return parseFloat(d.fraction) > 0.0;
119616           };
119617         }
119618
119619         function filterRoles(geometry) {
119620           return function (d) {
119621             if (d.role === '') return false; // exclude empty role
119622
119623             if (d.role.match(/[A-Z*;,]/) !== null) return false; // exclude uppercase letters and some punctuation
119624
119625             return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
119626           };
119627         }
119628
119629         function valKey(d) {
119630           return {
119631             value: d.key,
119632             title: d.key
119633           };
119634         }
119635
119636         function valKeyDescription(d) {
119637           var obj = {
119638             value: d.value,
119639             title: d.description || d.value
119640           };
119641
119642           if (d.count) {
119643             obj.count = d.count;
119644           }
119645
119646           return obj;
119647         }
119648
119649         function roleKey(d) {
119650           return {
119651             value: d.role,
119652             title: d.role
119653           };
119654         } // sort keys with ':' lower than keys without ':'
119655
119656
119657         function sortKeys(a, b) {
119658           return a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1 ? -1 : a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1 ? 1 : 0;
119659         }
119660
119661         var debouncedRequest = debounce(request, 300, {
119662           leading: false
119663         });
119664
119665         function request(url, params, exactMatch, callback, loaded) {
119666           if (_inflight[url]) return;
119667           if (checkCache(url, params, exactMatch, callback)) return;
119668           var controller = new AbortController();
119669           _inflight[url] = controller;
119670           d3_json(url, {
119671             signal: controller.signal
119672           }).then(function (result) {
119673             delete _inflight[url];
119674             if (loaded) loaded(null, result);
119675           })["catch"](function (err) {
119676             delete _inflight[url];
119677             if (err.name === 'AbortError') return;
119678             if (loaded) loaded(err.message);
119679           });
119680         }
119681
119682         function checkCache(url, params, exactMatch, callback) {
119683           var rp = params.rp || 25;
119684           var testQuery = params.query || '';
119685           var testUrl = url;
119686
119687           do {
119688             var hit = _taginfoCache[testUrl]; // exact match, or shorter match yielding fewer than max results (rp)
119689
119690             if (hit && (url === testUrl || hit.length < rp)) {
119691               callback(null, hit);
119692               return true;
119693             } // don't try to shorten the query
119694
119695
119696             if (exactMatch || !testQuery.length) return false; // do shorten the query to see if we already have a cached result
119697             // that has returned fewer than max results (rp)
119698
119699             testQuery = testQuery.slice(0, -1);
119700             testUrl = url.replace(/&query=(.*?)&/, '&query=' + testQuery + '&');
119701           } while (testQuery.length >= 0);
119702
119703           return false;
119704         }
119705
119706         var serviceTaginfo = {
119707           init: function init() {
119708             _inflight = {};
119709             _taginfoCache = {};
119710             _popularKeys = {
119711               // manually exclude some keys – #5377, #7485
119712               postal_code: true,
119713               full_name: true,
119714               loc_name: true,
119715               reg_name: true,
119716               short_name: true,
119717               sorting_name: true,
119718               artist_name: true,
119719               nat_name: true,
119720               long_name: true,
119721               'bridge:name': true
119722             }; // Fetch popular keys.  We'll exclude these from `values`
119723             // lookups because they stress taginfo, and they aren't likely
119724             // to yield meaningful autocomplete results.. see #3955
119725
119726             var params = {
119727               rp: 100,
119728               sortname: 'values_all',
119729               sortorder: 'desc',
119730               page: 1,
119731               debounce: false,
119732               lang: _mainLocalizer.languageCode()
119733             };
119734             this.keys(params, function (err, data) {
119735               if (err) return;
119736               data.forEach(function (d) {
119737                 if (d.value === 'opening_hours') return; // exception
119738
119739                 _popularKeys[d.value] = true;
119740               });
119741             });
119742           },
119743           reset: function reset() {
119744             Object.values(_inflight).forEach(function (controller) {
119745               controller.abort();
119746             });
119747             _inflight = {};
119748           },
119749           keys: function keys(params, callback) {
119750             var doRequest = params.debounce ? debouncedRequest : request;
119751             params = clean(setSort(params));
119752             params = Object.assign({
119753               rp: 10,
119754               sortname: 'count_all',
119755               sortorder: 'desc',
119756               page: 1,
119757               lang: _mainLocalizer.languageCode()
119758             }, params);
119759             var url = _apibase + 'keys/all?' + utilQsString(params);
119760             doRequest(url, params, false, callback, function (err, d) {
119761               if (err) {
119762                 callback(err);
119763               } else {
119764                 var f = filterKeys(params.filter);
119765                 var result = d.data.filter(f).sort(sortKeys).map(valKey);
119766                 _taginfoCache[url] = result;
119767                 callback(null, result);
119768               }
119769             });
119770           },
119771           multikeys: function multikeys(params, callback) {
119772             var doRequest = params.debounce ? debouncedRequest : request;
119773             params = clean(setSort(params));
119774             params = Object.assign({
119775               rp: 25,
119776               sortname: 'count_all',
119777               sortorder: 'desc',
119778               page: 1,
119779               lang: _mainLocalizer.languageCode()
119780             }, params);
119781             var prefix = params.query;
119782             var url = _apibase + 'keys/all?' + utilQsString(params);
119783             doRequest(url, params, true, callback, function (err, d) {
119784               if (err) {
119785                 callback(err);
119786               } else {
119787                 var f = filterMultikeys(prefix);
119788                 var result = d.data.filter(f).map(valKey);
119789                 _taginfoCache[url] = result;
119790                 callback(null, result);
119791               }
119792             });
119793           },
119794           values: function values(params, callback) {
119795             // Exclude popular keys from values lookups.. see #3955
119796             var key = params.key;
119797
119798             if (key && _popularKeys[key]) {
119799               callback(null, []);
119800               return;
119801             }
119802
119803             var doRequest = params.debounce ? debouncedRequest : request;
119804             params = clean(setSort(setFilter(params)));
119805             params = Object.assign({
119806               rp: 25,
119807               sortname: 'count_all',
119808               sortorder: 'desc',
119809               page: 1,
119810               lang: _mainLocalizer.languageCode()
119811             }, params);
119812             var url = _apibase + 'key/values?' + utilQsString(params);
119813             doRequest(url, params, false, callback, function (err, d) {
119814               if (err) {
119815                 callback(err);
119816               } else {
119817                 // In most cases we prefer taginfo value results with lowercase letters.
119818                 // A few OSM keys expect values to contain uppercase values (see #3377).
119819                 // This is not an exhaustive list (e.g. `name` also has uppercase values)
119820                 // but these are the fields where taginfo value lookup is most useful.
119821                 var re = /network|taxon|genus|species|brand|grape_variety|royal_cypher|listed_status|booth|rating|stars|:output|_hours|_times|_ref|manufacturer|country|target|brewery|cai_scale/;
119822                 var allowUpperCase = re.test(params.key);
119823                 var f = filterValues(allowUpperCase);
119824                 var result = d.data.filter(f).map(valKeyDescription);
119825                 _taginfoCache[url] = result;
119826                 callback(null, result);
119827               }
119828             });
119829           },
119830           roles: function roles(params, callback) {
119831             var doRequest = params.debounce ? debouncedRequest : request;
119832             var geometry = params.geometry;
119833             params = clean(setSortMembers(params));
119834             params = Object.assign({
119835               rp: 25,
119836               sortname: 'count_all_members',
119837               sortorder: 'desc',
119838               page: 1,
119839               lang: _mainLocalizer.languageCode()
119840             }, params);
119841             var url = _apibase + 'relation/roles?' + utilQsString(params);
119842             doRequest(url, params, true, callback, function (err, d) {
119843               if (err) {
119844                 callback(err);
119845               } else {
119846                 var f = filterRoles(geometry);
119847                 var result = d.data.filter(f).map(roleKey);
119848                 _taginfoCache[url] = result;
119849                 callback(null, result);
119850               }
119851             });
119852           },
119853           docs: function docs(params, callback) {
119854             var doRequest = params.debounce ? debouncedRequest : request;
119855             params = clean(setSort(params));
119856             var path = 'key/wiki_pages?';
119857
119858             if (params.value) {
119859               path = 'tag/wiki_pages?';
119860             } else if (params.rtype) {
119861               path = 'relation/wiki_pages?';
119862             }
119863
119864             var url = _apibase + path + utilQsString(params);
119865             doRequest(url, params, true, callback, function (err, d) {
119866               if (err) {
119867                 callback(err);
119868               } else {
119869                 _taginfoCache[url] = d.data;
119870                 callback(null, d.data);
119871               }
119872             });
119873           },
119874           apibase: function apibase(_) {
119875             if (!arguments.length) return _apibase;
119876             _apibase = _;
119877             return this;
119878           }
119879         };
119880
119881         /**
119882          * Wraps a GeoJSON {@link Geometry} in a GeoJSON {@link Feature}.
119883          *
119884          * @name feature
119885          * @param {Geometry} geometry input geometry
119886          * @param {Object} [properties={}] an Object of key-value pairs to add as properties
119887          * @param {Object} [options={}] Optional Parameters
119888          * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
119889          * @param {string|number} [options.id] Identifier associated with the Feature
119890          * @returns {Feature} a GeoJSON Feature
119891          * @example
119892          * var geometry = {
119893          *   "type": "Point",
119894          *   "coordinates": [110, 50]
119895          * };
119896          *
119897          * var feature = turf.feature(geometry);
119898          *
119899          * //=feature
119900          */
119901
119902         function feature(geom, properties, options) {
119903           if (options === void 0) {
119904             options = {};
119905           }
119906
119907           var feat = {
119908             type: "Feature"
119909           };
119910
119911           if (options.id === 0 || options.id) {
119912             feat.id = options.id;
119913           }
119914
119915           if (options.bbox) {
119916             feat.bbox = options.bbox;
119917           }
119918
119919           feat.properties = properties || {};
119920           feat.geometry = geom;
119921           return feat;
119922         }
119923         /**
119924          * Creates a {@link Polygon} {@link Feature} from an Array of LinearRings.
119925          *
119926          * @name polygon
119927          * @param {Array<Array<Array<number>>>} coordinates an array of LinearRings
119928          * @param {Object} [properties={}] an Object of key-value pairs to add as properties
119929          * @param {Object} [options={}] Optional Parameters
119930          * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
119931          * @param {string|number} [options.id] Identifier associated with the Feature
119932          * @returns {Feature<Polygon>} Polygon Feature
119933          * @example
119934          * var polygon = turf.polygon([[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]], { name: 'poly1' });
119935          *
119936          * //=polygon
119937          */
119938
119939         function polygon(coordinates, properties, options) {
119940           if (options === void 0) {
119941             options = {};
119942           }
119943
119944           for (var _i = 0, coordinates_1 = coordinates; _i < coordinates_1.length; _i++) {
119945             var ring = coordinates_1[_i];
119946
119947             if (ring.length < 4) {
119948               throw new Error("Each LinearRing of a Polygon must have 4 or more Positions.");
119949             }
119950
119951             for (var j = 0; j < ring[ring.length - 1].length; j++) {
119952               // Check if first point of Polygon contains two numbers
119953               if (ring[ring.length - 1][j] !== ring[0][j]) {
119954                 throw new Error("First and last Position are not equivalent.");
119955               }
119956             }
119957           }
119958
119959           var geom = {
119960             type: "Polygon",
119961             coordinates: coordinates
119962           };
119963           return feature(geom, properties, options);
119964         }
119965         /**
119966          * Creates a {@link LineString} {@link Feature} from an Array of Positions.
119967          *
119968          * @name lineString
119969          * @param {Array<Array<number>>} coordinates an array of Positions
119970          * @param {Object} [properties={}] an Object of key-value pairs to add as properties
119971          * @param {Object} [options={}] Optional Parameters
119972          * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
119973          * @param {string|number} [options.id] Identifier associated with the Feature
119974          * @returns {Feature<LineString>} LineString Feature
119975          * @example
119976          * var linestring1 = turf.lineString([[-24, 63], [-23, 60], [-25, 65], [-20, 69]], {name: 'line 1'});
119977          * var linestring2 = turf.lineString([[-14, 43], [-13, 40], [-15, 45], [-10, 49]], {name: 'line 2'});
119978          *
119979          * //=linestring1
119980          * //=linestring2
119981          */
119982
119983         function lineString(coordinates, properties, options) {
119984           if (options === void 0) {
119985             options = {};
119986           }
119987
119988           if (coordinates.length < 2) {
119989             throw new Error("coordinates must be an array of two or more positions");
119990           }
119991
119992           var geom = {
119993             type: "LineString",
119994             coordinates: coordinates
119995           };
119996           return feature(geom, properties, options);
119997         }
119998         /**
119999          * Creates a {@link Feature<MultiLineString>} based on a
120000          * coordinate array. Properties can be added optionally.
120001          *
120002          * @name multiLineString
120003          * @param {Array<Array<Array<number>>>} coordinates an array of LineStrings
120004          * @param {Object} [properties={}] an Object of key-value pairs to add as properties
120005          * @param {Object} [options={}] Optional Parameters
120006          * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
120007          * @param {string|number} [options.id] Identifier associated with the Feature
120008          * @returns {Feature<MultiLineString>} a MultiLineString feature
120009          * @throws {Error} if no coordinates are passed
120010          * @example
120011          * var multiLine = turf.multiLineString([[[0,0],[10,10]]]);
120012          *
120013          * //=multiLine
120014          */
120015
120016         function multiLineString(coordinates, properties, options) {
120017           if (options === void 0) {
120018             options = {};
120019           }
120020
120021           var geom = {
120022             type: "MultiLineString",
120023             coordinates: coordinates
120024           };
120025           return feature(geom, properties, options);
120026         }
120027         /**
120028          * Creates a {@link Feature<MultiPolygon>} based on a
120029          * coordinate array. Properties can be added optionally.
120030          *
120031          * @name multiPolygon
120032          * @param {Array<Array<Array<Array<number>>>>} coordinates an array of Polygons
120033          * @param {Object} [properties={}] an Object of key-value pairs to add as properties
120034          * @param {Object} [options={}] Optional Parameters
120035          * @param {Array<number>} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature
120036          * @param {string|number} [options.id] Identifier associated with the Feature
120037          * @returns {Feature<MultiPolygon>} a multipolygon feature
120038          * @throws {Error} if no coordinates are passed
120039          * @example
120040          * var multiPoly = turf.multiPolygon([[[[0,0],[0,10],[10,10],[10,0],[0,0]]]]);
120041          *
120042          * //=multiPoly
120043          *
120044          */
120045
120046         function multiPolygon(coordinates, properties, options) {
120047           if (options === void 0) {
120048             options = {};
120049           }
120050
120051           var geom = {
120052             type: "MultiPolygon",
120053             coordinates: coordinates
120054           };
120055           return feature(geom, properties, options);
120056         }
120057
120058         /**
120059          * Get Geometry from Feature or Geometry Object
120060          *
120061          * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object
120062          * @returns {Geometry|null} GeoJSON Geometry Object
120063          * @throws {Error} if geojson is not a Feature or Geometry Object
120064          * @example
120065          * var point = {
120066          *   "type": "Feature",
120067          *   "properties": {},
120068          *   "geometry": {
120069          *     "type": "Point",
120070          *     "coordinates": [110, 40]
120071          *   }
120072          * }
120073          * var geom = turf.getGeom(point)
120074          * //={"type": "Point", "coordinates": [110, 40]}
120075          */
120076
120077         function getGeom(geojson) {
120078           if (geojson.type === "Feature") {
120079             return geojson.geometry;
120080           }
120081
120082           return geojson;
120083         }
120084
120085         // Cohen-Sutherland line clipping algorithm, adapted to efficiently
120086         // handle polylines rather than just segments
120087         function lineclip(points, bbox, result) {
120088           var len = points.length,
120089               codeA = bitCode(points[0], bbox),
120090               part = [],
120091               i,
120092               codeB,
120093               lastCode;
120094           var a;
120095           var b;
120096           if (!result) result = [];
120097
120098           for (i = 1; i < len; i++) {
120099             a = points[i - 1];
120100             b = points[i];
120101             codeB = lastCode = bitCode(b, bbox);
120102
120103             while (true) {
120104               if (!(codeA | codeB)) {
120105                 // accept
120106                 part.push(a);
120107
120108                 if (codeB !== lastCode) {
120109                   // segment went outside
120110                   part.push(b);
120111
120112                   if (i < len - 1) {
120113                     // start a new line
120114                     result.push(part);
120115                     part = [];
120116                   }
120117                 } else if (i === len - 1) {
120118                   part.push(b);
120119                 }
120120
120121                 break;
120122               } else if (codeA & codeB) {
120123                 // trivial reject
120124                 break;
120125               } else if (codeA) {
120126                 // a outside, intersect with clip edge
120127                 a = intersect(a, b, codeA, bbox);
120128                 codeA = bitCode(a, bbox);
120129               } else {
120130                 // b outside
120131                 b = intersect(a, b, codeB, bbox);
120132                 codeB = bitCode(b, bbox);
120133               }
120134             }
120135
120136             codeA = lastCode;
120137           }
120138
120139           if (part.length) result.push(part);
120140           return result;
120141         } // Sutherland-Hodgeman polygon clipping algorithm
120142
120143         function polygonclip(points, bbox) {
120144           var result, edge, prev, prevInside, i, p, inside; // clip against each side of the clip rectangle
120145
120146           for (edge = 1; edge <= 8; edge *= 2) {
120147             result = [];
120148             prev = points[points.length - 1];
120149             prevInside = !(bitCode(prev, bbox) & edge);
120150
120151             for (i = 0; i < points.length; i++) {
120152               p = points[i];
120153               inside = !(bitCode(p, bbox) & edge); // if segment goes through the clip window, add an intersection
120154
120155               if (inside !== prevInside) result.push(intersect(prev, p, edge, bbox));
120156               if (inside) result.push(p); // add a point if it's inside
120157
120158               prev = p;
120159               prevInside = inside;
120160             }
120161
120162             points = result;
120163             if (!points.length) break;
120164           }
120165
120166           return result;
120167         } // intersect a segment against one of the 4 lines that make up the bbox
120168
120169         function intersect(a, b, edge, bbox) {
120170           return edge & 8 ? [a[0] + (b[0] - a[0]) * (bbox[3] - a[1]) / (b[1] - a[1]), bbox[3]] // top
120171           : edge & 4 ? [a[0] + (b[0] - a[0]) * (bbox[1] - a[1]) / (b[1] - a[1]), bbox[1]] // bottom
120172           : edge & 2 ? [bbox[2], a[1] + (b[1] - a[1]) * (bbox[2] - a[0]) / (b[0] - a[0])] // right
120173           : edge & 1 ? [bbox[0], a[1] + (b[1] - a[1]) * (bbox[0] - a[0]) / (b[0] - a[0])] // left
120174           : null;
120175         } // bit code reflects the point position relative to the bbox:
120176         //         left  mid  right
120177         //    top  1001  1000  1010
120178         //    mid  0001  0000  0010
120179         // bottom  0101  0100  0110
120180
120181
120182         function bitCode(p, bbox) {
120183           var code = 0;
120184           if (p[0] < bbox[0]) code |= 1; // left
120185           else if (p[0] > bbox[2]) code |= 2; // right
120186
120187           if (p[1] < bbox[1]) code |= 4; // bottom
120188           else if (p[1] > bbox[3]) code |= 8; // top
120189
120190           return code;
120191         }
120192
120193         /**
120194          * Takes a {@link Feature} and a bbox and clips the feature to the bbox using
120195          * [lineclip](https://github.com/mapbox/lineclip).
120196          * May result in degenerate edges when clipping Polygons.
120197          *
120198          * @name bboxClip
120199          * @param {Feature<LineString|MultiLineString|Polygon|MultiPolygon>} feature feature to clip to the bbox
120200          * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order
120201          * @returns {Feature<LineString|MultiLineString|Polygon|MultiPolygon>} clipped Feature
120202          * @example
120203          * var bbox = [0, 0, 10, 10];
120204          * var poly = turf.polygon([[[2, 2], [8, 4], [12, 8], [3, 7], [2, 2]]]);
120205          *
120206          * var clipped = turf.bboxClip(poly, bbox);
120207          *
120208          * //addToMap
120209          * var addToMap = [bbox, poly, clipped]
120210          */
120211
120212         function bboxClip(feature, bbox) {
120213           var geom = getGeom(feature);
120214           var type = geom.type;
120215           var properties = feature.type === "Feature" ? feature.properties : {};
120216           var coords = geom.coordinates;
120217
120218           switch (type) {
120219             case "LineString":
120220             case "MultiLineString":
120221               {
120222                 var lines_1 = [];
120223
120224                 if (type === "LineString") {
120225                   coords = [coords];
120226                 }
120227
120228                 coords.forEach(function (line) {
120229                   lineclip(line, bbox, lines_1);
120230                 });
120231
120232                 if (lines_1.length === 1) {
120233                   return lineString(lines_1[0], properties);
120234                 }
120235
120236                 return multiLineString(lines_1, properties);
120237               }
120238
120239             case "Polygon":
120240               return polygon(clipPolygon(coords, bbox), properties);
120241
120242             case "MultiPolygon":
120243               return multiPolygon(coords.map(function (poly) {
120244                 return clipPolygon(poly, bbox);
120245               }), properties);
120246
120247             default:
120248               throw new Error("geometry " + type + " not supported");
120249           }
120250         }
120251
120252         function clipPolygon(rings, bbox) {
120253           var outRings = [];
120254
120255           for (var _i = 0, rings_1 = rings; _i < rings_1.length; _i++) {
120256             var ring = rings_1[_i];
120257             var clipped = polygonclip(ring, bbox);
120258
120259             if (clipped.length > 0) {
120260               if (clipped[0][0] !== clipped[clipped.length - 1][0] || clipped[0][1] !== clipped[clipped.length - 1][1]) {
120261                 clipped.push(clipped[0]);
120262               }
120263
120264               if (clipped.length >= 4) {
120265                 outRings.push(clipped);
120266               }
120267             }
120268           }
120269
120270           return outRings;
120271         }
120272
120273         var tiler = utilTiler().tileSize(512).margin(1);
120274         var dispatch = dispatch$8('loadedData');
120275
120276         var _vtCache;
120277
120278         function abortRequest(controller) {
120279           controller.abort();
120280         }
120281
120282         function vtToGeoJSON(data, tile, mergeCache) {
120283           var vectorTile$1 = new vectorTile.VectorTile(new pbf(data));
120284           var layers = Object.keys(vectorTile$1.layers);
120285
120286           if (!Array.isArray(layers)) {
120287             layers = [layers];
120288           }
120289
120290           var features = [];
120291           layers.forEach(function (layerID) {
120292             var layer = vectorTile$1.layers[layerID];
120293
120294             if (layer) {
120295               for (var i = 0; i < layer.length; i++) {
120296                 var feature = layer.feature(i).toGeoJSON(tile.xyz[0], tile.xyz[1], tile.xyz[2]);
120297                 var geometry = feature.geometry; // Treat all Polygons as MultiPolygons
120298
120299                 if (geometry.type === 'Polygon') {
120300                   geometry.type = 'MultiPolygon';
120301                   geometry.coordinates = [geometry.coordinates];
120302                 }
120303
120304                 var isClipped = false; // Clip to tile bounds
120305
120306                 if (geometry.type === 'MultiPolygon') {
120307                   var featureClip = bboxClip(feature, tile.extent.rectangle());
120308
120309                   if (!fastDeepEqual(feature.geometry, featureClip.geometry)) {
120310                     // feature = featureClip;
120311                     isClipped = true;
120312                   }
120313
120314                   if (!feature.geometry.coordinates.length) continue; // not actually on this tile
120315
120316                   if (!feature.geometry.coordinates[0].length) continue; // not actually on this tile
120317                 } // Generate some unique IDs and add some metadata
120318
120319
120320                 var featurehash = utilHashcode(fastJsonStableStringify(feature));
120321                 var propertyhash = utilHashcode(fastJsonStableStringify(feature.properties || {}));
120322                 feature.__layerID__ = layerID.replace(/[^_a-zA-Z0-9\-]/g, '_');
120323                 feature.__featurehash__ = featurehash;
120324                 feature.__propertyhash__ = propertyhash;
120325                 features.push(feature); // Clipped Polygons at same zoom with identical properties can get merged
120326
120327                 if (isClipped && geometry.type === 'MultiPolygon') {
120328                   var merged = mergeCache[propertyhash];
120329
120330                   if (merged && merged.length) {
120331                     var other = merged[0];
120332                     var coords = index.union(feature.geometry.coordinates, other.geometry.coordinates);
120333
120334                     if (!coords || !coords.length) {
120335                       continue; // something failed in polygon union
120336                     }
120337
120338                     merged.push(feature);
120339
120340                     for (var j = 0; j < merged.length; j++) {
120341                       // all these features get...
120342                       merged[j].geometry.coordinates = coords; // same coords
120343
120344                       merged[j].__featurehash__ = featurehash; // same hash, so deduplication works
120345                     }
120346                   } else {
120347                     mergeCache[propertyhash] = [feature];
120348                   }
120349                 }
120350               }
120351             }
120352           });
120353           return features;
120354         }
120355
120356         function loadTile(source, tile) {
120357           if (source.loaded[tile.id] || source.inflight[tile.id]) return;
120358           var url = source.template.replace('{x}', tile.xyz[0]).replace('{y}', tile.xyz[1]) // TMS-flipped y coordinate
120359           .replace(/\{[t-]y\}/, Math.pow(2, tile.xyz[2]) - tile.xyz[1] - 1).replace(/\{z(oom)?\}/, tile.xyz[2]).replace(/\{switch:([^}]+)\}/, function (s, r) {
120360             var subdomains = r.split(',');
120361             return subdomains[(tile.xyz[0] + tile.xyz[1]) % subdomains.length];
120362           });
120363           var controller = new AbortController();
120364           source.inflight[tile.id] = controller;
120365           fetch(url, {
120366             signal: controller.signal
120367           }).then(function (response) {
120368             if (!response.ok) {
120369               throw new Error(response.status + ' ' + response.statusText);
120370             }
120371
120372             source.loaded[tile.id] = [];
120373             delete source.inflight[tile.id];
120374             return response.arrayBuffer();
120375           }).then(function (data) {
120376             if (!data) {
120377               throw new Error('No Data');
120378             }
120379
120380             var z = tile.xyz[2];
120381
120382             if (!source.canMerge[z]) {
120383               source.canMerge[z] = {}; // initialize mergeCache
120384             }
120385
120386             source.loaded[tile.id] = vtToGeoJSON(data, tile, source.canMerge[z]);
120387             dispatch.call('loadedData');
120388           })["catch"](function () {
120389             source.loaded[tile.id] = [];
120390             delete source.inflight[tile.id];
120391           });
120392         }
120393
120394         var serviceVectorTile = {
120395           init: function init() {
120396             if (!_vtCache) {
120397               this.reset();
120398             }
120399
120400             this.event = utilRebind(this, dispatch, 'on');
120401           },
120402           reset: function reset() {
120403             for (var sourceID in _vtCache) {
120404               var source = _vtCache[sourceID];
120405
120406               if (source && source.inflight) {
120407                 Object.values(source.inflight).forEach(abortRequest);
120408               }
120409             }
120410
120411             _vtCache = {};
120412           },
120413           addSource: function addSource(sourceID, template) {
120414             _vtCache[sourceID] = {
120415               template: template,
120416               inflight: {},
120417               loaded: {},
120418               canMerge: {}
120419             };
120420             return _vtCache[sourceID];
120421           },
120422           data: function data(sourceID, projection) {
120423             var source = _vtCache[sourceID];
120424             if (!source) return [];
120425             var tiles = tiler.getTiles(projection);
120426             var seen = {};
120427             var results = [];
120428
120429             for (var i = 0; i < tiles.length; i++) {
120430               var features = source.loaded[tiles[i].id];
120431               if (!features || !features.length) continue;
120432
120433               for (var j = 0; j < features.length; j++) {
120434                 var feature = features[j];
120435                 var hash = feature.__featurehash__;
120436                 if (seen[hash]) continue;
120437                 seen[hash] = true; // return a shallow copy, because the hash may change
120438                 // later if this feature gets merged with another
120439
120440                 results.push(Object.assign({}, feature)); // shallow copy
120441               }
120442             }
120443
120444             return results;
120445           },
120446           loadTiles: function loadTiles(sourceID, template, projection) {
120447             var source = _vtCache[sourceID];
120448
120449             if (!source) {
120450               source = this.addSource(sourceID, template);
120451             }
120452
120453             var tiles = tiler.getTiles(projection); // abort inflight requests that are no longer needed
120454
120455             Object.keys(source.inflight).forEach(function (k) {
120456               var wanted = tiles.find(function (tile) {
120457                 return k === tile.id;
120458               });
120459
120460               if (!wanted) {
120461                 abortRequest(source.inflight[k]);
120462                 delete source.inflight[k];
120463               }
120464             });
120465             tiles.forEach(function (tile) {
120466               loadTile(source, tile);
120467             });
120468           },
120469           cache: function cache() {
120470             return _vtCache;
120471           }
120472         };
120473
120474         var apibase = 'https://www.wikidata.org/w/api.php?';
120475         var _wikidataCache = {};
120476         var serviceWikidata = {
120477           init: function init() {},
120478           reset: function reset() {
120479             _wikidataCache = {};
120480           },
120481           // Search for Wikidata items matching the query
120482           itemsForSearchQuery: function itemsForSearchQuery(query, callback) {
120483             if (!query) {
120484               if (callback) callback('No query', {});
120485               return;
120486             }
120487
120488             var lang = this.languagesToQuery()[0];
120489             var url = apibase + utilQsString({
120490               action: 'wbsearchentities',
120491               format: 'json',
120492               formatversion: 2,
120493               search: query,
120494               type: 'item',
120495               // the language to search
120496               language: lang,
120497               // the language for the label and description in the result
120498               uselang: lang,
120499               limit: 10,
120500               origin: '*'
120501             });
120502             d3_json(url).then(function (result) {
120503               if (result && result.error) {
120504                 throw new Error(result.error);
120505               }
120506
120507               if (callback) callback(null, result.search || {});
120508             })["catch"](function (err) {
120509               if (callback) callback(err.message, {});
120510             });
120511           },
120512           // Given a Wikipedia language and article title,
120513           // return an array of corresponding Wikidata entities.
120514           itemsByTitle: function itemsByTitle(lang, title, callback) {
120515             if (!title) {
120516               if (callback) callback('No title', {});
120517               return;
120518             }
120519
120520             lang = lang || 'en';
120521             var url = apibase + utilQsString({
120522               action: 'wbgetentities',
120523               format: 'json',
120524               formatversion: 2,
120525               sites: lang.replace(/-/g, '_') + 'wiki',
120526               titles: title,
120527               languages: 'en',
120528               // shrink response by filtering to one language
120529               origin: '*'
120530             });
120531             d3_json(url).then(function (result) {
120532               if (result && result.error) {
120533                 throw new Error(result.error);
120534               }
120535
120536               if (callback) callback(null, result.entities || {});
120537             })["catch"](function (err) {
120538               if (callback) callback(err.message, {});
120539             });
120540           },
120541           languagesToQuery: function languagesToQuery() {
120542             return _mainLocalizer.localeCodes().map(function (code) {
120543               return code.toLowerCase();
120544             }).filter(function (code) {
120545               // HACK: en-us isn't a wikidata language. We should really be filtering by
120546               // the languages known to be supported by wikidata.
120547               return code !== 'en-us';
120548             });
120549           },
120550           entityByQID: function entityByQID(qid, callback) {
120551             if (!qid) {
120552               callback('No qid', {});
120553               return;
120554             }
120555
120556             if (_wikidataCache[qid]) {
120557               if (callback) callback(null, _wikidataCache[qid]);
120558               return;
120559             }
120560
120561             var langs = this.languagesToQuery();
120562             var url = apibase + utilQsString({
120563               action: 'wbgetentities',
120564               format: 'json',
120565               formatversion: 2,
120566               ids: qid,
120567               props: 'labels|descriptions|claims|sitelinks',
120568               sitefilter: langs.map(function (d) {
120569                 return d + 'wiki';
120570               }).join('|'),
120571               languages: langs.join('|'),
120572               languagefallback: 1,
120573               origin: '*'
120574             });
120575             d3_json(url).then(function (result) {
120576               if (result && result.error) {
120577                 throw new Error(result.error);
120578               }
120579
120580               if (callback) callback(null, result.entities[qid] || {});
120581             })["catch"](function (err) {
120582               if (callback) callback(err.message, {});
120583             });
120584           },
120585           // Pass `params` object of the form:
120586           // {
120587           //   qid: 'string'      // brand wikidata  (e.g. 'Q37158')
120588           // }
120589           //
120590           // Get an result object used to display tag documentation
120591           // {
120592           //   title:        'string',
120593           //   description:  'string',
120594           //   editURL:      'string',
120595           //   imageURL:     'string',
120596           //   wiki:         { title: 'string', text: 'string', url: 'string' }
120597           // }
120598           //
120599           getDocs: function getDocs(params, callback) {
120600             var langs = this.languagesToQuery();
120601             this.entityByQID(params.qid, function (err, entity) {
120602               if (err || !entity) {
120603                 callback(err || 'No entity');
120604                 return;
120605               }
120606
120607               var i;
120608               var description;
120609
120610               for (i in langs) {
120611                 var code = langs[i];
120612
120613                 if (entity.descriptions[code] && entity.descriptions[code].language === code) {
120614                   description = entity.descriptions[code];
120615                   break;
120616                 }
120617               }
120618
120619               if (!description && Object.values(entity.descriptions).length) description = Object.values(entity.descriptions)[0]; // prepare result
120620
120621               var result = {
120622                 title: entity.id,
120623                 description: description ? description.value : '',
120624                 descriptionLocaleCode: description ? description.language : '',
120625                 editURL: 'https://www.wikidata.org/wiki/' + entity.id
120626               }; // add image
120627
120628               if (entity.claims) {
120629                 var imageroot = 'https://commons.wikimedia.org/w/index.php';
120630                 var props = ['P154', 'P18']; // logo image, image
120631
120632                 var prop, image;
120633
120634                 for (i = 0; i < props.length; i++) {
120635                   prop = entity.claims[props[i]];
120636
120637                   if (prop && Object.keys(prop).length > 0) {
120638                     image = prop[Object.keys(prop)[0]].mainsnak.datavalue.value;
120639
120640                     if (image) {
120641                       result.imageURL = imageroot + '?' + utilQsString({
120642                         title: 'Special:Redirect/file/' + image,
120643                         width: 400
120644                       });
120645                       break;
120646                     }
120647                   }
120648                 }
120649               }
120650
120651               if (entity.sitelinks) {
120652                 var englishLocale = _mainLocalizer.languageCode().toLowerCase() === 'en'; // must be one of these that we requested..
120653
120654                 for (i = 0; i < langs.length; i++) {
120655                   // check each, in order of preference
120656                   var w = langs[i] + 'wiki';
120657
120658                   if (entity.sitelinks[w]) {
120659                     var title = entity.sitelinks[w].title;
120660                     var tKey = 'inspector.wiki_reference';
120661
120662                     if (!englishLocale && langs[i] === 'en') {
120663                       // user's locale isn't English but
120664                       tKey = 'inspector.wiki_en_reference'; // we are sending them to enwiki anyway..
120665                     }
120666
120667                     result.wiki = {
120668                       title: title,
120669                       text: tKey,
120670                       url: 'https://' + langs[i] + '.wikipedia.org/wiki/' + title.replace(/ /g, '_')
120671                     };
120672                     break;
120673                   }
120674                 }
120675               }
120676
120677               callback(null, result);
120678             });
120679           }
120680         };
120681
120682         var endpoint = 'https://en.wikipedia.org/w/api.php?';
120683         var serviceWikipedia = {
120684           init: function init() {},
120685           reset: function reset() {},
120686           search: function search(lang, query, callback) {
120687             if (!query) {
120688               if (callback) callback('No Query', []);
120689               return;
120690             }
120691
120692             lang = lang || 'en';
120693             var url = endpoint.replace('en', lang) + utilQsString({
120694               action: 'query',
120695               list: 'search',
120696               srlimit: '10',
120697               srinfo: 'suggestion',
120698               format: 'json',
120699               origin: '*',
120700               srsearch: query
120701             });
120702             d3_json(url).then(function (result) {
120703               if (result && result.error) {
120704                 throw new Error(result.error);
120705               } else if (!result || !result.query || !result.query.search) {
120706                 throw new Error('No Results');
120707               }
120708
120709               if (callback) {
120710                 var titles = result.query.search.map(function (d) {
120711                   return d.title;
120712                 });
120713                 callback(null, titles);
120714               }
120715             })["catch"](function (err) {
120716               if (callback) callback(err, []);
120717             });
120718           },
120719           suggestions: function suggestions(lang, query, callback) {
120720             if (!query) {
120721               if (callback) callback('', []);
120722               return;
120723             }
120724
120725             lang = lang || 'en';
120726             var url = endpoint.replace('en', lang) + utilQsString({
120727               action: 'opensearch',
120728               namespace: 0,
120729               suggest: '',
120730               format: 'json',
120731               origin: '*',
120732               search: query
120733             });
120734             d3_json(url).then(function (result) {
120735               if (result && result.error) {
120736                 throw new Error(result.error);
120737               } else if (!result || result.length < 2) {
120738                 throw new Error('No Results');
120739               }
120740
120741               if (callback) callback(null, result[1] || []);
120742             })["catch"](function (err) {
120743               if (callback) callback(err.message, []);
120744             });
120745           },
120746           translations: function translations(lang, title, callback) {
120747             if (!title) {
120748               if (callback) callback('No Title');
120749               return;
120750             }
120751
120752             var url = endpoint.replace('en', lang) + utilQsString({
120753               action: 'query',
120754               prop: 'langlinks',
120755               format: 'json',
120756               origin: '*',
120757               lllimit: 500,
120758               titles: title
120759             });
120760             d3_json(url).then(function (result) {
120761               if (result && result.error) {
120762                 throw new Error(result.error);
120763               } else if (!result || !result.query || !result.query.pages) {
120764                 throw new Error('No Results');
120765               }
120766
120767               if (callback) {
120768                 var list = result.query.pages[Object.keys(result.query.pages)[0]];
120769                 var translations = {};
120770
120771                 if (list && list.langlinks) {
120772                   list.langlinks.forEach(function (d) {
120773                     translations[d.lang] = d['*'];
120774                   });
120775                 }
120776
120777                 callback(null, translations);
120778               }
120779             })["catch"](function (err) {
120780               if (callback) callback(err.message);
120781             });
120782           }
120783         };
120784
120785         var services = {
120786           geocoder: serviceNominatim,
120787           keepRight: serviceKeepRight,
120788           improveOSM: serviceImproveOSM,
120789           osmose: serviceOsmose,
120790           mapillary: serviceMapillary,
120791           nsi: serviceNsi,
120792           kartaview: serviceKartaview,
120793           osm: serviceOsm,
120794           osmWikibase: serviceOsmWikibase,
120795           maprules: serviceMapRules,
120796           streetside: serviceStreetside,
120797           taginfo: serviceTaginfo,
120798           vectorTile: serviceVectorTile,
120799           wikidata: serviceWikidata,
120800           wikipedia: serviceWikipedia
120801         };
120802
120803         function modeDragNote(context) {
120804           var mode = {
120805             id: 'drag-note',
120806             button: 'browse'
120807           };
120808           var edit = behaviorEdit(context);
120809
120810           var _nudgeInterval;
120811
120812           var _lastLoc;
120813
120814           var _note; // most current note.. dragged note may have stale datum.
120815
120816
120817           function startNudge(d3_event, nudge) {
120818             if (_nudgeInterval) window.clearInterval(_nudgeInterval);
120819             _nudgeInterval = window.setInterval(function () {
120820               context.map().pan(nudge);
120821               doMove(d3_event, nudge);
120822             }, 50);
120823           }
120824
120825           function stopNudge() {
120826             if (_nudgeInterval) {
120827               window.clearInterval(_nudgeInterval);
120828               _nudgeInterval = null;
120829             }
120830           }
120831
120832           function origin(note) {
120833             return context.projection(note.loc);
120834           }
120835
120836           function start(d3_event, note) {
120837             _note = note;
120838             var osm = services.osm;
120839
120840             if (osm) {
120841               // Get latest note from cache.. The marker may have a stale datum bound to it
120842               // and dragging it around can sometimes delete the users note comment.
120843               _note = osm.getNote(_note.id);
120844             }
120845
120846             context.surface().selectAll('.note-' + _note.id).classed('active', true);
120847             context.perform(actionNoop());
120848             context.enter(mode);
120849             context.selectedNoteID(_note.id);
120850           }
120851
120852           function move(d3_event, entity, point) {
120853             d3_event.stopPropagation();
120854             _lastLoc = context.projection.invert(point);
120855             doMove(d3_event);
120856             var nudge = geoViewportEdge(point, context.map().dimensions());
120857
120858             if (nudge) {
120859               startNudge(d3_event, nudge);
120860             } else {
120861               stopNudge();
120862             }
120863           }
120864
120865           function doMove(d3_event, nudge) {
120866             nudge = nudge || [0, 0];
120867             var currPoint = d3_event && d3_event.point || context.projection(_lastLoc);
120868             var currMouse = geoVecSubtract(currPoint, nudge);
120869             var loc = context.projection.invert(currMouse);
120870             _note = _note.move(loc);
120871             var osm = services.osm;
120872
120873             if (osm) {
120874               osm.replaceNote(_note); // update note cache
120875             }
120876
120877             context.replace(actionNoop()); // trigger redraw
120878           }
120879
120880           function end() {
120881             context.replace(actionNoop()); // trigger redraw
120882
120883             context.selectedNoteID(_note.id).enter(modeSelectNote(context, _note.id));
120884           }
120885
120886           var drag = behaviorDrag().selector('.layer-touch.markers .target.note.new').surface(context.container().select('.main-map').node()).origin(origin).on('start', start).on('move', move).on('end', end);
120887
120888           mode.enter = function () {
120889             context.install(edit);
120890           };
120891
120892           mode.exit = function () {
120893             context.ui().sidebar.hover.cancel();
120894             context.uninstall(edit);
120895             context.surface().selectAll('.active').classed('active', false);
120896             stopNudge();
120897           };
120898
120899           mode.behavior = drag;
120900           return mode;
120901         }
120902
120903         function modeSelectData(context, selectedDatum) {
120904           var mode = {
120905             id: 'select-data',
120906             button: 'browse'
120907           };
120908           var keybinding = utilKeybinding('select-data');
120909           var dataEditor = uiDataEditor(context);
120910           var behaviors = [behaviorBreathe(), behaviorHover(context), behaviorSelect(context), behaviorLasso(context), modeDragNode(context).behavior, modeDragNote(context).behavior]; // class the data as selected, or return to browse mode if the data is gone
120911
120912           function selectData(d3_event, drawn) {
120913             var selection = context.surface().selectAll('.layer-mapdata .data' + selectedDatum.__featurehash__);
120914
120915             if (selection.empty()) {
120916               // Return to browse mode if selected DOM elements have
120917               // disappeared because the user moved them out of view..
120918               var source = d3_event && d3_event.type === 'zoom' && d3_event.sourceEvent;
120919
120920               if (drawn && source && (source.type === 'pointermove' || source.type === 'mousemove' || source.type === 'touchmove')) {
120921                 context.enter(modeBrowse(context));
120922               }
120923             } else {
120924               selection.classed('selected', true);
120925             }
120926           }
120927
120928           function esc() {
120929             if (context.container().select('.combobox').size()) return;
120930             context.enter(modeBrowse(context));
120931           }
120932
120933           mode.zoomToSelected = function () {
120934             var extent = geoExtent(d3_geoBounds(selectedDatum));
120935             context.map().centerZoomEase(extent.center(), context.map().trimmedExtentZoom(extent));
120936           };
120937
120938           mode.enter = function () {
120939             behaviors.forEach(context.install);
120940             keybinding.on(_t('inspector.zoom_to.key'), mode.zoomToSelected).on('⎋', esc, true);
120941             select(document).call(keybinding);
120942             selectData();
120943             var sidebar = context.ui().sidebar;
120944             sidebar.show(dataEditor.datum(selectedDatum)); // expand the sidebar, avoid obscuring the data if needed
120945
120946             var extent = geoExtent(d3_geoBounds(selectedDatum));
120947             sidebar.expand(sidebar.intersects(extent));
120948             context.map().on('drawn.select-data', selectData);
120949           };
120950
120951           mode.exit = function () {
120952             behaviors.forEach(context.uninstall);
120953             select(document).call(keybinding.unbind);
120954             context.surface().selectAll('.layer-mapdata .selected').classed('selected hover', false);
120955             context.map().on('drawn.select-data', null);
120956             context.ui().sidebar.hide();
120957           };
120958
120959           return mode;
120960         }
120961
120962         function behaviorSelect(context) {
120963           var _tolerancePx = 4; // see also behaviorDrag
120964
120965           var _lastMouseEvent = null;
120966           var _showMenu = false;
120967           var _downPointers = {};
120968           var _longPressTimeout = null;
120969           var _lastInteractionType = null; // the id of the down pointer that's enabling multiselection while down
120970
120971           var _multiselectionPointerId = null; // use pointer events on supported platforms; fallback to mouse events
120972
120973           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
120974
120975           function keydown(d3_event) {
120976             if (d3_event.keyCode === 32) {
120977               // don't react to spacebar events during text input
120978               var activeNode = document.activeElement;
120979               if (activeNode && new Set(['INPUT', 'TEXTAREA']).has(activeNode.nodeName)) return;
120980             }
120981
120982             if (d3_event.keyCode === 93 || // context menu key
120983             d3_event.keyCode === 32) {
120984               // spacebar
120985               d3_event.preventDefault();
120986             }
120987
120988             if (d3_event.repeat) return; // ignore repeated events for held keys
120989             // if any key is pressed the user is probably doing something other than long-pressing
120990
120991             cancelLongPress();
120992
120993             if (d3_event.shiftKey) {
120994               context.surface().classed('behavior-multiselect', true);
120995             }
120996
120997             if (d3_event.keyCode === 32) {
120998               // spacebar
120999               if (!_downPointers.spacebar && _lastMouseEvent) {
121000                 cancelLongPress();
121001                 _longPressTimeout = window.setTimeout(didLongPress, 500, 'spacebar', 'spacebar');
121002                 _downPointers.spacebar = {
121003                   firstEvent: _lastMouseEvent,
121004                   lastEvent: _lastMouseEvent
121005                 };
121006               }
121007             }
121008           }
121009
121010           function keyup(d3_event) {
121011             cancelLongPress();
121012
121013             if (!d3_event.shiftKey) {
121014               context.surface().classed('behavior-multiselect', false);
121015             }
121016
121017             if (d3_event.keyCode === 93) {
121018               // context menu key
121019               d3_event.preventDefault();
121020               _lastInteractionType = 'menukey';
121021               contextmenu(d3_event);
121022             } else if (d3_event.keyCode === 32) {
121023               // spacebar
121024               var pointer = _downPointers.spacebar;
121025
121026               if (pointer) {
121027                 delete _downPointers.spacebar;
121028                 if (pointer.done) return;
121029                 d3_event.preventDefault();
121030                 _lastInteractionType = 'spacebar';
121031                 click(pointer.firstEvent, pointer.lastEvent, 'spacebar');
121032               }
121033             }
121034           }
121035
121036           function pointerdown(d3_event) {
121037             var id = (d3_event.pointerId || 'mouse').toString();
121038             cancelLongPress();
121039             if (d3_event.buttons && d3_event.buttons !== 1) return;
121040             context.ui().closeEditMenu();
121041             _longPressTimeout = window.setTimeout(didLongPress, 500, id, 'longdown-' + (d3_event.pointerType || 'mouse'));
121042             _downPointers[id] = {
121043               firstEvent: d3_event,
121044               lastEvent: d3_event
121045             };
121046           }
121047
121048           function didLongPress(id, interactionType) {
121049             var pointer = _downPointers[id];
121050             if (!pointer) return;
121051
121052             for (var i in _downPointers) {
121053               // don't allow this or any currently down pointer to trigger another click
121054               _downPointers[i].done = true;
121055             } // treat long presses like right-clicks
121056
121057
121058             _longPressTimeout = null;
121059             _lastInteractionType = interactionType;
121060             _showMenu = true;
121061             click(pointer.firstEvent, pointer.lastEvent, id);
121062           }
121063
121064           function pointermove(d3_event) {
121065             var id = (d3_event.pointerId || 'mouse').toString();
121066
121067             if (_downPointers[id]) {
121068               _downPointers[id].lastEvent = d3_event;
121069             }
121070
121071             if (!d3_event.pointerType || d3_event.pointerType === 'mouse') {
121072               _lastMouseEvent = d3_event;
121073
121074               if (_downPointers.spacebar) {
121075                 _downPointers.spacebar.lastEvent = d3_event;
121076               }
121077             }
121078           }
121079
121080           function pointerup(d3_event) {
121081             var id = (d3_event.pointerId || 'mouse').toString();
121082             var pointer = _downPointers[id];
121083             if (!pointer) return;
121084             delete _downPointers[id];
121085
121086             if (_multiselectionPointerId === id) {
121087               _multiselectionPointerId = null;
121088             }
121089
121090             if (pointer.done) return;
121091             click(pointer.firstEvent, d3_event, id);
121092           }
121093
121094           function pointercancel(d3_event) {
121095             var id = (d3_event.pointerId || 'mouse').toString();
121096             if (!_downPointers[id]) return;
121097             delete _downPointers[id];
121098
121099             if (_multiselectionPointerId === id) {
121100               _multiselectionPointerId = null;
121101             }
121102           }
121103
121104           function contextmenu(d3_event) {
121105             d3_event.preventDefault();
121106
121107             if (!+d3_event.clientX && !+d3_event.clientY) {
121108               if (_lastMouseEvent) {
121109                 d3_event.sourceEvent = _lastMouseEvent;
121110               } else {
121111                 return;
121112               }
121113             } else {
121114               _lastMouseEvent = d3_event;
121115               _lastInteractionType = 'rightclick';
121116             }
121117
121118             _showMenu = true;
121119             click(d3_event, d3_event);
121120           }
121121
121122           function click(firstEvent, lastEvent, pointerId) {
121123             cancelLongPress();
121124             var mapNode = context.container().select('.main-map').node(); // Use the `main-map` coordinate system since the surface and supersurface
121125             // are transformed when drag-panning.
121126
121127             var pointGetter = utilFastMouse(mapNode);
121128             var p1 = pointGetter(firstEvent);
121129             var p2 = pointGetter(lastEvent);
121130             var dist = geoVecLength(p1, p2);
121131
121132             if (dist > _tolerancePx || !mapContains(lastEvent)) {
121133               resetProperties();
121134               return;
121135             }
121136
121137             var targetDatum = lastEvent.target.__data__;
121138             var multiselectEntityId;
121139
121140             if (!_multiselectionPointerId) {
121141               // If a different pointer than the one triggering this click is down on a
121142               // feature, treat this and all future clicks as multiselection until that
121143               // pointer is raised.
121144               var selectPointerInfo = pointerDownOnSelection(pointerId);
121145
121146               if (selectPointerInfo) {
121147                 _multiselectionPointerId = selectPointerInfo.pointerId; // if the other feature isn't selected yet, make sure we select it
121148
121149                 multiselectEntityId = !selectPointerInfo.selected && selectPointerInfo.entityId;
121150                 _downPointers[selectPointerInfo.pointerId].done = true;
121151               }
121152             } // support multiselect if data is already selected
121153
121154
121155             var isMultiselect = context.mode().id === 'select' && ( // and shift key is down
121156             lastEvent && lastEvent.shiftKey || // or we're lasso-selecting
121157             context.surface().select('.lasso').node() || // or a pointer is down over a selected feature
121158             _multiselectionPointerId && !multiselectEntityId);
121159
121160             processClick(targetDatum, isMultiselect, p2, multiselectEntityId);
121161
121162             function mapContains(event) {
121163               var rect = mapNode.getBoundingClientRect();
121164               return event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom;
121165             }
121166
121167             function pointerDownOnSelection(skipPointerId) {
121168               var mode = context.mode();
121169               var selectedIDs = mode.id === 'select' ? mode.selectedIDs() : [];
121170
121171               for (var pointerId in _downPointers) {
121172                 if (pointerId === 'spacebar' || pointerId === skipPointerId) continue;
121173                 var pointerInfo = _downPointers[pointerId];
121174                 var p1 = pointGetter(pointerInfo.firstEvent);
121175                 var p2 = pointGetter(pointerInfo.lastEvent);
121176                 if (geoVecLength(p1, p2) > _tolerancePx) continue;
121177                 var datum = pointerInfo.firstEvent.target.__data__;
121178                 var entity = datum && datum.properties && datum.properties.entity || datum;
121179
121180                 if (context.graph().hasEntity(entity.id)) {
121181                   return {
121182                     pointerId: pointerId,
121183                     entityId: entity.id,
121184                     selected: selectedIDs.indexOf(entity.id) !== -1
121185                   };
121186                 }
121187               }
121188
121189               return null;
121190             }
121191           }
121192
121193           function processClick(datum, isMultiselect, point, alsoSelectId) {
121194             var mode = context.mode();
121195             var showMenu = _showMenu;
121196             var interactionType = _lastInteractionType;
121197             var entity = datum && datum.properties && datum.properties.entity;
121198             if (entity) datum = entity;
121199
121200             if (datum && datum.type === 'midpoint') {
121201               // treat targeting midpoints as if targeting the parent way
121202               datum = datum.parents[0];
121203             }
121204
121205             var newMode;
121206
121207             if (datum instanceof osmEntity) {
121208               // targeting an entity
121209               var selectedIDs = context.selectedIDs();
121210               context.selectedNoteID(null);
121211               context.selectedErrorID(null);
121212
121213               if (!isMultiselect) {
121214                 // don't change the selection if we're toggling the menu atop a multiselection
121215                 if (!showMenu || selectedIDs.length <= 1 || selectedIDs.indexOf(datum.id) === -1) {
121216                   if (alsoSelectId === datum.id) alsoSelectId = null;
121217                   selectedIDs = (alsoSelectId ? [alsoSelectId] : []).concat([datum.id]); // always enter modeSelect even if the entity is already
121218                   // selected since listeners may expect `context.enter` events,
121219                   // e.g. in the walkthrough
121220
121221                   newMode = mode.id === 'select' ? mode.selectedIDs(selectedIDs) : modeSelect(context, selectedIDs).selectBehavior(behavior);
121222                   context.enter(newMode);
121223                 }
121224               } else {
121225                 if (selectedIDs.indexOf(datum.id) !== -1) {
121226                   // clicked entity is already in the selectedIDs list..
121227                   if (!showMenu) {
121228                     // deselect clicked entity, then reenter select mode or return to browse mode..
121229                     selectedIDs = selectedIDs.filter(function (id) {
121230                       return id !== datum.id;
121231                     });
121232                     newMode = selectedIDs.length ? mode.selectedIDs(selectedIDs) : modeBrowse(context).selectBehavior(behavior);
121233                     context.enter(newMode);
121234                   }
121235                 } else {
121236                   // clicked entity is not in the selected list, add it..
121237                   selectedIDs = selectedIDs.concat([datum.id]);
121238                   newMode = mode.selectedIDs(selectedIDs);
121239                   context.enter(newMode);
121240                 }
121241               }
121242             } else if (datum && datum.__featurehash__ && !isMultiselect) {
121243               // targeting custom data
121244               context.selectedNoteID(null).enter(modeSelectData(context, datum));
121245             } else if (datum instanceof osmNote && !isMultiselect) {
121246               // targeting a note
121247               context.selectedNoteID(datum.id).enter(modeSelectNote(context, datum.id));
121248             } else if (datum instanceof QAItem & !isMultiselect) {
121249               // targeting an external QA issue
121250               context.selectedErrorID(datum.id).enter(modeSelectError(context, datum.id, datum.service));
121251             } else {
121252               // targeting nothing
121253               context.selectedNoteID(null);
121254               context.selectedErrorID(null);
121255
121256               if (!isMultiselect && mode.id !== 'browse') {
121257                 context.enter(modeBrowse(context));
121258               }
121259             }
121260
121261             context.ui().closeEditMenu(); // always request to show the edit menu in case the mode needs it
121262
121263             if (showMenu) context.ui().showEditMenu(point, interactionType);
121264             resetProperties();
121265           }
121266
121267           function cancelLongPress() {
121268             if (_longPressTimeout) window.clearTimeout(_longPressTimeout);
121269             _longPressTimeout = null;
121270           }
121271
121272           function resetProperties() {
121273             cancelLongPress();
121274             _showMenu = false;
121275             _lastInteractionType = null; // don't reset _lastMouseEvent since it might still be useful
121276           }
121277
121278           function behavior(selection) {
121279             resetProperties();
121280             _lastMouseEvent = context.map().lastPointerEvent();
121281             select(window).on('keydown.select', keydown).on('keyup.select', keyup).on(_pointerPrefix + 'move.select', pointermove, true).on(_pointerPrefix + 'up.select', pointerup, true).on('pointercancel.select', pointercancel, true).on('contextmenu.select-window', function (d3_event) {
121282               // Edge and IE really like to show the contextmenu on the
121283               // menubar when user presses a keyboard menu button
121284               // even after we've already preventdefaulted the key event.
121285               var e = d3_event;
121286
121287               if (+e.clientX === 0 && +e.clientY === 0) {
121288                 d3_event.preventDefault();
121289               }
121290             });
121291             selection.on(_pointerPrefix + 'down.select', pointerdown).on('contextmenu.select', contextmenu);
121292             /*if (d3_event && d3_event.shiftKey) {
121293                 context.surface()
121294                     .classed('behavior-multiselect', true);
121295             }*/
121296           }
121297
121298           behavior.off = function (selection) {
121299             cancelLongPress();
121300             select(window).on('keydown.select', null).on('keyup.select', null).on('contextmenu.select-window', null).on(_pointerPrefix + 'move.select', null, true).on(_pointerPrefix + 'up.select', null, true).on('pointercancel.select', null, true);
121301             selection.on(_pointerPrefix + 'down.select', null).on('contextmenu.select', null);
121302             context.surface().classed('behavior-multiselect', false);
121303           };
121304
121305           return behavior;
121306         }
121307
121308         function operationContinue(context, selectedIDs) {
121309           var _entities = selectedIDs.map(function (id) {
121310             return context.graph().entity(id);
121311           });
121312
121313           var _geometries = Object.assign({
121314             line: [],
121315             vertex: []
121316           }, utilArrayGroupBy(_entities, function (entity) {
121317             return entity.geometry(context.graph());
121318           }));
121319
121320           var _vertex = _geometries.vertex.length && _geometries.vertex[0];
121321
121322           function candidateWays() {
121323             return _vertex ? context.graph().parentWays(_vertex).filter(function (parent) {
121324               return parent.geometry(context.graph()) === 'line' && !parent.isClosed() && parent.affix(_vertex.id) && (_geometries.line.length === 0 || _geometries.line[0] === parent);
121325             }) : [];
121326           }
121327
121328           var _candidates = candidateWays();
121329
121330           var operation = function operation() {
121331             var candidate = _candidates[0];
121332             context.enter(modeDrawLine(context, candidate.id, context.graph(), 'line', candidate.affix(_vertex.id), true));
121333           };
121334
121335           operation.relatedEntityIds = function () {
121336             return _candidates.length ? [_candidates[0].id] : [];
121337           };
121338
121339           operation.available = function () {
121340             return _geometries.vertex.length === 1 && _geometries.line.length <= 1 && !context.features().hasHiddenConnections(_vertex, context.graph());
121341           };
121342
121343           operation.disabled = function () {
121344             if (_candidates.length === 0) {
121345               return 'not_eligible';
121346             } else if (_candidates.length > 1) {
121347               return 'multiple';
121348             }
121349
121350             return false;
121351           };
121352
121353           operation.tooltip = function () {
121354             var disable = operation.disabled();
121355             return disable ? _t('operations.continue.' + disable) : _t('operations.continue.description');
121356           };
121357
121358           operation.annotation = function () {
121359             return _t('operations.continue.annotation.line');
121360           };
121361
121362           operation.id = 'continue';
121363           operation.keys = [_t('operations.continue.key')];
121364           operation.title = _t('operations.continue.title');
121365           operation.behavior = behaviorOperation(context).which(operation);
121366           return operation;
121367         }
121368
121369         function operationCopy(context, selectedIDs) {
121370           function getFilteredIdsToCopy() {
121371             return selectedIDs.filter(function (selectedID) {
121372               var entity = context.graph().hasEntity(selectedID); // don't copy untagged vertices separately from ways
121373
121374               return entity.hasInterestingTags() || entity.geometry(context.graph()) !== 'vertex';
121375             });
121376           }
121377
121378           var operation = function operation() {
121379             var graph = context.graph();
121380             var selected = groupEntities(getFilteredIdsToCopy(), graph);
121381             var canCopy = [];
121382             var skip = {};
121383             var entity;
121384             var i;
121385
121386             for (i = 0; i < selected.relation.length; i++) {
121387               entity = selected.relation[i];
121388
121389               if (!skip[entity.id] && entity.isComplete(graph)) {
121390                 canCopy.push(entity.id);
121391                 skip = getDescendants(entity.id, graph, skip);
121392               }
121393             }
121394
121395             for (i = 0; i < selected.way.length; i++) {
121396               entity = selected.way[i];
121397
121398               if (!skip[entity.id]) {
121399                 canCopy.push(entity.id);
121400                 skip = getDescendants(entity.id, graph, skip);
121401               }
121402             }
121403
121404             for (i = 0; i < selected.node.length; i++) {
121405               entity = selected.node[i];
121406
121407               if (!skip[entity.id]) {
121408                 canCopy.push(entity.id);
121409               }
121410             }
121411
121412             context.copyIDs(canCopy);
121413
121414             if (_point && (canCopy.length !== 1 || graph.entity(canCopy[0]).type !== 'node')) {
121415               // store the anchor coordinates if copying more than a single node
121416               context.copyLonLat(context.projection.invert(_point));
121417             } else {
121418               context.copyLonLat(null);
121419             }
121420           };
121421
121422           function groupEntities(ids, graph) {
121423             var entities = ids.map(function (id) {
121424               return graph.entity(id);
121425             });
121426             return Object.assign({
121427               relation: [],
121428               way: [],
121429               node: []
121430             }, utilArrayGroupBy(entities, 'type'));
121431           }
121432
121433           function getDescendants(id, graph, descendants) {
121434             var entity = graph.entity(id);
121435             var children;
121436             descendants = descendants || {};
121437
121438             if (entity.type === 'relation') {
121439               children = entity.members.map(function (m) {
121440                 return m.id;
121441               });
121442             } else if (entity.type === 'way') {
121443               children = entity.nodes;
121444             } else {
121445               children = [];
121446             }
121447
121448             for (var i = 0; i < children.length; i++) {
121449               if (!descendants[children[i]]) {
121450                 descendants[children[i]] = true;
121451                 descendants = getDescendants(children[i], graph, descendants);
121452               }
121453             }
121454
121455             return descendants;
121456           }
121457
121458           operation.available = function () {
121459             return getFilteredIdsToCopy().length > 0;
121460           };
121461
121462           operation.disabled = function () {
121463             var extent = utilTotalExtent(getFilteredIdsToCopy(), context.graph());
121464
121465             if (extent.percentContainedIn(context.map().extent()) < 0.8) {
121466               return 'too_large';
121467             }
121468
121469             return false;
121470           };
121471
121472           operation.availableForKeypress = function () {
121473             var selection = window.getSelection && window.getSelection(); // if the user has text selected then let them copy that, not the selected feature
121474
121475             return !selection || !selection.toString();
121476           };
121477
121478           operation.tooltip = function () {
121479             var disable = operation.disabled();
121480             return disable ? _t('operations.copy.' + disable, {
121481               n: selectedIDs.length
121482             }) : _t('operations.copy.description', {
121483               n: selectedIDs.length
121484             });
121485           };
121486
121487           operation.annotation = function () {
121488             return _t('operations.copy.annotation', {
121489               n: selectedIDs.length
121490             });
121491           };
121492
121493           var _point;
121494
121495           operation.point = function (val) {
121496             _point = val;
121497             return operation;
121498           };
121499
121500           operation.id = 'copy';
121501           operation.keys = [uiCmd('⌘C')];
121502           operation.title = _t('operations.copy.title');
121503           operation.behavior = behaviorOperation(context).which(operation);
121504           return operation;
121505         }
121506
121507         function operationDisconnect(context, selectedIDs) {
121508           var _vertexIDs = [];
121509           var _wayIDs = [];
121510           var _otherIDs = [];
121511           var _actions = [];
121512           selectedIDs.forEach(function (id) {
121513             var entity = context.entity(id);
121514
121515             if (entity.type === 'way') {
121516               _wayIDs.push(id);
121517             } else if (entity.geometry(context.graph()) === 'vertex') {
121518               _vertexIDs.push(id);
121519             } else {
121520               _otherIDs.push(id);
121521             }
121522           });
121523
121524           var _coords,
121525               _descriptionID = '',
121526               _annotationID = 'features';
121527
121528           var _disconnectingVertexIds = [];
121529           var _disconnectingWayIds = [];
121530
121531           if (_vertexIDs.length > 0) {
121532             // At the selected vertices, disconnect the selected ways, if any, else
121533             // disconnect all connected ways
121534             _disconnectingVertexIds = _vertexIDs;
121535
121536             _vertexIDs.forEach(function (vertexID) {
121537               var action = actionDisconnect(vertexID);
121538
121539               if (_wayIDs.length > 0) {
121540                 var waysIDsForVertex = _wayIDs.filter(function (wayID) {
121541                   var way = context.entity(wayID);
121542                   return way.nodes.indexOf(vertexID) !== -1;
121543                 });
121544
121545                 action.limitWays(waysIDsForVertex);
121546               }
121547
121548               _actions.push(action);
121549
121550               _disconnectingWayIds = _disconnectingWayIds.concat(context.graph().parentWays(context.graph().entity(vertexID)).map(function (d) {
121551                 return d.id;
121552               }));
121553             });
121554
121555             _disconnectingWayIds = utilArrayUniq(_disconnectingWayIds).filter(function (id) {
121556               return _wayIDs.indexOf(id) === -1;
121557             });
121558             _descriptionID += _actions.length === 1 ? 'single_point.' : 'multiple_points.';
121559
121560             if (_wayIDs.length === 1) {
121561               _descriptionID += 'single_way.' + context.graph().geometry(_wayIDs[0]);
121562             } else {
121563               _descriptionID += _wayIDs.length === 0 ? 'no_ways' : 'multiple_ways';
121564             }
121565           } else if (_wayIDs.length > 0) {
121566             // Disconnect the selected ways from each other, if they're connected,
121567             // else disconnect them from all connected ways
121568             var ways = _wayIDs.map(function (id) {
121569               return context.entity(id);
121570             });
121571
121572             var nodes = utilGetAllNodes(_wayIDs, context.graph());
121573             _coords = nodes.map(function (n) {
121574               return n.loc;
121575             }); // actions for connected nodes shared by at least two selected ways
121576
121577             var sharedActions = [];
121578             var sharedNodes = []; // actions for connected nodes
121579
121580             var unsharedActions = [];
121581             var unsharedNodes = [];
121582             nodes.forEach(function (node) {
121583               var action = actionDisconnect(node.id).limitWays(_wayIDs);
121584
121585               if (action.disabled(context.graph()) !== 'not_connected') {
121586                 var count = 0;
121587
121588                 for (var i in ways) {
121589                   var way = ways[i];
121590
121591                   if (way.nodes.indexOf(node.id) !== -1) {
121592                     count += 1;
121593                   }
121594
121595                   if (count > 1) break;
121596                 }
121597
121598                 if (count > 1) {
121599                   sharedActions.push(action);
121600                   sharedNodes.push(node);
121601                 } else {
121602                   unsharedActions.push(action);
121603                   unsharedNodes.push(node);
121604                 }
121605               }
121606             });
121607             _descriptionID += 'no_points.';
121608             _descriptionID += _wayIDs.length === 1 ? 'single_way.' : 'multiple_ways.';
121609
121610             if (sharedActions.length) {
121611               // if any nodes are shared, only disconnect the selected ways from each other
121612               _actions = sharedActions;
121613               _disconnectingVertexIds = sharedNodes.map(function (node) {
121614                 return node.id;
121615               });
121616               _descriptionID += 'conjoined';
121617               _annotationID = 'from_each_other';
121618             } else {
121619               // if no nodes are shared, disconnect the selected ways from all connected ways
121620               _actions = unsharedActions;
121621               _disconnectingVertexIds = unsharedNodes.map(function (node) {
121622                 return node.id;
121623               });
121624
121625               if (_wayIDs.length === 1) {
121626                 _descriptionID += context.graph().geometry(_wayIDs[0]);
121627               } else {
121628                 _descriptionID += 'separate';
121629               }
121630             }
121631           }
121632
121633           var _extent = utilTotalExtent(_disconnectingVertexIds, context.graph());
121634
121635           var operation = function operation() {
121636             context.perform(function (graph) {
121637               return _actions.reduce(function (graph, action) {
121638                 return action(graph);
121639               }, graph);
121640             }, operation.annotation());
121641             context.validator().validate();
121642           };
121643
121644           operation.relatedEntityIds = function () {
121645             if (_vertexIDs.length) {
121646               return _disconnectingWayIds;
121647             }
121648
121649             return _disconnectingVertexIds;
121650           };
121651
121652           operation.available = function () {
121653             if (_actions.length === 0) return false;
121654             if (_otherIDs.length !== 0) return false;
121655             if (_vertexIDs.length !== 0 && _wayIDs.length !== 0 && !_wayIDs.every(function (wayID) {
121656               return _vertexIDs.some(function (vertexID) {
121657                 var way = context.entity(wayID);
121658                 return way.nodes.indexOf(vertexID) !== -1;
121659               });
121660             })) return false;
121661             return true;
121662           };
121663
121664           operation.disabled = function () {
121665             var reason;
121666
121667             for (var actionIndex in _actions) {
121668               reason = _actions[actionIndex].disabled(context.graph());
121669               if (reason) return reason;
121670             }
121671
121672             if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
121673               return 'too_large.' + ((_vertexIDs.length ? _vertexIDs : _wayIDs).length === 1 ? 'single' : 'multiple');
121674             } else if (_coords && someMissing()) {
121675               return 'not_downloaded';
121676             } else if (selectedIDs.some(context.hasHiddenConnections)) {
121677               return 'connected_to_hidden';
121678             }
121679
121680             return false;
121681
121682             function someMissing() {
121683               if (context.inIntro()) return false;
121684               var osm = context.connection();
121685
121686               if (osm) {
121687                 var missing = _coords.filter(function (loc) {
121688                   return !osm.isDataLoaded(loc);
121689                 });
121690
121691                 if (missing.length) {
121692                   missing.forEach(function (loc) {
121693                     context.loadTileAtLoc(loc);
121694                   });
121695                   return true;
121696                 }
121697               }
121698
121699               return false;
121700             }
121701           };
121702
121703           operation.tooltip = function () {
121704             var disable = operation.disabled();
121705
121706             if (disable) {
121707               return _t('operations.disconnect.' + disable);
121708             }
121709
121710             return _t('operations.disconnect.description.' + _descriptionID);
121711           };
121712
121713           operation.annotation = function () {
121714             return _t('operations.disconnect.annotation.' + _annotationID);
121715           };
121716
121717           operation.id = 'disconnect';
121718           operation.keys = [_t('operations.disconnect.key')];
121719           operation.title = _t('operations.disconnect.title');
121720           operation.behavior = behaviorOperation(context).which(operation);
121721           return operation;
121722         }
121723
121724         function operationDowngrade(context, selectedIDs) {
121725           var _affectedFeatureCount = 0;
121726
121727           var _downgradeType = downgradeTypeForEntityIDs(selectedIDs);
121728
121729           var _multi = _affectedFeatureCount === 1 ? 'single' : 'multiple';
121730
121731           function downgradeTypeForEntityIDs(entityIds) {
121732             var downgradeType;
121733             _affectedFeatureCount = 0;
121734
121735             for (var i in entityIds) {
121736               var entityID = entityIds[i];
121737               var type = downgradeTypeForEntityID(entityID);
121738
121739               if (type) {
121740                 _affectedFeatureCount += 1;
121741
121742                 if (downgradeType && type !== downgradeType) {
121743                   if (downgradeType !== 'generic' && type !== 'generic') {
121744                     downgradeType = 'building_address';
121745                   } else {
121746                     downgradeType = 'generic';
121747                   }
121748                 } else {
121749                   downgradeType = type;
121750                 }
121751               }
121752             }
121753
121754             return downgradeType;
121755           }
121756
121757           function downgradeTypeForEntityID(entityID) {
121758             var graph = context.graph();
121759             var entity = graph.entity(entityID);
121760             var preset = _mainPresetIndex.match(entity, graph);
121761             if (!preset || preset.isFallback()) return null;
121762
121763             if (entity.type === 'node' && preset.id !== 'address' && Object.keys(entity.tags).some(function (key) {
121764               return key.match(/^addr:.{1,}/);
121765             })) {
121766               return 'address';
121767             }
121768
121769             var geometry = entity.geometry(graph);
121770
121771             if (geometry === 'area' && entity.tags.building && !preset.tags.building) {
121772               return 'building';
121773             }
121774
121775             if (geometry === 'vertex' && Object.keys(entity.tags).length) {
121776               return 'generic';
121777             }
121778
121779             return null;
121780           }
121781
121782           var buildingKeysToKeep = ['architect', 'building', 'height', 'layer', 'source', 'type', 'wheelchair'];
121783           var addressKeysToKeep = ['source'];
121784
121785           var operation = function operation() {
121786             context.perform(function (graph) {
121787               for (var i in selectedIDs) {
121788                 var entityID = selectedIDs[i];
121789                 var type = downgradeTypeForEntityID(entityID);
121790                 if (!type) continue;
121791                 var tags = Object.assign({}, graph.entity(entityID).tags); // shallow copy
121792
121793                 for (var key in tags) {
121794                   if (type === 'address' && addressKeysToKeep.indexOf(key) !== -1) continue;
121795
121796                   if (type === 'building') {
121797                     if (buildingKeysToKeep.indexOf(key) !== -1 || key.match(/^building:.{1,}/) || key.match(/^roof:.{1,}/)) continue;
121798                   }
121799
121800                   if (type !== 'generic') {
121801                     if (key.match(/^addr:.{1,}/) || key.match(/^source:.{1,}/)) continue;
121802                   }
121803
121804                   delete tags[key];
121805                 }
121806
121807                 graph = actionChangeTags(entityID, tags)(graph);
121808               }
121809
121810               return graph;
121811             }, operation.annotation());
121812             context.validator().validate(); // refresh the select mode to enable the delete operation
121813
121814             context.enter(modeSelect(context, selectedIDs));
121815           };
121816
121817           operation.available = function () {
121818             return _downgradeType;
121819           };
121820
121821           operation.disabled = function () {
121822             if (selectedIDs.some(hasWikidataTag)) {
121823               return 'has_wikidata_tag';
121824             }
121825
121826             return false;
121827
121828             function hasWikidataTag(id) {
121829               var entity = context.entity(id);
121830               return entity.tags.wikidata && entity.tags.wikidata.trim().length > 0;
121831             }
121832           };
121833
121834           operation.tooltip = function () {
121835             var disable = operation.disabled();
121836             return disable ? _t('operations.downgrade.' + disable + '.' + _multi) : _t('operations.downgrade.description.' + _downgradeType);
121837           };
121838
121839           operation.annotation = function () {
121840             var suffix;
121841
121842             if (_downgradeType === 'building_address') {
121843               suffix = 'generic';
121844             } else {
121845               suffix = _downgradeType;
121846             }
121847
121848             return _t('operations.downgrade.annotation.' + suffix, {
121849               n: _affectedFeatureCount
121850             });
121851           };
121852
121853           operation.id = 'downgrade';
121854           operation.keys = [uiCmd('⌫')];
121855           operation.title = _t('operations.downgrade.title');
121856           operation.behavior = behaviorOperation(context).which(operation);
121857           return operation;
121858         }
121859
121860         function operationExtract(context, selectedIDs) {
121861           var _amount = selectedIDs.length === 1 ? 'single' : 'multiple';
121862
121863           var _geometries = utilArrayUniq(selectedIDs.map(function (entityID) {
121864             return context.graph().hasEntity(entityID) && context.graph().geometry(entityID);
121865           }).filter(Boolean));
121866
121867           var _geometryID = _geometries.length === 1 ? _geometries[0] : 'feature';
121868
121869           var _extent;
121870
121871           var _actions = selectedIDs.map(function (entityID) {
121872             var graph = context.graph();
121873             var entity = graph.hasEntity(entityID);
121874             if (!entity || !entity.hasInterestingTags()) return null;
121875             if (entity.type === 'node' && graph.parentWays(entity).length === 0) return null;
121876
121877             if (entity.type !== 'node') {
121878               var preset = _mainPresetIndex.match(entity, graph); // only allow extraction from ways/relations if the preset supports points
121879
121880               if (preset.geometry.indexOf('point') === -1) return null;
121881             }
121882
121883             _extent = _extent ? _extent.extend(entity.extent(graph)) : entity.extent(graph);
121884             return actionExtract(entityID, context.projection);
121885           }).filter(Boolean);
121886
121887           var operation = function operation() {
121888             var combinedAction = function combinedAction(graph) {
121889               _actions.forEach(function (action) {
121890                 graph = action(graph);
121891               });
121892
121893               return graph;
121894             };
121895
121896             context.perform(combinedAction, operation.annotation()); // do the extract
121897
121898             var extractedNodeIDs = _actions.map(function (action) {
121899               return action.getExtractedNodeID();
121900             });
121901
121902             context.enter(modeSelect(context, extractedNodeIDs));
121903           };
121904
121905           operation.available = function () {
121906             return _actions.length && selectedIDs.length === _actions.length;
121907           };
121908
121909           operation.disabled = function () {
121910             if (_extent && _extent.percentContainedIn(context.map().extent()) < 0.8) {
121911               return 'too_large';
121912             } else if (selectedIDs.some(function (entityID) {
121913               return context.graph().geometry(entityID) === 'vertex' && context.hasHiddenConnections(entityID);
121914             })) {
121915               return 'connected_to_hidden';
121916             }
121917
121918             return false;
121919           };
121920
121921           operation.tooltip = function () {
121922             var disableReason = operation.disabled();
121923
121924             if (disableReason) {
121925               return _t('operations.extract.' + disableReason + '.' + _amount);
121926             } else {
121927               return _t('operations.extract.description.' + _geometryID + '.' + _amount);
121928             }
121929           };
121930
121931           operation.annotation = function () {
121932             return _t('operations.extract.annotation', {
121933               n: selectedIDs.length
121934             });
121935           };
121936
121937           operation.id = 'extract';
121938           operation.keys = [_t('operations.extract.key')];
121939           operation.title = _t('operations.extract.title');
121940           operation.behavior = behaviorOperation(context).which(operation);
121941           return operation;
121942         }
121943
121944         function operationMerge(context, selectedIDs) {
121945           var _action = getAction();
121946
121947           function getAction() {
121948             // prefer a non-disabled action first
121949             var join = actionJoin(selectedIDs);
121950             if (!join.disabled(context.graph())) return join;
121951             var merge = actionMerge(selectedIDs);
121952             if (!merge.disabled(context.graph())) return merge;
121953             var mergePolygon = actionMergePolygon(selectedIDs);
121954             if (!mergePolygon.disabled(context.graph())) return mergePolygon;
121955             var mergeNodes = actionMergeNodes(selectedIDs);
121956             if (!mergeNodes.disabled(context.graph())) return mergeNodes; // otherwise prefer an action with an interesting disabled reason
121957
121958             if (join.disabled(context.graph()) !== 'not_eligible') return join;
121959             if (merge.disabled(context.graph()) !== 'not_eligible') return merge;
121960             if (mergePolygon.disabled(context.graph()) !== 'not_eligible') return mergePolygon;
121961             return mergeNodes;
121962           }
121963
121964           var operation = function operation() {
121965             if (operation.disabled()) return;
121966             context.perform(_action, operation.annotation());
121967             context.validator().validate();
121968             var resultIDs = selectedIDs.filter(context.hasEntity);
121969
121970             if (resultIDs.length > 1) {
121971               var interestingIDs = resultIDs.filter(function (id) {
121972                 return context.entity(id).hasInterestingTags();
121973               });
121974               if (interestingIDs.length) resultIDs = interestingIDs;
121975             }
121976
121977             context.enter(modeSelect(context, resultIDs));
121978           };
121979
121980           operation.available = function () {
121981             return selectedIDs.length >= 2;
121982           };
121983
121984           operation.disabled = function () {
121985             var actionDisabled = _action.disabled(context.graph());
121986
121987             if (actionDisabled) return actionDisabled;
121988             var osm = context.connection();
121989
121990             if (osm && _action.resultingWayNodesLength && _action.resultingWayNodesLength(context.graph()) > osm.maxWayNodes()) {
121991               return 'too_many_vertices';
121992             }
121993
121994             return false;
121995           };
121996
121997           operation.tooltip = function () {
121998             var disabled = operation.disabled();
121999
122000             if (disabled) {
122001               if (disabled === 'conflicting_relations') {
122002                 return _t('operations.merge.conflicting_relations');
122003               }
122004
122005               if (disabled === 'restriction' || disabled === 'connectivity') {
122006                 return _t('operations.merge.damage_relation', {
122007                   relation: _mainPresetIndex.item('type/' + disabled).name()
122008                 });
122009               }
122010
122011               return _t('operations.merge.' + disabled);
122012             }
122013
122014             return _t('operations.merge.description');
122015           };
122016
122017           operation.annotation = function () {
122018             return _t('operations.merge.annotation', {
122019               n: selectedIDs.length
122020             });
122021           };
122022
122023           operation.id = 'merge';
122024           operation.keys = [_t('operations.merge.key')];
122025           operation.title = _t('operations.merge.title');
122026           operation.behavior = behaviorOperation(context).which(operation);
122027           return operation;
122028         }
122029
122030         function operationPaste(context) {
122031           var _pastePoint;
122032
122033           var operation = function operation() {
122034             if (!_pastePoint) return;
122035             var oldIDs = context.copyIDs();
122036             if (!oldIDs.length) return;
122037             var projection = context.projection;
122038             var extent = geoExtent();
122039             var oldGraph = context.copyGraph();
122040             var newIDs = [];
122041             var action = actionCopyEntities(oldIDs, oldGraph);
122042             context.perform(action);
122043             var copies = action.copies();
122044             var originals = new Set();
122045             Object.values(copies).forEach(function (entity) {
122046               originals.add(entity.id);
122047             });
122048
122049             for (var id in copies) {
122050               var oldEntity = oldGraph.entity(id);
122051               var newEntity = copies[id];
122052
122053               extent._extend(oldEntity.extent(oldGraph)); // Exclude child nodes from newIDs if their parent way was also copied.
122054
122055
122056               var parents = context.graph().parentWays(newEntity);
122057               var parentCopied = parents.some(function (parent) {
122058                 return originals.has(parent.id);
122059               });
122060
122061               if (!parentCopied) {
122062                 newIDs.push(newEntity.id);
122063               }
122064             } // Use the location of the copy operation to offset the paste location,
122065             // or else use the center of the pasted extent
122066
122067
122068             var copyPoint = context.copyLonLat() && projection(context.copyLonLat()) || projection(extent.center());
122069             var delta = geoVecSubtract(_pastePoint, copyPoint); // Move the pasted objects to be anchored at the paste location
122070
122071             context.replace(actionMove(newIDs, delta, projection), operation.annotation());
122072             context.enter(modeSelect(context, newIDs));
122073           };
122074
122075           operation.point = function (val) {
122076             _pastePoint = val;
122077             return operation;
122078           };
122079
122080           operation.available = function () {
122081             return context.mode().id === 'browse';
122082           };
122083
122084           operation.disabled = function () {
122085             return !context.copyIDs().length;
122086           };
122087
122088           operation.tooltip = function () {
122089             var oldGraph = context.copyGraph();
122090             var ids = context.copyIDs();
122091
122092             if (!ids.length) {
122093               return _t('operations.paste.nothing_copied');
122094             }
122095
122096             return _t('operations.paste.description', {
122097               feature: utilDisplayLabel(oldGraph.entity(ids[0]), oldGraph),
122098               n: ids.length
122099             });
122100           };
122101
122102           operation.annotation = function () {
122103             var ids = context.copyIDs();
122104             return _t('operations.paste.annotation', {
122105               n: ids.length
122106             });
122107           };
122108
122109           operation.id = 'paste';
122110           operation.keys = [uiCmd('⌘V')];
122111           operation.title = _t('operations.paste.title');
122112           return operation;
122113         }
122114
122115         function operationReverse(context, selectedIDs) {
122116           var operation = function operation() {
122117             context.perform(function combinedReverseAction(graph) {
122118               actions().forEach(function (action) {
122119                 graph = action(graph);
122120               });
122121               return graph;
122122             }, operation.annotation());
122123             context.validator().validate();
122124           };
122125
122126           function actions(situation) {
122127             return selectedIDs.map(function (entityID) {
122128               var entity = context.hasEntity(entityID);
122129               if (!entity) return null;
122130
122131               if (situation === 'toolbar') {
122132                 if (entity.type === 'way' && !entity.isOneWay() && !entity.isSided()) return null;
122133               }
122134
122135               var geometry = entity.geometry(context.graph());
122136               if (entity.type !== 'node' && geometry !== 'line') return null;
122137               var action = actionReverse(entityID);
122138               if (action.disabled(context.graph())) return null;
122139               return action;
122140             }).filter(Boolean);
122141           }
122142
122143           function reverseTypeID() {
122144             var acts = actions();
122145             var nodeActionCount = acts.filter(function (act) {
122146               var entity = context.hasEntity(act.entityID());
122147               return entity && entity.type === 'node';
122148             }).length;
122149             if (nodeActionCount === 0) return 'line';
122150             if (nodeActionCount === acts.length) return 'point';
122151             return 'feature';
122152           }
122153
122154           operation.available = function (situation) {
122155             return actions(situation).length > 0;
122156           };
122157
122158           operation.disabled = function () {
122159             return false;
122160           };
122161
122162           operation.tooltip = function () {
122163             return _t('operations.reverse.description.' + reverseTypeID());
122164           };
122165
122166           operation.annotation = function () {
122167             var acts = actions();
122168             return _t('operations.reverse.annotation.' + reverseTypeID(), {
122169               n: acts.length
122170             });
122171           };
122172
122173           operation.id = 'reverse';
122174           operation.keys = [_t('operations.reverse.key')];
122175           operation.title = _t('operations.reverse.title');
122176           operation.behavior = behaviorOperation(context).which(operation);
122177           return operation;
122178         }
122179
122180         function operationSplit(context, selectedIDs) {
122181           var _vertexIds = selectedIDs.filter(function (id) {
122182             return context.graph().geometry(id) === 'vertex';
122183           });
122184
122185           var _selectedWayIds = selectedIDs.filter(function (id) {
122186             var entity = context.graph().hasEntity(id);
122187             return entity && entity.type === 'way';
122188           });
122189
122190           var _isAvailable = _vertexIds.length > 0 && _vertexIds.length + _selectedWayIds.length === selectedIDs.length;
122191
122192           var _action = actionSplit(_vertexIds);
122193
122194           var _ways = [];
122195           var _geometry = 'feature';
122196           var _waysAmount = 'single';
122197
122198           var _nodesAmount = _vertexIds.length === 1 ? 'single' : 'multiple';
122199
122200           if (_isAvailable) {
122201             if (_selectedWayIds.length) _action.limitWays(_selectedWayIds);
122202             _ways = _action.ways(context.graph());
122203             var geometries = {};
122204
122205             _ways.forEach(function (way) {
122206               geometries[way.geometry(context.graph())] = true;
122207             });
122208
122209             if (Object.keys(geometries).length === 1) {
122210               _geometry = Object.keys(geometries)[0];
122211             }
122212
122213             _waysAmount = _ways.length === 1 ? 'single' : 'multiple';
122214           }
122215
122216           var operation = function operation() {
122217             var difference = context.perform(_action, operation.annotation()); // select both the nodes and the ways so the mapper can immediately disconnect them if desired
122218
122219             var idsToSelect = _vertexIds.concat(difference.extantIDs().filter(function (id) {
122220               // filter out relations that may have had member additions
122221               return context.entity(id).type === 'way';
122222             }));
122223
122224             context.enter(modeSelect(context, idsToSelect));
122225           };
122226
122227           operation.relatedEntityIds = function () {
122228             return _selectedWayIds.length ? [] : _ways.map(function (way) {
122229               return way.id;
122230             });
122231           };
122232
122233           operation.available = function () {
122234             return _isAvailable;
122235           };
122236
122237           operation.disabled = function () {
122238             var reason = _action.disabled(context.graph());
122239
122240             if (reason) {
122241               return reason;
122242             } else if (selectedIDs.some(context.hasHiddenConnections)) {
122243               return 'connected_to_hidden';
122244             }
122245
122246             return false;
122247           };
122248
122249           operation.tooltip = function () {
122250             var disable = operation.disabled();
122251             if (disable) return _t('operations.split.' + disable);
122252             return _t('operations.split.description.' + _geometry + '.' + _waysAmount + '.' + _nodesAmount + '_node');
122253           };
122254
122255           operation.annotation = function () {
122256             return _t('operations.split.annotation.' + _geometry, {
122257               n: _ways.length
122258             });
122259           };
122260
122261           operation.icon = function () {
122262             if (_waysAmount === 'multiple') {
122263               return '#iD-operation-split-multiple';
122264             } else {
122265               return '#iD-operation-split';
122266             }
122267           };
122268
122269           operation.id = 'split';
122270           operation.keys = [_t('operations.split.key')];
122271           operation.title = _t('operations.split.title');
122272           operation.behavior = behaviorOperation(context).which(operation);
122273           return operation;
122274         }
122275
122276         function operationStraighten(context, selectedIDs) {
122277           var _wayIDs = selectedIDs.filter(function (id) {
122278             return id.charAt(0) === 'w';
122279           });
122280
122281           var _nodeIDs = selectedIDs.filter(function (id) {
122282             return id.charAt(0) === 'n';
122283           });
122284
122285           var _amount = (_wayIDs.length ? _wayIDs : _nodeIDs).length === 1 ? 'single' : 'multiple';
122286
122287           var _nodes = utilGetAllNodes(selectedIDs, context.graph());
122288
122289           var _coords = _nodes.map(function (n) {
122290             return n.loc;
122291           });
122292
122293           var _extent = utilTotalExtent(selectedIDs, context.graph());
122294
122295           var _action = chooseAction();
122296
122297           var _geometry;
122298
122299           function chooseAction() {
122300             // straighten selected nodes
122301             if (_wayIDs.length === 0 && _nodeIDs.length > 2) {
122302               _geometry = 'point';
122303               return actionStraightenNodes(_nodeIDs, context.projection); // straighten selected ways (possibly between range of 2 selected nodes)
122304             } else if (_wayIDs.length > 0 && (_nodeIDs.length === 0 || _nodeIDs.length === 2)) {
122305               var startNodeIDs = [];
122306               var endNodeIDs = [];
122307
122308               for (var i = 0; i < selectedIDs.length; i++) {
122309                 var entity = context.entity(selectedIDs[i]);
122310
122311                 if (entity.type === 'node') {
122312                   continue;
122313                 } else if (entity.type !== 'way' || entity.isClosed()) {
122314                   return null; // exit early, can't straighten these
122315                 }
122316
122317                 startNodeIDs.push(entity.first());
122318                 endNodeIDs.push(entity.last());
122319               } // Remove duplicate end/startNodeIDs (duplicate nodes cannot be at the line end)
122320
122321
122322               startNodeIDs = startNodeIDs.filter(function (n) {
122323                 return startNodeIDs.indexOf(n) === startNodeIDs.lastIndexOf(n);
122324               });
122325               endNodeIDs = endNodeIDs.filter(function (n) {
122326                 return endNodeIDs.indexOf(n) === endNodeIDs.lastIndexOf(n);
122327               }); // Ensure all ways are connected (i.e. only 2 unique endpoints/startpoints)
122328
122329               if (utilArrayDifference(startNodeIDs, endNodeIDs).length + utilArrayDifference(endNodeIDs, startNodeIDs).length !== 2) return null; // Ensure path contains at least 3 unique nodes
122330
122331               var wayNodeIDs = utilGetAllNodes(_wayIDs, context.graph()).map(function (node) {
122332                 return node.id;
122333               });
122334               if (wayNodeIDs.length <= 2) return null; // If range of 2 selected nodes is supplied, ensure nodes lie on the selected path
122335
122336               if (_nodeIDs.length === 2 && (wayNodeIDs.indexOf(_nodeIDs[0]) === -1 || wayNodeIDs.indexOf(_nodeIDs[1]) === -1)) return null;
122337
122338               if (_nodeIDs.length) {
122339                 // If we're only straightenting between two points, we only need that extent visible
122340                 _extent = utilTotalExtent(_nodeIDs, context.graph());
122341               }
122342
122343               _geometry = 'line';
122344               return actionStraightenWay(selectedIDs, context.projection);
122345             }
122346
122347             return null;
122348           }
122349
122350           function operation() {
122351             if (!_action) return;
122352             context.perform(_action, operation.annotation());
122353             window.setTimeout(function () {
122354               context.validator().validate();
122355             }, 300); // after any transition
122356           }
122357
122358           operation.available = function () {
122359             return Boolean(_action);
122360           };
122361
122362           operation.disabled = function () {
122363             var reason = _action.disabled(context.graph());
122364
122365             if (reason) {
122366               return reason;
122367             } else if (_extent.percentContainedIn(context.map().extent()) < 0.8) {
122368               return 'too_large';
122369             } else if (someMissing()) {
122370               return 'not_downloaded';
122371             } else if (selectedIDs.some(context.hasHiddenConnections)) {
122372               return 'connected_to_hidden';
122373             }
122374
122375             return false;
122376
122377             function someMissing() {
122378               if (context.inIntro()) return false;
122379               var osm = context.connection();
122380
122381               if (osm) {
122382                 var missing = _coords.filter(function (loc) {
122383                   return !osm.isDataLoaded(loc);
122384                 });
122385
122386                 if (missing.length) {
122387                   missing.forEach(function (loc) {
122388                     context.loadTileAtLoc(loc);
122389                   });
122390                   return true;
122391                 }
122392               }
122393
122394               return false;
122395             }
122396           };
122397
122398           operation.tooltip = function () {
122399             var disable = operation.disabled();
122400             return disable ? _t('operations.straighten.' + disable + '.' + _amount) : _t('operations.straighten.description.' + _geometry + (_wayIDs.length === 1 ? '' : 's'));
122401           };
122402
122403           operation.annotation = function () {
122404             return _t('operations.straighten.annotation.' + _geometry, {
122405               n: _wayIDs.length ? _wayIDs.length : _nodeIDs.length
122406             });
122407           };
122408
122409           operation.id = 'straighten';
122410           operation.keys = [_t('operations.straighten.key')];
122411           operation.title = _t('operations.straighten.title');
122412           operation.behavior = behaviorOperation(context).which(operation);
122413           return operation;
122414         }
122415
122416         var Operations = /*#__PURE__*/Object.freeze({
122417                 __proto__: null,
122418                 operationCircularize: operationCircularize,
122419                 operationContinue: operationContinue,
122420                 operationCopy: operationCopy,
122421                 operationDelete: operationDelete,
122422                 operationDisconnect: operationDisconnect,
122423                 operationDowngrade: operationDowngrade,
122424                 operationExtract: operationExtract,
122425                 operationMerge: operationMerge,
122426                 operationMove: operationMove,
122427                 operationOrthogonalize: operationOrthogonalize,
122428                 operationPaste: operationPaste,
122429                 operationReflectShort: operationReflectShort,
122430                 operationReflectLong: operationReflectLong,
122431                 operationReverse: operationReverse,
122432                 operationRotate: operationRotate,
122433                 operationSplit: operationSplit,
122434                 operationStraighten: operationStraighten
122435         });
122436
122437         function modeSelect(context, selectedIDs) {
122438           var mode = {
122439             id: 'select',
122440             button: 'browse'
122441           };
122442           var keybinding = utilKeybinding('select');
122443
122444           var _breatheBehavior = behaviorBreathe();
122445
122446           var _modeDragNode = modeDragNode(context);
122447
122448           var _selectBehavior;
122449
122450           var _behaviors = [];
122451           var _operations = [];
122452           var _newFeature = false;
122453           var _follow = false; // `_focusedParentWayId` is used when we visit a vertex with multiple
122454           // parents, and we want to remember which parent line we started on.
122455
122456           var _focusedParentWayId;
122457
122458           var _focusedVertexIds;
122459
122460           function singular() {
122461             if (selectedIDs && selectedIDs.length === 1) {
122462               return context.hasEntity(selectedIDs[0]);
122463             }
122464           }
122465
122466           function selectedEntities() {
122467             return selectedIDs.map(function (id) {
122468               return context.hasEntity(id);
122469             }).filter(Boolean);
122470           }
122471
122472           function checkSelectedIDs() {
122473             var ids = [];
122474
122475             if (Array.isArray(selectedIDs)) {
122476               ids = selectedIDs.filter(function (id) {
122477                 return context.hasEntity(id);
122478               });
122479             }
122480
122481             if (!ids.length) {
122482               context.enter(modeBrowse(context));
122483               return false;
122484             } else if (selectedIDs.length > 1 && ids.length === 1 || selectedIDs.length === 1 && ids.length > 1) {
122485               // switch between single- and multi-select UI
122486               context.enter(modeSelect(context, ids));
122487               return false;
122488             }
122489
122490             selectedIDs = ids;
122491             return true;
122492           } // find the parent ways for nextVertex, previousVertex, and selectParent
122493
122494
122495           function parentWaysIdsOfSelection(onlyCommonParents) {
122496             var graph = context.graph();
122497             var parents = [];
122498
122499             for (var i = 0; i < selectedIDs.length; i++) {
122500               var entity = context.hasEntity(selectedIDs[i]);
122501
122502               if (!entity || entity.geometry(graph) !== 'vertex') {
122503                 return []; // selection includes some non-vertices
122504               }
122505
122506               var currParents = graph.parentWays(entity).map(function (w) {
122507                 return w.id;
122508               });
122509
122510               if (!parents.length) {
122511                 parents = currParents;
122512                 continue;
122513               }
122514
122515               parents = (onlyCommonParents ? utilArrayIntersection : utilArrayUnion)(parents, currParents);
122516
122517               if (!parents.length) {
122518                 return [];
122519               }
122520             }
122521
122522             return parents;
122523           } // find the child nodes for selected ways
122524
122525
122526           function childNodeIdsOfSelection(onlyCommon) {
122527             var graph = context.graph();
122528             var childs = [];
122529
122530             for (var i = 0; i < selectedIDs.length; i++) {
122531               var entity = context.hasEntity(selectedIDs[i]);
122532
122533               if (!entity || !['area', 'line'].includes(entity.geometry(graph))) {
122534                 return []; // selection includes non-area/non-line
122535               }
122536
122537               var currChilds = graph.childNodes(entity).map(function (node) {
122538                 return node.id;
122539               });
122540
122541               if (!childs.length) {
122542                 childs = currChilds;
122543                 continue;
122544               }
122545
122546               childs = (onlyCommon ? utilArrayIntersection : utilArrayUnion)(childs, currChilds);
122547
122548               if (!childs.length) {
122549                 return [];
122550               }
122551             }
122552
122553             return childs;
122554           }
122555
122556           function checkFocusedParent() {
122557             if (_focusedParentWayId) {
122558               var parents = parentWaysIdsOfSelection(true);
122559               if (parents.indexOf(_focusedParentWayId) === -1) _focusedParentWayId = null;
122560             }
122561           }
122562
122563           function parentWayIdForVertexNavigation() {
122564             var parentIds = parentWaysIdsOfSelection(true);
122565
122566             if (_focusedParentWayId && parentIds.indexOf(_focusedParentWayId) !== -1) {
122567               // prefer the previously seen parent
122568               return _focusedParentWayId;
122569             }
122570
122571             return parentIds.length ? parentIds[0] : null;
122572           }
122573
122574           mode.selectedIDs = function (val) {
122575             if (!arguments.length) return selectedIDs;
122576             selectedIDs = val;
122577             return mode;
122578           };
122579
122580           mode.zoomToSelected = function () {
122581             context.map().zoomToEase(selectedEntities());
122582           };
122583
122584           mode.newFeature = function (val) {
122585             if (!arguments.length) return _newFeature;
122586             _newFeature = val;
122587             return mode;
122588           };
122589
122590           mode.selectBehavior = function (val) {
122591             if (!arguments.length) return _selectBehavior;
122592             _selectBehavior = val;
122593             return mode;
122594           };
122595
122596           mode.follow = function (val) {
122597             if (!arguments.length) return _follow;
122598             _follow = val;
122599             return mode;
122600           };
122601
122602           function loadOperations() {
122603             _operations.forEach(function (operation) {
122604               if (operation.behavior) {
122605                 context.uninstall(operation.behavior);
122606               }
122607             });
122608
122609             _operations = Object.values(Operations).map(function (o) {
122610               return o(context, selectedIDs);
122611             }).filter(function (o) {
122612               return o.id !== 'delete' && o.id !== 'downgrade' && o.id !== 'copy';
122613             }).concat([// group copy/downgrade/delete operation together at the end of the list
122614             operationCopy(context, selectedIDs), operationDowngrade(context, selectedIDs), operationDelete(context, selectedIDs)]).filter(function (operation) {
122615               return operation.available();
122616             });
122617
122618             _operations.forEach(function (operation) {
122619               if (operation.behavior) {
122620                 context.install(operation.behavior);
122621               }
122622             }); // remove any displayed menu
122623
122624
122625             context.ui().closeEditMenu();
122626           }
122627
122628           mode.operations = function () {
122629             return _operations;
122630           };
122631
122632           mode.enter = function () {
122633             if (!checkSelectedIDs()) return;
122634             context.features().forceVisible(selectedIDs);
122635
122636             _modeDragNode.restoreSelectedIDs(selectedIDs);
122637
122638             loadOperations();
122639
122640             if (!_behaviors.length) {
122641               if (!_selectBehavior) _selectBehavior = behaviorSelect(context);
122642               _behaviors = [behaviorPaste(context), _breatheBehavior, behaviorHover(context).on('hover', context.ui().sidebar.hoverModeSelect), _selectBehavior, behaviorLasso(context), _modeDragNode.behavior, modeDragNote(context).behavior];
122643             }
122644
122645             _behaviors.forEach(context.install);
122646
122647             keybinding.on(_t('inspector.zoom_to.key'), mode.zoomToSelected).on(['[', 'pgup'], previousVertex).on([']', 'pgdown'], nextVertex).on(['{', uiCmd('⌘['), 'home'], firstVertex).on(['}', uiCmd('⌘]'), 'end'], lastVertex).on(uiCmd('⇧←'), nudgeSelection([-10, 0])).on(uiCmd('⇧↑'), nudgeSelection([0, -10])).on(uiCmd('⇧→'), nudgeSelection([10, 0])).on(uiCmd('⇧↓'), nudgeSelection([0, 10])).on(uiCmd('⇧⌥←'), nudgeSelection([-100, 0])).on(uiCmd('⇧⌥↑'), nudgeSelection([0, -100])).on(uiCmd('⇧⌥→'), nudgeSelection([100, 0])).on(uiCmd('⇧⌥↓'), nudgeSelection([0, 100])).on(utilKeybinding.plusKeys.map(function (key) {
122648               return uiCmd('⇧' + key);
122649             }), scaleSelection(1.05)).on(utilKeybinding.plusKeys.map(function (key) {
122650               return uiCmd('⇧⌥' + key);
122651             }), scaleSelection(Math.pow(1.05, 5))).on(utilKeybinding.minusKeys.map(function (key) {
122652               return uiCmd('⇧' + key);
122653             }), scaleSelection(1 / 1.05)).on(utilKeybinding.minusKeys.map(function (key) {
122654               return uiCmd('⇧⌥' + key);
122655             }), scaleSelection(1 / Math.pow(1.05, 5))).on(['\\', 'pause'], focusNextParent).on(uiCmd('⌘↑'), selectParent).on(uiCmd('⌘↓'), selectChild).on('⎋', esc, true);
122656             select(document).call(keybinding);
122657             context.ui().sidebar.select(selectedIDs, _newFeature);
122658             context.history().on('change.select', function () {
122659               loadOperations(); // reselect after change in case relation members were removed or added
122660
122661               selectElements();
122662             }).on('undone.select', checkSelectedIDs).on('redone.select', checkSelectedIDs);
122663             context.map().on('drawn.select', selectElements).on('crossEditableZoom.select', function () {
122664               selectElements();
122665
122666               _breatheBehavior.restartIfNeeded(context.surface());
122667             });
122668             context.map().doubleUpHandler().on('doubleUp.modeSelect', didDoubleUp);
122669             selectElements();
122670
122671             if (_follow) {
122672               var extent = geoExtent();
122673               var graph = context.graph();
122674               selectedIDs.forEach(function (id) {
122675                 var entity = context.entity(id);
122676
122677                 extent._extend(entity.extent(graph));
122678               });
122679               var loc = extent.center();
122680               context.map().centerEase(loc); // we could enter the mode multiple times, so reset follow for next time
122681
122682               _follow = false;
122683             }
122684
122685             function nudgeSelection(delta) {
122686               return function () {
122687                 // prevent nudging during low zoom selection
122688                 if (!context.map().withinEditableZoom()) return;
122689                 var moveOp = operationMove(context, selectedIDs);
122690
122691                 if (moveOp.disabled()) {
122692                   context.ui().flash.duration(4000).iconName('#iD-operation-' + moveOp.id).iconClass('operation disabled').label(moveOp.tooltip)();
122693                 } else {
122694                   context.perform(actionMove(selectedIDs, delta, context.projection), moveOp.annotation());
122695                   context.validator().validate();
122696                 }
122697               };
122698             }
122699
122700             function scaleSelection(factor) {
122701               return function () {
122702                 // prevent scaling during low zoom selection
122703                 if (!context.map().withinEditableZoom()) return;
122704                 var nodes = utilGetAllNodes(selectedIDs, context.graph());
122705                 var isUp = factor > 1; // can only scale if multiple nodes are selected
122706
122707                 if (nodes.length <= 1) return;
122708                 var extent = utilTotalExtent(selectedIDs, context.graph()); // These disabled checks would normally be handled by an operation
122709                 // object, but we don't want an actual scale operation at this point.
122710
122711                 function scalingDisabled() {
122712                   if (tooSmall()) {
122713                     return 'too_small';
122714                   } else if (extent.percentContainedIn(context.map().extent()) < 0.8) {
122715                     return 'too_large';
122716                   } else if (someMissing() || selectedIDs.some(incompleteRelation)) {
122717                     return 'not_downloaded';
122718                   } else if (selectedIDs.some(context.hasHiddenConnections)) {
122719                     return 'connected_to_hidden';
122720                   }
122721
122722                   return false;
122723
122724                   function tooSmall() {
122725                     if (isUp) return false;
122726                     var dLon = Math.abs(extent[1][0] - extent[0][0]);
122727                     var dLat = Math.abs(extent[1][1] - extent[0][1]);
122728                     return dLon < geoMetersToLon(1, extent[1][1]) && dLat < geoMetersToLat(1);
122729                   }
122730
122731                   function someMissing() {
122732                     if (context.inIntro()) return false;
122733                     var osm = context.connection();
122734
122735                     if (osm) {
122736                       var missing = nodes.filter(function (n) {
122737                         return !osm.isDataLoaded(n.loc);
122738                       });
122739
122740                       if (missing.length) {
122741                         missing.forEach(function (loc) {
122742                           context.loadTileAtLoc(loc);
122743                         });
122744                         return true;
122745                       }
122746                     }
122747
122748                     return false;
122749                   }
122750
122751                   function incompleteRelation(id) {
122752                     var entity = context.entity(id);
122753                     return entity.type === 'relation' && !entity.isComplete(context.graph());
122754                   }
122755                 }
122756
122757                 var disabled = scalingDisabled();
122758
122759                 if (disabled) {
122760                   var multi = selectedIDs.length === 1 ? 'single' : 'multiple';
122761                   context.ui().flash.duration(4000).iconName('#iD-icon-no').iconClass('operation disabled').label(_t.html('operations.scale.' + disabled + '.' + multi))();
122762                 } else {
122763                   var pivot = context.projection(extent.center());
122764                   var annotation = _t('operations.scale.annotation.' + (isUp ? 'up' : 'down') + '.feature', {
122765                     n: selectedIDs.length
122766                   });
122767                   context.perform(actionScale(selectedIDs, pivot, factor, context.projection), annotation);
122768                   context.validator().validate();
122769                 }
122770               };
122771             }
122772
122773             function didDoubleUp(d3_event, loc) {
122774               if (!context.map().withinEditableZoom()) return;
122775               var target = select(d3_event.target);
122776               var datum = target.datum();
122777               var entity = datum && datum.properties && datum.properties.entity;
122778               if (!entity) return;
122779
122780               if (entity instanceof osmWay && target.classed('target')) {
122781                 var choice = geoChooseEdge(context.graph().childNodes(entity), loc, context.projection);
122782                 var prev = entity.nodes[choice.index - 1];
122783                 var next = entity.nodes[choice.index];
122784                 context.perform(actionAddMidpoint({
122785                   loc: choice.loc,
122786                   edge: [prev, next]
122787                 }, osmNode()), _t('operations.add.annotation.vertex'));
122788                 context.validator().validate();
122789               } else if (entity.type === 'midpoint') {
122790                 context.perform(actionAddMidpoint({
122791                   loc: entity.loc,
122792                   edge: entity.edge
122793                 }, osmNode()), _t('operations.add.annotation.vertex'));
122794                 context.validator().validate();
122795               }
122796             }
122797
122798             function selectElements() {
122799               if (!checkSelectedIDs()) return;
122800               var surface = context.surface();
122801               surface.selectAll('.selected-member').classed('selected-member', false);
122802               surface.selectAll('.selected').classed('selected', false);
122803               surface.selectAll('.related').classed('related', false); // reload `_focusedParentWayId` based on the current selection
122804
122805               checkFocusedParent();
122806
122807               if (_focusedParentWayId) {
122808                 surface.selectAll(utilEntitySelector([_focusedParentWayId])).classed('related', true);
122809               }
122810
122811               if (context.map().withinEditableZoom()) {
122812                 // Apply selection styling if not in wide selection
122813                 surface.selectAll(utilDeepMemberSelector(selectedIDs, context.graph(), true
122814                 /* skipMultipolgonMembers */
122815                 )).classed('selected-member', true);
122816                 surface.selectAll(utilEntityOrDeepMemberSelector(selectedIDs, context.graph())).classed('selected', true);
122817               }
122818             }
122819
122820             function esc() {
122821               if (context.container().select('.combobox').size()) return;
122822               context.enter(modeBrowse(context));
122823             }
122824
122825             function firstVertex(d3_event) {
122826               d3_event.preventDefault();
122827               var entity = singular();
122828               var parentId = parentWayIdForVertexNavigation();
122829               var way;
122830
122831               if (entity && entity.type === 'way') {
122832                 way = entity;
122833               } else if (parentId) {
122834                 way = context.entity(parentId);
122835               }
122836
122837               _focusedParentWayId = way && way.id;
122838
122839               if (way) {
122840                 context.enter(mode.selectedIDs([way.first()]).follow(true));
122841               }
122842             }
122843
122844             function lastVertex(d3_event) {
122845               d3_event.preventDefault();
122846               var entity = singular();
122847               var parentId = parentWayIdForVertexNavigation();
122848               var way;
122849
122850               if (entity && entity.type === 'way') {
122851                 way = entity;
122852               } else if (parentId) {
122853                 way = context.entity(parentId);
122854               }
122855
122856               _focusedParentWayId = way && way.id;
122857
122858               if (way) {
122859                 context.enter(mode.selectedIDs([way.last()]).follow(true));
122860               }
122861             }
122862
122863             function previousVertex(d3_event) {
122864               d3_event.preventDefault();
122865               var parentId = parentWayIdForVertexNavigation();
122866               _focusedParentWayId = parentId;
122867               if (!parentId) return;
122868               var way = context.entity(parentId);
122869               var length = way.nodes.length;
122870               var curr = way.nodes.indexOf(selectedIDs[0]);
122871               var index = -1;
122872
122873               if (curr > 0) {
122874                 index = curr - 1;
122875               } else if (way.isClosed()) {
122876                 index = length - 2;
122877               }
122878
122879               if (index !== -1) {
122880                 context.enter(mode.selectedIDs([way.nodes[index]]).follow(true));
122881               }
122882             }
122883
122884             function nextVertex(d3_event) {
122885               d3_event.preventDefault();
122886               var parentId = parentWayIdForVertexNavigation();
122887               _focusedParentWayId = parentId;
122888               if (!parentId) return;
122889               var way = context.entity(parentId);
122890               var length = way.nodes.length;
122891               var curr = way.nodes.indexOf(selectedIDs[0]);
122892               var index = -1;
122893
122894               if (curr < length - 1) {
122895                 index = curr + 1;
122896               } else if (way.isClosed()) {
122897                 index = 0;
122898               }
122899
122900               if (index !== -1) {
122901                 context.enter(mode.selectedIDs([way.nodes[index]]).follow(true));
122902               }
122903             }
122904
122905             function focusNextParent(d3_event) {
122906               d3_event.preventDefault();
122907               var parents = parentWaysIdsOfSelection(true);
122908               if (!parents || parents.length < 2) return;
122909               var index = parents.indexOf(_focusedParentWayId);
122910
122911               if (index < 0 || index > parents.length - 2) {
122912                 _focusedParentWayId = parents[0];
122913               } else {
122914                 _focusedParentWayId = parents[index + 1];
122915               }
122916
122917               var surface = context.surface();
122918               surface.selectAll('.related').classed('related', false);
122919
122920               if (_focusedParentWayId) {
122921                 surface.selectAll(utilEntitySelector([_focusedParentWayId])).classed('related', true);
122922               }
122923             }
122924
122925             function selectParent(d3_event) {
122926               d3_event.preventDefault();
122927               var currentSelectedIds = mode.selectedIDs();
122928               var parentIds = _focusedParentWayId ? [_focusedParentWayId] : parentWaysIdsOfSelection(false);
122929               if (!parentIds.length) return;
122930               context.enter(mode.selectedIDs(parentIds)); // set this after re-entering the selection since we normally want it cleared on exit
122931
122932               _focusedVertexIds = currentSelectedIds;
122933             }
122934
122935             function selectChild(d3_event) {
122936               d3_event.preventDefault();
122937               var currentSelectedIds = mode.selectedIDs();
122938               var childIds = _focusedVertexIds ? _focusedVertexIds.filter(function (id) {
122939                 return context.hasEntity(id);
122940               }) : childNodeIdsOfSelection(true);
122941               if (!childIds || !childIds.length) return;
122942               if (currentSelectedIds.length === 1) _focusedParentWayId = currentSelectedIds[0];
122943               context.enter(mode.selectedIDs(childIds));
122944             }
122945           };
122946
122947           mode.exit = function () {
122948             // we could enter the mode multiple times but it's only new the first time
122949             _newFeature = false;
122950             _focusedVertexIds = null;
122951
122952             _operations.forEach(function (operation) {
122953               if (operation.behavior) {
122954                 context.uninstall(operation.behavior);
122955               }
122956             });
122957
122958             _operations = [];
122959
122960             _behaviors.forEach(context.uninstall);
122961
122962             select(document).call(keybinding.unbind);
122963             context.ui().closeEditMenu();
122964             context.history().on('change.select', null).on('undone.select', null).on('redone.select', null);
122965             var surface = context.surface();
122966             surface.selectAll('.selected-member').classed('selected-member', false);
122967             surface.selectAll('.selected').classed('selected', false);
122968             surface.selectAll('.highlighted').classed('highlighted', false);
122969             surface.selectAll('.related').classed('related', false);
122970             context.map().on('drawn.select', null);
122971             context.ui().sidebar.hide();
122972             context.features().forceVisible([]);
122973             var entity = singular();
122974
122975             if (_newFeature && entity && entity.type === 'relation' && // no tags
122976             Object.keys(entity.tags).length === 0 && // no parent relations
122977             context.graph().parentRelations(entity).length === 0 && ( // no members or one member with no role
122978             entity.members.length === 0 || entity.members.length === 1 && !entity.members[0].role)) {
122979               // the user added this relation but didn't edit it at all, so just delete it
122980               var deleteAction = actionDeleteRelation(entity.id, true
122981               /* don't delete untagged members */
122982               );
122983               context.perform(deleteAction, _t('operations.delete.annotation.relation'));
122984               context.validator().validate();
122985             }
122986           };
122987
122988           return mode;
122989         }
122990
122991         function behaviorLasso(context) {
122992           // use pointer events on supported platforms; fallback to mouse events
122993           var _pointerPrefix = 'PointerEvent' in window ? 'pointer' : 'mouse';
122994
122995           var behavior = function behavior(selection) {
122996             var lasso;
122997
122998             function pointerdown(d3_event) {
122999               var button = 0; // left
123000
123001               if (d3_event.button === button && d3_event.shiftKey === true) {
123002                 lasso = null;
123003                 select(window).on(_pointerPrefix + 'move.lasso', pointermove).on(_pointerPrefix + 'up.lasso', pointerup);
123004                 d3_event.stopPropagation();
123005               }
123006             }
123007
123008             function pointermove() {
123009               if (!lasso) {
123010                 lasso = uiLasso(context);
123011                 context.surface().call(lasso);
123012               }
123013
123014               lasso.p(context.map().mouse());
123015             }
123016
123017             function normalize(a, b) {
123018               return [[Math.min(a[0], b[0]), Math.min(a[1], b[1])], [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
123019             }
123020
123021             function lassoed() {
123022               if (!lasso) return [];
123023               var graph = context.graph();
123024               var limitToNodes;
123025
123026               if (context.map().editableDataEnabled(true
123027               /* skipZoomCheck */
123028               ) && context.map().isInWideSelection()) {
123029                 // only select from the visible nodes
123030                 limitToNodes = new Set(utilGetAllNodes(context.selectedIDs(), graph));
123031               } else if (!context.map().editableDataEnabled()) {
123032                 return [];
123033               }
123034
123035               var bounds = lasso.extent().map(context.projection.invert);
123036               var extent = geoExtent(normalize(bounds[0], bounds[1]));
123037               var intersects = context.history().intersects(extent).filter(function (entity) {
123038                 return entity.type === 'node' && (!limitToNodes || limitToNodes.has(entity)) && geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) && !context.features().isHidden(entity, graph, entity.geometry(graph));
123039               }); // sort the lassoed nodes as best we can
123040
123041               intersects.sort(function (node1, node2) {
123042                 var parents1 = graph.parentWays(node1);
123043                 var parents2 = graph.parentWays(node2);
123044
123045                 if (parents1.length && parents2.length) {
123046                   // both nodes are vertices
123047                   var sharedParents = utilArrayIntersection(parents1, parents2);
123048
123049                   if (sharedParents.length) {
123050                     var sharedParentNodes = sharedParents[0].nodes; // vertices are members of the same way; sort them in their listed order
123051
123052                     return sharedParentNodes.indexOf(node1.id) - sharedParentNodes.indexOf(node2.id);
123053                   } else {
123054                     // vertices do not share a way; group them by their respective parent ways
123055                     return parseFloat(parents1[0].id.slice(1)) - parseFloat(parents2[0].id.slice(1));
123056                   }
123057                 } else if (parents1.length || parents2.length) {
123058                   // only one node is a vertex; sort standalone points before vertices
123059                   return parents1.length - parents2.length;
123060                 } // both nodes are standalone points; sort left to right
123061
123062
123063                 return node1.loc[0] - node2.loc[0];
123064               });
123065               return intersects.map(function (entity) {
123066                 return entity.id;
123067               });
123068             }
123069
123070             function pointerup() {
123071               select(window).on(_pointerPrefix + 'move.lasso', null).on(_pointerPrefix + 'up.lasso', null);
123072               if (!lasso) return;
123073               var ids = lassoed();
123074               lasso.close();
123075
123076               if (ids.length) {
123077                 context.enter(modeSelect(context, ids));
123078               }
123079             }
123080
123081             selection.on(_pointerPrefix + 'down.lasso', pointerdown);
123082           };
123083
123084           behavior.off = function (selection) {
123085             selection.on(_pointerPrefix + 'down.lasso', null);
123086           };
123087
123088           return behavior;
123089         }
123090
123091         function modeBrowse(context) {
123092           var mode = {
123093             button: 'browse',
123094             id: 'browse',
123095             title: _t('modes.browse.title'),
123096             description: _t('modes.browse.description')
123097           };
123098           var sidebar;
123099
123100           var _selectBehavior;
123101
123102           var _behaviors = [];
123103
123104           mode.selectBehavior = function (val) {
123105             if (!arguments.length) return _selectBehavior;
123106             _selectBehavior = val;
123107             return mode;
123108           };
123109
123110           mode.enter = function () {
123111             if (!_behaviors.length) {
123112               if (!_selectBehavior) _selectBehavior = behaviorSelect(context);
123113               _behaviors = [behaviorPaste(context), behaviorHover(context).on('hover', context.ui().sidebar.hover), _selectBehavior, behaviorLasso(context), modeDragNode(context).behavior, modeDragNote(context).behavior];
123114             }
123115
123116             _behaviors.forEach(context.install); // Get focus on the body.
123117
123118
123119             if (document.activeElement && document.activeElement.blur) {
123120               document.activeElement.blur();
123121             }
123122
123123             if (sidebar) {
123124               context.ui().sidebar.show(sidebar);
123125             } else {
123126               context.ui().sidebar.select(null);
123127             }
123128           };
123129
123130           mode.exit = function () {
123131             context.ui().sidebar.hover.cancel();
123132
123133             _behaviors.forEach(context.uninstall);
123134
123135             if (sidebar) {
123136               context.ui().sidebar.hide();
123137             }
123138           };
123139
123140           mode.sidebar = function (_) {
123141             if (!arguments.length) return sidebar;
123142             sidebar = _;
123143             return mode;
123144           };
123145
123146           mode.operations = function () {
123147             return [operationPaste(context)];
123148           };
123149
123150           return mode;
123151         }
123152
123153         function behaviorAddWay(context) {
123154           var dispatch = dispatch$8('start', 'startFromWay', 'startFromNode');
123155           var draw = behaviorDraw(context);
123156
123157           function behavior(surface) {
123158             draw.on('click', function () {
123159               dispatch.apply('start', this, arguments);
123160             }).on('clickWay', function () {
123161               dispatch.apply('startFromWay', this, arguments);
123162             }).on('clickNode', function () {
123163               dispatch.apply('startFromNode', this, arguments);
123164             }).on('cancel', behavior.cancel).on('finish', behavior.cancel);
123165             context.map().dblclickZoomEnable(false);
123166             surface.call(draw);
123167           }
123168
123169           behavior.off = function (surface) {
123170             surface.call(draw.off);
123171           };
123172
123173           behavior.cancel = function () {
123174             window.setTimeout(function () {
123175               context.map().dblclickZoomEnable(true);
123176             }, 1000);
123177             context.enter(modeBrowse(context));
123178           };
123179
123180           return utilRebind(behavior, dispatch, 'on');
123181         }
123182
123183         function behaviorHash(context) {
123184           // cached window.location.hash
123185           var _cachedHash = null; // allowable latitude range
123186
123187           var _latitudeLimit = 90 - 1e-8;
123188
123189           function computedHashParameters() {
123190             var map = context.map();
123191             var center = map.center();
123192             var zoom = map.zoom();
123193             var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
123194             var oldParams = utilObjectOmit(utilStringQs(window.location.hash), ['comment', 'source', 'hashtags', 'walkthrough']);
123195             var newParams = {};
123196             delete oldParams.id;
123197             var selected = context.selectedIDs().filter(function (id) {
123198               return context.hasEntity(id);
123199             });
123200
123201             if (selected.length) {
123202               newParams.id = selected.join(',');
123203             }
123204
123205             newParams.map = zoom.toFixed(2) + '/' + center[1].toFixed(precision) + '/' + center[0].toFixed(precision);
123206             return Object.assign(oldParams, newParams);
123207           }
123208
123209           function computedHash() {
123210             return '#' + utilQsString(computedHashParameters(), true);
123211           }
123212
123213           function computedTitle(includeChangeCount) {
123214             var baseTitle = context.documentTitleBase() || 'iD';
123215             var contextual;
123216             var changeCount;
123217             var titleID;
123218             var selected = context.selectedIDs().filter(function (id) {
123219               return context.hasEntity(id);
123220             });
123221
123222             if (selected.length) {
123223               var firstLabel = utilDisplayLabel(context.entity(selected[0]), context.graph());
123224
123225               if (selected.length > 1) {
123226                 contextual = _t('title.labeled_and_more', {
123227                   labeled: firstLabel,
123228                   count: selected.length - 1
123229                 });
123230               } else {
123231                 contextual = firstLabel;
123232               }
123233
123234               titleID = 'context';
123235             }
123236
123237             if (includeChangeCount) {
123238               changeCount = context.history().difference().summary().length;
123239
123240               if (changeCount > 0) {
123241                 titleID = contextual ? 'changes_context' : 'changes';
123242               }
123243             }
123244
123245             if (titleID) {
123246               return _t('title.format.' + titleID, {
123247                 changes: changeCount,
123248                 base: baseTitle,
123249                 context: contextual
123250               });
123251             }
123252
123253             return baseTitle;
123254           }
123255
123256           function updateTitle(includeChangeCount) {
123257             if (!context.setsDocumentTitle()) return;
123258             var newTitle = computedTitle(includeChangeCount);
123259
123260             if (document.title !== newTitle) {
123261               document.title = newTitle;
123262             }
123263           }
123264
123265           function updateHashIfNeeded() {
123266             if (context.inIntro()) return;
123267             var latestHash = computedHash();
123268
123269             if (_cachedHash !== latestHash) {
123270               _cachedHash = latestHash; // Update the URL hash without affecting the browser navigation stack,
123271               // though unavoidably creating a browser history entry
123272
123273               window.history.replaceState(null, computedTitle(false
123274               /* includeChangeCount */
123275               ), latestHash); // set the title we want displayed for the browser tab/window
123276
123277               updateTitle(true
123278               /* includeChangeCount */
123279               );
123280             }
123281           }
123282
123283           var _throttledUpdate = throttle(updateHashIfNeeded, 500);
123284
123285           var _throttledUpdateTitle = throttle(function () {
123286             updateTitle(true
123287             /* includeChangeCount */
123288             );
123289           }, 500);
123290
123291           function hashchange() {
123292             // ignore spurious hashchange events
123293             if (window.location.hash === _cachedHash) return;
123294             _cachedHash = window.location.hash;
123295             var q = utilStringQs(_cachedHash);
123296             var mapArgs = (q.map || '').split('/').map(Number);
123297
123298             if (mapArgs.length < 3 || mapArgs.some(isNaN)) {
123299               // replace bogus hash
123300               updateHashIfNeeded();
123301             } else {
123302               // don't update if the new hash already reflects the state of iD
123303               if (_cachedHash === computedHash()) return;
123304               var mode = context.mode();
123305               context.map().centerZoom([mapArgs[2], Math.min(_latitudeLimit, Math.max(-_latitudeLimit, mapArgs[1]))], mapArgs[0]);
123306
123307               if (q.id && mode) {
123308                 var ids = q.id.split(',').filter(function (id) {
123309                   return context.hasEntity(id);
123310                 });
123311
123312                 if (ids.length && (mode.id === 'browse' || mode.id === 'select' && !utilArrayIdentical(mode.selectedIDs(), ids))) {
123313                   context.enter(modeSelect(context, ids));
123314                   return;
123315                 }
123316               }
123317
123318               var center = context.map().center();
123319               var dist = geoSphericalDistance(center, [mapArgs[2], mapArgs[1]]);
123320               var maxdist = 500; // Don't allow the hash location to change too much while drawing
123321               // This can happen if the user accidentally hit the back button.  #3996
123322
123323               if (mode && mode.id.match(/^draw/) !== null && dist > maxdist) {
123324                 context.enter(modeBrowse(context));
123325                 return;
123326               }
123327             }
123328           }
123329
123330           function behavior() {
123331             context.map().on('move.behaviorHash', _throttledUpdate);
123332             context.history().on('change.behaviorHash', _throttledUpdateTitle);
123333             context.on('enter.behaviorHash', _throttledUpdate);
123334             select(window).on('hashchange.behaviorHash', hashchange);
123335
123336             if (window.location.hash) {
123337               var q = utilStringQs(window.location.hash);
123338
123339               if (q.id) {
123340                 //if (!context.history().hasRestorableChanges()) {
123341                 // targeting specific features: download, select, and zoom to them
123342                 context.zoomToEntity(q.id.split(',')[0], !q.map); //}
123343               }
123344
123345               if (q.walkthrough === 'true') {
123346                 behavior.startWalkthrough = true;
123347               }
123348
123349               if (q.map) {
123350                 behavior.hadHash = true;
123351               }
123352
123353               hashchange();
123354               updateTitle(false);
123355             }
123356           }
123357
123358           behavior.off = function () {
123359             _throttledUpdate.cancel();
123360
123361             _throttledUpdateTitle.cancel();
123362
123363             context.map().on('move.behaviorHash', null);
123364             context.on('enter.behaviorHash', null);
123365             select(window).on('hashchange.behaviorHash', null);
123366             window.location.hash = '';
123367           };
123368
123369           return behavior;
123370         }
123371
123372         // This is only done in testing because of the performance penalty.
123373
123374         var debug = false; // Reexport just what our tests use, see #4379
123375         var d3 = {
123376           dispatch: dispatch$8,
123377           geoMercator: mercator,
123378           geoProjection: projection,
123379           polygonArea: d3_polygonArea,
123380           polygonCentroid: d3_polygonCentroid,
123381           select: select,
123382           selectAll: selectAll,
123383           timerFlush: timerFlush
123384         };
123385
123386         var iD = /*#__PURE__*/Object.freeze({
123387                 __proto__: null,
123388                 debug: debug,
123389                 d3: d3,
123390                 actionAddEntity: actionAddEntity,
123391                 actionAddMember: actionAddMember,
123392                 actionAddMidpoint: actionAddMidpoint,
123393                 actionAddVertex: actionAddVertex,
123394                 actionChangeMember: actionChangeMember,
123395                 actionChangePreset: actionChangePreset,
123396                 actionChangeTags: actionChangeTags,
123397                 actionCircularize: actionCircularize,
123398                 actionConnect: actionConnect,
123399                 actionCopyEntities: actionCopyEntities,
123400                 actionDeleteMember: actionDeleteMember,
123401                 actionDeleteMultiple: actionDeleteMultiple,
123402                 actionDeleteNode: actionDeleteNode,
123403                 actionDeleteRelation: actionDeleteRelation,
123404                 actionDeleteWay: actionDeleteWay,
123405                 actionDiscardTags: actionDiscardTags,
123406                 actionDisconnect: actionDisconnect,
123407                 actionExtract: actionExtract,
123408                 actionJoin: actionJoin,
123409                 actionMerge: actionMerge,
123410                 actionMergeNodes: actionMergeNodes,
123411                 actionMergePolygon: actionMergePolygon,
123412                 actionMergeRemoteChanges: actionMergeRemoteChanges,
123413                 actionMove: actionMove,
123414                 actionMoveMember: actionMoveMember,
123415                 actionMoveNode: actionMoveNode,
123416                 actionNoop: actionNoop,
123417                 actionOrthogonalize: actionOrthogonalize,
123418                 actionRestrictTurn: actionRestrictTurn,
123419                 actionReverse: actionReverse,
123420                 actionRevert: actionRevert,
123421                 actionRotate: actionRotate,
123422                 actionScale: actionScale,
123423                 actionSplit: actionSplit,
123424                 actionStraightenNodes: actionStraightenNodes,
123425                 actionStraightenWay: actionStraightenWay,
123426                 actionUnrestrictTurn: actionUnrestrictTurn,
123427                 actionReflect: actionReflect,
123428                 actionUpgradeTags: actionUpgradeTags,
123429                 behaviorAddWay: behaviorAddWay,
123430                 behaviorBreathe: behaviorBreathe,
123431                 behaviorDrag: behaviorDrag,
123432                 behaviorDrawWay: behaviorDrawWay,
123433                 behaviorDraw: behaviorDraw,
123434                 behaviorEdit: behaviorEdit,
123435                 behaviorHash: behaviorHash,
123436                 behaviorHover: behaviorHover,
123437                 behaviorLasso: behaviorLasso,
123438                 behaviorOperation: behaviorOperation,
123439                 behaviorPaste: behaviorPaste,
123440                 behaviorSelect: behaviorSelect,
123441                 coreContext: coreContext,
123442                 coreFileFetcher: coreFileFetcher,
123443                 fileFetcher: _mainFileFetcher,
123444                 coreDifference: coreDifference,
123445                 coreGraph: coreGraph,
123446                 coreHistory: coreHistory,
123447                 coreLocalizer: coreLocalizer,
123448                 t: _t,
123449                 localizer: _mainLocalizer,
123450                 coreLocations: coreLocations,
123451                 locationManager: _mainLocations,
123452                 prefs: corePreferences,
123453                 coreTree: coreTree,
123454                 coreUploader: coreUploader,
123455                 coreValidator: coreValidator,
123456                 geoExtent: geoExtent,
123457                 geoLatToMeters: geoLatToMeters,
123458                 geoLonToMeters: geoLonToMeters,
123459                 geoMetersToLat: geoMetersToLat,
123460                 geoMetersToLon: geoMetersToLon,
123461                 geoMetersToOffset: geoMetersToOffset,
123462                 geoOffsetToMeters: geoOffsetToMeters,
123463                 geoScaleToZoom: geoScaleToZoom,
123464                 geoSphericalClosestNode: geoSphericalClosestNode,
123465                 geoSphericalDistance: geoSphericalDistance,
123466                 geoZoomToScale: geoZoomToScale,
123467                 geoAngle: geoAngle,
123468                 geoChooseEdge: geoChooseEdge,
123469                 geoEdgeEqual: geoEdgeEqual,
123470                 geoGetSmallestSurroundingRectangle: geoGetSmallestSurroundingRectangle,
123471                 geoHasLineIntersections: geoHasLineIntersections,
123472                 geoHasSelfIntersections: geoHasSelfIntersections,
123473                 geoRotate: geoRotate,
123474                 geoLineIntersection: geoLineIntersection,
123475                 geoPathHasIntersections: geoPathHasIntersections,
123476                 geoPathIntersections: geoPathIntersections,
123477                 geoPathLength: geoPathLength,
123478                 geoPointInPolygon: geoPointInPolygon,
123479                 geoPolygonContainsPolygon: geoPolygonContainsPolygon,
123480                 geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
123481                 geoViewportEdge: geoViewportEdge,
123482                 geoRawMercator: geoRawMercator,
123483                 geoVecAdd: geoVecAdd,
123484                 geoVecAngle: geoVecAngle,
123485                 geoVecCross: geoVecCross,
123486                 geoVecDot: geoVecDot,
123487                 geoVecEqual: geoVecEqual,
123488                 geoVecFloor: geoVecFloor,
123489                 geoVecInterp: geoVecInterp,
123490                 geoVecLength: geoVecLength,
123491                 geoVecLengthSquare: geoVecLengthSquare,
123492                 geoVecNormalize: geoVecNormalize,
123493                 geoVecNormalizedDot: geoVecNormalizedDot,
123494                 geoVecProject: geoVecProject,
123495                 geoVecSubtract: geoVecSubtract,
123496                 geoVecScale: geoVecScale,
123497                 geoOrthoNormalizedDotProduct: geoOrthoNormalizedDotProduct,
123498                 geoOrthoCalcScore: geoOrthoCalcScore,
123499                 geoOrthoMaxOffsetAngle: geoOrthoMaxOffsetAngle,
123500                 geoOrthoCanOrthogonalize: geoOrthoCanOrthogonalize,
123501                 modeAddArea: modeAddArea,
123502                 modeAddLine: modeAddLine,
123503                 modeAddPoint: modeAddPoint,
123504                 modeAddNote: modeAddNote,
123505                 modeBrowse: modeBrowse,
123506                 modeDragNode: modeDragNode,
123507                 modeDragNote: modeDragNote,
123508                 modeDrawArea: modeDrawArea,
123509                 modeDrawLine: modeDrawLine,
123510                 modeMove: modeMove,
123511                 modeRotate: modeRotate,
123512                 modeSave: modeSave,
123513                 modeSelect: modeSelect,
123514                 modeSelectData: modeSelectData,
123515                 modeSelectError: modeSelectError,
123516                 modeSelectNote: modeSelectNote,
123517                 operationCircularize: operationCircularize,
123518                 operationContinue: operationContinue,
123519                 operationCopy: operationCopy,
123520                 operationDelete: operationDelete,
123521                 operationDisconnect: operationDisconnect,
123522                 operationDowngrade: operationDowngrade,
123523                 operationExtract: operationExtract,
123524                 operationMerge: operationMerge,
123525                 operationMove: operationMove,
123526                 operationOrthogonalize: operationOrthogonalize,
123527                 operationPaste: operationPaste,
123528                 operationReflectShort: operationReflectShort,
123529                 operationReflectLong: operationReflectLong,
123530                 operationReverse: operationReverse,
123531                 operationRotate: operationRotate,
123532                 operationSplit: operationSplit,
123533                 operationStraighten: operationStraighten,
123534                 osmChangeset: osmChangeset,
123535                 osmEntity: osmEntity,
123536                 osmNode: osmNode,
123537                 osmNote: osmNote,
123538                 osmRelation: osmRelation,
123539                 osmWay: osmWay,
123540                 QAItem: QAItem,
123541                 osmIntersection: osmIntersection,
123542                 osmTurn: osmTurn,
123543                 osmInferRestriction: osmInferRestriction,
123544                 osmLanes: osmLanes,
123545                 osmOldMultipolygonOuterMemberOfRelation: osmOldMultipolygonOuterMemberOfRelation,
123546                 osmIsOldMultipolygonOuterMember: osmIsOldMultipolygonOuterMember,
123547                 osmOldMultipolygonOuterMember: osmOldMultipolygonOuterMember,
123548                 osmJoinWays: osmJoinWays,
123549                 get osmAreaKeys () { return osmAreaKeys; },
123550                 osmSetAreaKeys: osmSetAreaKeys,
123551                 osmTagSuggestingArea: osmTagSuggestingArea,
123552                 get osmPointTags () { return osmPointTags; },
123553                 osmSetPointTags: osmSetPointTags,
123554                 get osmVertexTags () { return osmVertexTags; },
123555                 osmSetVertexTags: osmSetVertexTags,
123556                 osmNodeGeometriesForTags: osmNodeGeometriesForTags,
123557                 osmOneWayTags: osmOneWayTags,
123558                 osmPavedTags: osmPavedTags,
123559                 osmIsInterestingTag: osmIsInterestingTag,
123560                 osmRoutableHighwayTagValues: osmRoutableHighwayTagValues,
123561                 osmFlowingWaterwayTagValues: osmFlowingWaterwayTagValues,
123562                 osmRailwayTrackTagValues: osmRailwayTrackTagValues,
123563                 presetCategory: presetCategory,
123564                 presetCollection: presetCollection,
123565                 presetField: presetField,
123566                 presetPreset: presetPreset,
123567                 presetManager: _mainPresetIndex,
123568                 presetIndex: presetIndex,
123569                 rendererBackgroundSource: rendererBackgroundSource,
123570                 rendererBackground: rendererBackground,
123571                 rendererFeatures: rendererFeatures,
123572                 rendererMap: rendererMap,
123573                 rendererPhotos: rendererPhotos,
123574                 rendererTileLayer: rendererTileLayer,
123575                 services: services,
123576                 serviceKeepRight: serviceKeepRight,
123577                 serviceImproveOSM: serviceImproveOSM,
123578                 serviceOsmose: serviceOsmose,
123579                 serviceMapillary: serviceMapillary,
123580                 serviceMapRules: serviceMapRules,
123581                 serviceNominatim: serviceNominatim,
123582                 serviceNsi: serviceNsi,
123583                 serviceKartaview: serviceKartaview,
123584                 serviceOsm: serviceOsm,
123585                 serviceOsmWikibase: serviceOsmWikibase,
123586                 serviceStreetside: serviceStreetside,
123587                 serviceTaginfo: serviceTaginfo,
123588                 serviceVectorTile: serviceVectorTile,
123589                 serviceWikidata: serviceWikidata,
123590                 serviceWikipedia: serviceWikipedia,
123591                 svgAreas: svgAreas,
123592                 svgData: svgData,
123593                 svgDebug: svgDebug,
123594                 svgDefs: svgDefs,
123595                 svgKeepRight: svgKeepRight,
123596                 svgIcon: svgIcon,
123597                 svgGeolocate: svgGeolocate,
123598                 svgLabels: svgLabels,
123599                 svgLayers: svgLayers,
123600                 svgLines: svgLines,
123601                 svgMapillaryImages: svgMapillaryImages,
123602                 svgMapillarySigns: svgMapillarySigns,
123603                 svgMidpoints: svgMidpoints,
123604                 svgNotes: svgNotes,
123605                 svgMarkerSegments: svgMarkerSegments,
123606                 svgKartaviewImages: svgKartaviewImages,
123607                 svgOsm: svgOsm,
123608                 svgPassiveVertex: svgPassiveVertex,
123609                 svgPath: svgPath,
123610                 svgPointTransform: svgPointTransform,
123611                 svgPoints: svgPoints,
123612                 svgRelationMemberTags: svgRelationMemberTags,
123613                 svgSegmentWay: svgSegmentWay,
123614                 svgStreetside: svgStreetside,
123615                 svgTagClasses: svgTagClasses,
123616                 svgTagPattern: svgTagPattern,
123617                 svgTouch: svgTouch,
123618                 svgTurns: svgTurns,
123619                 svgVertices: svgVertices,
123620                 uiFieldDefaultCheck: uiFieldCheck,
123621                 uiFieldOnewayCheck: uiFieldCheck,
123622                 uiFieldCheck: uiFieldCheck,
123623                 uiFieldManyCombo: uiFieldCombo,
123624                 uiFieldMultiCombo: uiFieldCombo,
123625                 uiFieldNetworkCombo: uiFieldCombo,
123626                 uiFieldSemiCombo: uiFieldCombo,
123627                 uiFieldTypeCombo: uiFieldCombo,
123628                 uiFieldCombo: uiFieldCombo,
123629                 uiFieldUrl: uiFieldText,
123630                 uiFieldIdentifier: uiFieldText,
123631                 uiFieldNumber: uiFieldText,
123632                 uiFieldTel: uiFieldText,
123633                 uiFieldEmail: uiFieldText,
123634                 uiFieldText: uiFieldText,
123635                 uiFieldAccess: uiFieldAccess,
123636                 uiFieldAddress: uiFieldAddress,
123637                 uiFieldCycleway: uiFieldCycleway,
123638                 uiFieldLanes: uiFieldLanes,
123639                 uiFieldLocalized: uiFieldLocalized,
123640                 uiFieldRoadheight: uiFieldRoadheight,
123641                 uiFieldRoadspeed: uiFieldRoadspeed,
123642                 uiFieldStructureRadio: uiFieldRadio,
123643                 uiFieldRadio: uiFieldRadio,
123644                 uiFieldRestrictions: uiFieldRestrictions,
123645                 uiFieldTextarea: uiFieldTextarea,
123646                 uiFieldWikidata: uiFieldWikidata,
123647                 uiFieldWikipedia: uiFieldWikipedia,
123648                 uiFields: uiFields,
123649                 uiIntro: uiIntro,
123650                 uiPanelBackground: uiPanelBackground,
123651                 uiPanelHistory: uiPanelHistory,
123652                 uiPanelLocation: uiPanelLocation,
123653                 uiPanelMeasurement: uiPanelMeasurement,
123654                 uiInfoPanels: uiInfoPanels,
123655                 uiPaneBackground: uiPaneBackground,
123656                 uiPaneHelp: uiPaneHelp,
123657                 uiPaneIssues: uiPaneIssues,
123658                 uiPaneMapData: uiPaneMapData,
123659                 uiPanePreferences: uiPanePreferences,
123660                 uiSectionBackgroundDisplayOptions: uiSectionBackgroundDisplayOptions,
123661                 uiSectionBackgroundList: uiSectionBackgroundList,
123662                 uiSectionBackgroundOffset: uiSectionBackgroundOffset,
123663                 uiSectionChanges: uiSectionChanges,
123664                 uiSectionDataLayers: uiSectionDataLayers,
123665                 uiSectionEntityIssues: uiSectionEntityIssues,
123666                 uiSectionFeatureType: uiSectionFeatureType,
123667                 uiSectionMapFeatures: uiSectionMapFeatures,
123668                 uiSectionMapStyleOptions: uiSectionMapStyleOptions,
123669                 uiSectionOverlayList: uiSectionOverlayList,
123670                 uiSectionPhotoOverlays: uiSectionPhotoOverlays,
123671                 uiSectionPresetFields: uiSectionPresetFields,
123672                 uiSectionPrivacy: uiSectionPrivacy,
123673                 uiSectionRawMemberEditor: uiSectionRawMemberEditor,
123674                 uiSectionRawMembershipEditor: uiSectionRawMembershipEditor,
123675                 uiSectionRawTagEditor: uiSectionRawTagEditor,
123676                 uiSectionSelectionList: uiSectionSelectionList,
123677                 uiSectionValidationIssues: uiSectionValidationIssues,
123678                 uiSectionValidationOptions: uiSectionValidationOptions,
123679                 uiSectionValidationRules: uiSectionValidationRules,
123680                 uiSectionValidationStatus: uiSectionValidationStatus,
123681                 uiSettingsCustomBackground: uiSettingsCustomBackground,
123682                 uiSettingsCustomData: uiSettingsCustomData,
123683                 uiInit: uiInit,
123684                 uiAccount: uiAccount,
123685                 uiAttribution: uiAttribution,
123686                 uiChangesetEditor: uiChangesetEditor,
123687                 uiCmd: uiCmd,
123688                 uiCombobox: uiCombobox,
123689                 uiCommit: uiCommit,
123690                 uiCommitWarnings: uiCommitWarnings,
123691                 uiConfirm: uiConfirm,
123692                 uiConflicts: uiConflicts,
123693                 uiContributors: uiContributors,
123694                 uiCurtain: uiCurtain,
123695                 uiDataEditor: uiDataEditor,
123696                 uiDataHeader: uiDataHeader,
123697                 uiDisclosure: uiDisclosure,
123698                 uiEditMenu: uiEditMenu,
123699                 uiEntityEditor: uiEntityEditor,
123700                 uiFeatureInfo: uiFeatureInfo,
123701                 uiFeatureList: uiFeatureList,
123702                 uiField: uiField,
123703                 uiFieldHelp: uiFieldHelp,
123704                 uiFlash: uiFlash,
123705                 uiFormFields: uiFormFields,
123706                 uiFullScreen: uiFullScreen,
123707                 uiGeolocate: uiGeolocate,
123708                 uiImproveOsmComments: uiImproveOsmComments,
123709                 uiImproveOsmDetails: uiImproveOsmDetails,
123710                 uiImproveOsmEditor: uiImproveOsmEditor,
123711                 uiImproveOsmHeader: uiImproveOsmHeader,
123712                 uiInfo: uiInfo,
123713                 uiInspector: uiInspector,
123714                 uiIssuesInfo: uiIssuesInfo,
123715                 uiKeepRightDetails: uiKeepRightDetails,
123716                 uiKeepRightEditor: uiKeepRightEditor,
123717                 uiKeepRightHeader: uiKeepRightHeader,
123718                 uiLasso: uiLasso,
123719                 uiLoading: uiLoading,
123720                 uiMapInMap: uiMapInMap,
123721                 uiModal: uiModal,
123722                 uiNotice: uiNotice,
123723                 uiNoteComments: uiNoteComments,
123724                 uiNoteEditor: uiNoteEditor,
123725                 uiNoteHeader: uiNoteHeader,
123726                 uiNoteReport: uiNoteReport,
123727                 uiPopover: uiPopover,
123728                 uiPresetIcon: uiPresetIcon,
123729                 uiPresetList: uiPresetList,
123730                 uiRestore: uiRestore,
123731                 uiScale: uiScale,
123732                 uiSidebar: uiSidebar,
123733                 uiSourceSwitch: uiSourceSwitch,
123734                 uiSpinner: uiSpinner,
123735                 uiSplash: uiSplash,
123736                 uiStatus: uiStatus,
123737                 uiSuccess: uiSuccess,
123738                 uiTagReference: uiTagReference,
123739                 uiToggle: uiToggle,
123740                 uiTooltip: uiTooltip,
123741                 uiVersion: uiVersion,
123742                 uiViewOnOSM: uiViewOnOSM,
123743                 uiViewOnKeepRight: uiViewOnKeepRight,
123744                 uiZoom: uiZoom,
123745                 utilAesEncrypt: utilAesEncrypt,
123746                 utilAesDecrypt: utilAesDecrypt,
123747                 utilArrayChunk: utilArrayChunk,
123748                 utilArrayDifference: utilArrayDifference,
123749                 utilArrayFlatten: utilArrayFlatten,
123750                 utilArrayGroupBy: utilArrayGroupBy,
123751                 utilArrayIdentical: utilArrayIdentical,
123752                 utilArrayIntersection: utilArrayIntersection,
123753                 utilArrayUnion: utilArrayUnion,
123754                 utilArrayUniq: utilArrayUniq,
123755                 utilArrayUniqBy: utilArrayUniqBy,
123756                 utilAsyncMap: utilAsyncMap,
123757                 utilCleanTags: utilCleanTags,
123758                 utilCombinedTags: utilCombinedTags,
123759                 utilDeepMemberSelector: utilDeepMemberSelector,
123760                 utilDetect: utilDetect,
123761                 utilDisplayName: utilDisplayName,
123762                 utilDisplayNameForPath: utilDisplayNameForPath,
123763                 utilDisplayType: utilDisplayType,
123764                 utilDisplayLabel: utilDisplayLabel,
123765                 utilEntityRoot: utilEntityRoot,
123766                 utilEditDistance: utilEditDistance,
123767                 utilEntityAndDeepMemberIDs: utilEntityAndDeepMemberIDs,
123768                 utilEntityOrMemberSelector: utilEntityOrMemberSelector,
123769                 utilEntityOrDeepMemberSelector: utilEntityOrDeepMemberSelector,
123770                 utilEntitySelector: utilEntitySelector,
123771                 utilFastMouse: utilFastMouse,
123772                 utilFunctor: utilFunctor,
123773                 utilGetAllNodes: utilGetAllNodes,
123774                 utilGetSetValue: utilGetSetValue,
123775                 utilHashcode: utilHashcode,
123776                 utilHighlightEntities: utilHighlightEntities,
123777                 utilKeybinding: utilKeybinding,
123778                 utilNoAuto: utilNoAuto,
123779                 utilObjectOmit: utilObjectOmit,
123780                 utilCompareIDs: utilCompareIDs,
123781                 utilOldestID: utilOldestID,
123782                 utilPrefixCSSProperty: utilPrefixCSSProperty,
123783                 utilPrefixDOMProperty: utilPrefixDOMProperty,
123784                 utilQsString: utilQsString,
123785                 utilRebind: utilRebind,
123786                 utilSafeClassName: utilSafeClassName,
123787                 utilSetTransform: utilSetTransform,
123788                 utilSessionMutex: utilSessionMutex,
123789                 utilStringQs: utilStringQs,
123790                 utilTagDiff: utilTagDiff,
123791                 utilTagText: utilTagText,
123792                 utilTiler: utilTiler,
123793                 utilTotalExtent: utilTotalExtent,
123794                 utilTriggerEvent: utilTriggerEvent,
123795                 utilUnicodeCharsCount: utilUnicodeCharsCount,
123796                 utilUnicodeCharsTruncated: utilUnicodeCharsTruncated,
123797                 utilUniqueDomId: utilUniqueDomId,
123798                 utilWrap: utilWrap,
123799                 validationAlmostJunction: validationAlmostJunction,
123800                 validationCloseNodes: validationCloseNodes,
123801                 validationCrossingWays: validationCrossingWays,
123802                 validationDisconnectedWay: validationDisconnectedWay,
123803                 validationFormatting: validationFormatting,
123804                 validationHelpRequest: validationHelpRequest,
123805                 validationImpossibleOneway: validationImpossibleOneway,
123806                 validationIncompatibleSource: validationIncompatibleSource,
123807                 validationMaprules: validationMaprules,
123808                 validationMismatchedGeometry: validationMismatchedGeometry,
123809                 validationMissingRole: validationMissingRole,
123810                 validationMissingTag: validationMissingTag,
123811                 validationOutdatedTags: validationOutdatedTags,
123812                 validationPrivateData: validationPrivateData,
123813                 validationSuspiciousName: validationSuspiciousName,
123814                 validationUnsquareWay: validationUnsquareWay
123815         });
123816
123817         window.requestIdleCallback = window.requestIdleCallback || function (cb) {
123818           var start = Date.now();
123819           return window.requestAnimationFrame(function () {
123820             cb({
123821               didTimeout: false,
123822               timeRemaining: function timeRemaining() {
123823                 return Math.max(0, 50 - (Date.now() - start));
123824               }
123825             });
123826           });
123827         };
123828
123829         window.cancelIdleCallback = window.cancelIdleCallback || function (id) {
123830           window.cancelAnimationFrame(id);
123831         };
123832         window.iD = iD;
123833
123834 }());